<?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>DEV Community: Davide Del Papa</title>
    <description>The latest articles on DEV Community by Davide Del Papa (@davidedelpapa).</description>
    <link>https://dev.to/davidedelpapa</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%2F280018%2Fed530d51-2395-49e7-9ef3-16b2c69bfe4b.png</url>
      <title>DEV Community: Davide Del Papa</title>
      <link>https://dev.to/davidedelpapa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidedelpapa"/>
    <language>en</language>
    <item>
      <title>FreePascal/Lazarus and Rust Integration P.II</title>
      <dc:creator>Davide Del Papa</dc:creator>
      <pubDate>Thu, 29 Jan 2026 16:25:14 +0000</pubDate>
      <link>https://dev.to/davidedelpapa/freepascallazarus-and-rust-integration-pii-5dh1</link>
      <guid>https://dev.to/davidedelpapa/freepascallazarus-and-rust-integration-pii-5dh1</guid>
      <description>&lt;p&gt;In this installment we will see how to show something useful that integrates Rust + Lazarus/Free Pascal.&lt;/p&gt;

&lt;p&gt;All the code and more can be found in the &lt;a href="https://github.com/davidedelpapa/rust-lazarus-tutorial" rel="noopener noreferrer"&gt;linked repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple JSON &amp;lt;&amp;gt; MessagePack converter
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Rust Library
&lt;/h3&gt;

&lt;p&gt;We want to build a Rust library that handles the conversion between &lt;a href="https://www.json.org" rel="noopener noreferrer"&gt;JSON&lt;/a&gt; and &lt;a href="https://msgpack.org/" rel="noopener noreferrer"&gt;MessagePack&lt;/a&gt; (and viceversa). If you are new to MessagePack, think of it as a "compiled" binary JSON, a way to reduce JSON size bot in transmission and at rest. The problem with MessagePack is that, contrary to JSON, it is not human readable. That is where a JSON &amp;lt;&amp;gt; MessagePack converter could find its use case. So, let's build one!&lt;/p&gt;

&lt;p&gt;As for the Rust library, let's create a new lib such as:&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 jsonmplib &lt;span class="nt"&gt;--lib&lt;/span&gt;    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's add what we need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo add serde serde_json rmp-serde &lt;span class="nb"&gt;base64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's have a thought on what we need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A function to convert JSON to MP (MessagePack)&lt;/li&gt;
&lt;li&gt;A function to convert MP to JSON&lt;/li&gt;
&lt;li&gt;Data structures to pass around between Rust and Pascal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As MessagePack is a binary format, we will represent it with a struct that can hold a pointer to the binary data (bytes = &lt;code&gt;u8&lt;/code&gt;) as a C-style vector, and a dimension of the vector itself (least we read data that is not present in the vector).&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;#[repr(C)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;MpBuffer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;c_int&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;In this way we represent a nice old C-Style memory buffer.&lt;/p&gt;

&lt;p&gt;To free the buffer's memory we need a function that ca be called also over the fence, on Pascal's side:&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;#[unsafe(no_mangle)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;free_mpbuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MpBuffer&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="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="py"&gt;.data&lt;/span&gt;&lt;span class="nf"&gt;.is_null&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="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_raw_parts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="py"&gt;.data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="py"&gt;.len&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="py"&gt;.len&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;usize&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above, if the data pointer is not null we build a vector from "raw parts, i.e., pointer, length and capacity, and then drop it (remember it's an unsafe operation.) &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes capacity can be different from the length as the length is the dimension of the data, capacity is the reserved space fro the buffer, so that the actual dimension can grow up to take the whole vector capacity; for convenience we will set non-growing buffers (i.e., fixed space), so length and capacity are the same.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, onto the first function: convert JSON to MessagePack, saving it in the memory buffer. &lt;/p&gt;

&lt;p&gt;First we'll create an &lt;code&gt;empty()&lt;/code&gt; constructor for our &lt;code&gt;MpBuffer&lt;/code&gt;, so that we can create empty buffers to return when there's no JSON and on error:&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;impl&lt;/span&gt; &lt;span class="n"&gt;MpBuffer&lt;/span&gt; &lt;span class="p"&gt;{&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;empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;MpBuffer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;null_mut&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&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;Then, the actual conversion 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="nd"&gt;#[unsafe(no_mangle)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;json_to_msgpack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MpBuffer&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;json_ptr&lt;/span&gt;&lt;span class="nf"&gt;.is_null&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nn"&gt;MpBuffer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&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="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;CStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_ptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.to_str&lt;/span&gt;&lt;span class="p"&gt;()&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;json_str&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="c1"&gt;// Parse JSON&lt;/span&gt;
                &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;serde_json&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&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;json_str&lt;/span&gt;&lt;span class="p"&gt;)&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;value&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="c1"&gt;// Encode to MessagePack&lt;/span&gt;
                        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nf"&gt;to_vec&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;value&lt;/span&gt;&lt;span class="p"&gt;)&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;vec&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vec&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;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vec&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="nf"&gt;.as_mut_ptr&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

                                &lt;span class="c1"&gt;// Avoid dropping the Vec&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;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;forget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vec&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;c_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                                &lt;span class="n"&gt;MpBuffer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;c_len&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;_&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;MpBuffer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&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="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&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;MpBuffer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&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="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&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;MpBuffer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&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;The function is easy enough: we accept a C-style string (pointer) with the JSON, and we convert this to MessagePack, saving it in the buffer.&lt;/p&gt;

&lt;p&gt;The first thing we do is to return an empty buffer if the string is empty (pointer to null); then we try to construct the C-string form the pointer, matching the result: on error we return an empty &lt;code&gt;MpBuffer&lt;/code&gt; throughout the function.&lt;/p&gt;

&lt;p&gt;When we have our Cstring as &lt;code&gt;Ok&lt;/code&gt; value, we parse it as JSON, and once this is &lt;code&gt;Ok&lt;/code&gt; we encode it to a MessagePack &lt;code&gt;Vec&lt;/code&gt; and we get a pointer out of it, and its length (converted to c-Syle int, &lt;code&gt;c_int&lt;/code&gt;) to wrap it into the &lt;code&gt;MpBuffer&lt;/code&gt;. Finally, when we no longer need it, we do not drop the MessagePack &lt;code&gt;Vec&lt;/code&gt;; instead, we use &lt;code&gt;std::mem::forget&lt;/code&gt; to "deconstruct" it cleanly.&lt;/p&gt;

&lt;p&gt;As for the conversion back from MessagePack to JSON, the process is much easier, as we just return a C-style string (a pointer &lt;code&gt;c_char&lt;/code&gt;), so we do not need a memory buffer for it:&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;#[unsafe(no_mangle)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;msgpack_to_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&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;data&lt;/span&gt;&lt;span class="nf"&gt;.is_null&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nn"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;null_mut&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;slice&lt;/span&gt; &lt;span class="o"&gt;=&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;slice&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_raw_parts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;from_slice&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&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;slice&lt;/span&gt;&lt;span class="p"&gt;)&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;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;serde_json&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;to_string_pretty&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;value&lt;/span&gt;&lt;span class="p"&gt;)&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;json_str&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;CString&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;json_str&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_raw&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;_&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;ptr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;null_mut&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;_&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;ptr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;null_mut&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;In the above function we get the MessagePack as data and length, unpacking as to say, the &lt;code&gt;MpBuffer&lt;/code&gt; struct, so we can call it by literally unpacking the corresponding Pascal's record.&lt;/p&gt;

&lt;p&gt;We get a null pointer on an empty (or null) MessagePack, and throughout the function on error.&lt;/p&gt;

&lt;p&gt;For the actual conversion we get a slice from the raw parts of data and length of the memory buffer, and we use the &lt;code&gt;from_slice&lt;/code&gt; on it, to convert MessagePack to &lt;code&gt;serde_json&lt;/code&gt;'s &lt;code&gt;Value&lt;/code&gt;. If everything is &lt;code&gt;Ok&lt;/code&gt;, we prettify it and return it as a C-string, nice and easy.&lt;/p&gt;

&lt;p&gt;Once we have done with the basic functions, the final touch is to have a function that we'll call from Pascal in order to free the memory occupied by the c-strings in Rust:&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;#[unsafe(no_mangle)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;free_cstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&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="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="nf"&gt;.is_null&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="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;If you got the foregoing, this is almost trivial: we just wrap a &lt;code&gt;drop()&lt;/code&gt; on a &lt;code&gt;Cstring&lt;/code&gt; constructed "from raw" pointer to &lt;code&gt;c_char&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With these data structures and function,we have finished on Rust's side. &lt;br&gt;
Now, after building we can copy the resulting library to the usual places (here I'm on Linux, it must be copied to &lt;em&gt;/usr/lib/&lt;/em&gt;, on Windows it's sufficient to copy it at the root of the Lazarus project, near the .exe that will be produced):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo build &lt;span class="nt"&gt;--release&lt;/span&gt;
&lt;span class="nb"&gt;sudo cp &lt;/span&gt;target/release/libjsonmplib.so /usr/lib/libjsonmplib.so    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now pass the ball on Pascal's court to see how to handle this new library.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Pascal's side of things
&lt;/h3&gt;

&lt;p&gt;We will create a &lt;em&gt;simpledemo&lt;/em&gt; folder and a new Lazarus project select a &lt;code&gt;New.. Project/Simple Program&lt;/code&gt; called &lt;code&gt;jsonmpdemo&lt;/code&gt;. As usual, let's create first the .pas unit &lt;em&gt;jsonmplib.pas&lt;/em&gt; to interface with the Rust library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unit jsonmplib;

{$mode ObjFPC}{$H+}

interface

uses
  Classes, SysUtils;

type
  PMpBuffer = ^TMpBuffer;

  TMpBuffer = record
    Data: pbyte;
    len: longint;
  end;

function json_to_msgpack(jsonStr: pchar): TMpBuffer; cdecl; external 'libjsonmplib';

function msgpack_to_json(Data: pbyte; len: longint): pchar; cdecl; external 'libjsonmplib';

procedure free_mpbuffer(buf: TMpBuffer); cdecl; external 'libjsonmplib';

procedure free_cstring(str: pchar); cdecl; external 'libjsonmplib';

implementation

end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have followed the style we use in the first tutorial, this code shouldn't come with lots of surprises, but let's review it briefly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we create a &lt;code&gt;TMpBuffer&lt;/code&gt; record to map our Rust &lt;code&gt;MpBuffer&lt;/code&gt; struct, and a pointer for it (&lt;code&gt;PMpBuffer = ^TMpBuffer&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;after this, we map all of Rust's &lt;code&gt;extern C&lt;/code&gt; functions to Pascal ones with an &lt;code&gt;external 'libjsonmplib'&lt;/code&gt; for each. No implementation needed as the Rust library is the implementation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now as for some code to use the unit, inside the &lt;code&gt;jsonmpdemo.lpr&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program jsonmpdemo;

{$mode ObjFPC}{$H+}

uses
  jsonmplib, Classes, SysUtils;

var
  buf: TMpBuffer;
  jsonStr: PChar;
  msgpackStream: TMemoryStream;

begin
  // Convert JSON to MessagePack
  buf := json_to_msgpack(PChar('{"x":1,"y":2}'));

  if (buf.data &amp;lt;&amp;gt; nil) and (buf.len &amp;gt; 0) then
  begin
    msgpackStream := TMemoryStream.Create;
    try
      // Write MessagePack bytes to stream/file
      msgpackStream.WriteBuffer(buf.data^, buf.len);
      msgpackStream.SaveToFile('out.msgpack');
    finally
      msgpackStream.Free;
    end;
    free_mpbuffer(buf);   // Rust-allocated memory must be freed
  end
  else
    Writeln('ERROR: json_to_msgpack returned empty buffer.');

  // Now read from file back into a NEW stream
  msgpackStream := TMemoryStream.Create;
  try
    msgpackStream.LoadFromFile('out.msgpack');
    msgpackStream.Position := 0;

    // Convert MessagePack -&amp;gt; JSON
    jsonStr := msgpack_to_json(msgpackStream.Memory, msgpackStream.Size);

    if jsonStr &amp;lt;&amp;gt; nil then
    begin
      Writeln('Decoded JSON: ', jsonStr);
      free_cstring(jsonStr); // Rust-allocated memory must be freed
    end
    else
      Writeln('ERROR: msgpack_to_json returned NULL.');
  finally
    msgpackStream.Free;
  end;
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only "complication" here is that we're handling FPC's memory streams, as we need to handle MessagePack which of course is a binary stream.&lt;/p&gt;

&lt;p&gt;In the code above, we first create a  &lt;code&gt;TMpBuffer&lt;/code&gt; record using the function json_to_msgpack with a JSON object &lt;code&gt;{"x":1,"y":2}&lt;/code&gt; then we save the data (binary part) to a file, using a &lt;code&gt;TMemoryStream&lt;/code&gt; to handle the binary format, as said. We then free the streaming, so that the data is lost to the program, and so to prove that we can indeed write and read MessagePack to and from a file. For this reason we free also the record (which is kept in the Rust library's memory, so we use one of the function we prepared in Rust: &lt;code&gt;free_mpbuffer&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Reading back the lost data from the saved file is precisely what we do next: we allocate again the &lt;code&gt;TMemoryStream&lt;/code&gt; and we load it with bytes taken from the file we saved earlier. Then we use again the library to convert that byte stream into a JSON object with the function &lt;code&gt;msgpack_to_json&lt;/code&gt;, and show it to the user. After this we free again all memory, both in Rust and Lazarus.&lt;/p&gt;

&lt;p&gt;Once the program is compiled, the output is as expected:&lt;br&gt;
&lt;/p&gt;

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

Decoded JSON: &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"x"&lt;/span&gt;: 1,
  &lt;span class="s2"&gt;"y"&lt;/span&gt;: 2
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is even pretty printed (the original JSON object was not, remember?).&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced GUI
&lt;/h2&gt;

&lt;p&gt;Let's see if we can create a more interesting application out of this library. This time we create a &lt;code&gt;New.. Project/Application&lt;/code&gt; in Lazarus.&lt;/p&gt;

&lt;p&gt;We need to place graphical components on the main form here called &lt;code&gt;Form1&lt;/code&gt;. Take a look at this hierarchy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Form1: TForm1
  Panel1: TPanel (alTop)
    btnConvert: TButton (alLeft)
    btnReverse: TButton (alLeft)
    CheckBase64: TCheckBox (alLeft)
  Panel2: TPanel (alClient)
    Panel3: TPanel (alLeft)
      Label1: TLabel (alTop)
      Memo1: TMemo (alClient)
    Splitter1: TSplitter
    Panel4: TPanel (alClient)
      Label2: TLabel (alTop)
      Memo2: TMemo (alClient)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to replicate the parent/children structure with the same &lt;code&gt;component name: component type&lt;/code&gt; I used. In parentheses I placed also the &lt;code&gt;Align&lt;/code&gt; property to select. Maybe it's a naive way of creating layouts, but in Lazarus we can go far with nesting panels, splitters and the &lt;code&gt;Align&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;We can copy the &lt;em&gt;jsonmplib.pas&lt;/em&gt; we created in the simple app to interface with the Rust library, we don't need to reinvent the wheel here. and then connect the dots. &lt;/p&gt;

&lt;p&gt;Here's some code to get you going.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unit main;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
  jsonmplib;

type

  TDataFormat = (dfJSON, dfMsgPack);

  { TForm1 }

  TForm1 = class(TForm)
    btnConvert: TButton;
    btnReverse: TButton;
    CheckBase64: TCheckBox;
    Label1: TLabel;
    Label2: TLabel;
    Memo1: TMemo;
    Memo2: TMemo;
    Panel1: TPanel;
    Panel2: TPanel;
    Panel3: TPanel;
    Panel4: TPanel;
    Splitter1: TSplitter;
    procedure btnConvertClick(Sender: TObject);
    procedure btnReverseClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    FLeftFormat: TDataFormat;
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}


{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  FLeftFormat := dfJSON;  // left starts as JSON
  Label1.Caption := 'JSON';
  Label2.Caption := 'MessagePack';
end;

procedure TForm1.btnReverseClick(Sender: TObject);
var
  tmp: string;
begin
  // swap captions
  tmp := Label1.Caption;
  Label1.Caption := Label2.Caption;
  Label2.Caption := tmp;

  // swap memos visually
  tmp := Memo1.Text;
  Memo1.Text := Memo2.Text;
  Memo2.Text := tmp;

  // toggle the state
  if FLeftFormat = dfJSON then
    FLeftFormat := dfMsgPack
  else
    FLeftFormat := dfJSON;
end;

procedure TForm1.btnConvertClick(Sender: TObject);
var
  inp: string;
  outp: PChar;
  buf: TMpBuffer;
  ms: TMemoryStream;
begin
  inp := Memo1.Text;

  if FLeftFormat = dfJSON then
  begin
    // JSON -&amp;gt; MessagePack
    buf := json_to_msgpack(PChar(inp));
    try
      if (buf.Data &amp;lt;&amp;gt; nil) and (buf.len &amp;gt; 0) then
      begin
        ms := TMemoryStream.Create;
        try
          ms.WriteBuffer(buf.Data^, buf.len);
          ms.Position := 0;
          Memo2.Lines.Clear;
          Memo2.Lines.Add('(binary msgpack, ' + IntToStr(buf.len) + ' bytes)');
        finally
          ms.Free;
        end;
      end;
    finally
      free_mpbuffer(buf);
    end;
  end
  else
  begin
    // MessagePack -&amp;gt; JSON
    // Memo1 contains *text* describing MessagePack; in practice, this
    // will be raw binary loaded as hex or pasted, but for now assume raw bytes.
    {
      For now let's assume the user manually loads raw msgpack into Memo1.
      We need to fix this later on.
    }

    // Convert Memo1.Text to a byte buffer
    ms := TMemoryStream.Create;
    try
      ms.Write(PChar(inp)^, Length(inp));   // naive, for now
      outp := msgpack_to_json(ms.Memory, ms.Size);
      try
        if outp &amp;lt;&amp;gt; nil then
          Memo2.Text := outp;
      finally
        free_cstring(outp);
      end;
    finally
      ms.Free;
    end;
  end;
end;


end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code works, but it doesn't show anything on the MessagePack part, as we cannot really dump binary into the text memos as-is, nor can we switch and convert from MessagePack to JSON: the program in this state is not yet functional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going the Extra Mile: Handling Base64
&lt;/h2&gt;

&lt;p&gt;In the companion repository (and in the interface we used as layout) you can see an option to handle base64: we do not just signal that we can handle the binary data, we can actually use base64 to show this and even exchange MessagPack data with web APIs (which are incapable of dealing with binary as is, but love the base64 encoding of it).&lt;br&gt;
We added also a hex dump, so there's something to show for all the effort done when we are not using the base64.&lt;/p&gt;

&lt;p&gt;Refer to the &lt;code&gt;JSONMPConv/JMPC/&lt;/code&gt; folder in the companion repository.&lt;/p&gt;

&lt;p&gt;As usual, I hope this tutorial was useful for you, so if you want, leave a comment below.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>lazarus</category>
      <category>pascal</category>
      <category>ffi</category>
    </item>
    <item>
      <title>FreePascal/Lazarus and Rust Integration</title>
      <dc:creator>Davide Del Papa</dc:creator>
      <pubDate>Mon, 05 Jan 2026 13:38:54 +0000</pubDate>
      <link>https://dev.to/davidedelpapa/freepascallazarus-and-rust-integration-322i</link>
      <guid>https://dev.to/davidedelpapa/freepascallazarus-and-rust-integration-322i</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/davidedelpapa/rust-lazarus-tutorial" rel="noopener noreferrer"&gt;Code available on Github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Going thorugh the &lt;a href="https://www.tiobe.com/tiobe-index/" rel="noopener noreferrer"&gt;TIOBE Index&lt;/a&gt; we can find that constantly, in the top 10 of the most popular languages, one find that constantly there are some "old" languages that "refuse to die." Among those we find the Delphi/Object Pascal, at the moment of writing it's on the 9th position, or Visual Basic, at the 7th position. Instead, new languages, like Rust can be found more often than not, below the top 10 (at the moment of writing, Rust is on the 13th position, behind both Perl and Fortran). Be it far from trying to give reaons for the popularity of a language instead of another; may it be the sheer amount of codebases still mantained in those languages, or other reasons, the fact is that those languages are still in use.&lt;/p&gt;

&lt;p&gt;Seeing this I got thinking that maybe there is a potential benefit in talking about languages integration. So, why not integrate Rust and Pascal? In my case I'm presenting the &lt;a href="https://www.freepascal.org/" rel="noopener noreferrer"&gt;Free Pascal&lt;/a&gt; dialect, and the &lt;a href="https://www.lazarus-ide.org/" rel="noopener noreferrer"&gt;Lazarus IDE&lt;/a&gt; (because I'm biased over Open Source), but the code can be adapted easily to other Pascal dialects.&lt;/p&gt;

&lt;p&gt;This tutorial is split in two: in the first part I will present to you the "theory",a nd we will make up some contieved examples, and, while using Lazarus (which is a RAD IDE), we will concentrate on simple commandline Pascal applications (although in the companion Github repository there is an example of GUI usage). In the second part instead, we will produce a proper GUI application, with some real world usage, so stay tuned!&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello, World!
&lt;/h2&gt;

&lt;p&gt;Let's start with a sort of "hello world" integration: a simple Rust function that adds two numbers and a Pascal program that calls the function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rust Side
&lt;/h3&gt;

&lt;p&gt;On the Rust side, let's create a library to be used by the Pascal code, which we will call &lt;code&gt;rustlaz&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 rustlaz &lt;span class="nt"&gt;--lib&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;rustlaz &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; zed &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;I write &lt;code&gt;zed .&lt;/code&gt;, but you can write &lt;code&gt;hx .&lt;/code&gt;, &lt;code&gt;code .&lt;/code&gt;, or whichever editor you are using.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In &lt;em&gt;Cargo.toml&lt;/em&gt; make sure we compile a library:&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;[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;"cdylib"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While in &lt;em&gt;src/lib.rs&lt;/em&gt; we can create a dummy 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="nd"&gt;#[unsafe(no_mangle)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;add_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;#[unsafe(no_mangle)]&lt;/code&gt; will make sure that the function is ready to be called by an external language, and of course, the function itself must be &lt;code&gt;pub extern "C"&lt;/code&gt; to leverage C-style FFI (Foreign Function Integration).&lt;/p&gt;

&lt;p&gt;Now a build will give us a &lt;em&gt;.so&lt;/em&gt;, a &lt;em&gt;.dll&lt;/em&gt;, or a &lt;em&gt;.dylib&lt;/em&gt;, according to our system (Linux, Windows, o Mac).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo build &lt;span class="nt"&gt;--release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to copy the compiled library from &lt;em&gt;/target/release/&lt;/em&gt; into the root of the Lazarus project for a Windows system. In Linux instead, we need to copy it where the linker can see it, usually &lt;em&gt;/usr/lib/&lt;/em&gt;:&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;sudo cp &lt;/span&gt;target/release/librustlaz.so /usr/lib/librustlaz.so 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lazarus Side
&lt;/h3&gt;

&lt;p&gt;We start the Lazarus IDE and we select a &lt;code&gt;New.. Project/Simple Program&lt;/code&gt;. We can save it in the root of our project as &lt;em&gt;LazRust.lpi&lt;/em&gt;. In the companio Github repo this folder is called &lt;em&gt;lazrust/&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;At this point, before writing our program, we need to create a &lt;code&gt;New unit&lt;/code&gt; and save it as &lt;em&gt;RustLib.pas&lt;/em&gt; This unit will take care of integrating a C-style library interface, mapping it to Pascal functions.&lt;/p&gt;

&lt;p&gt;This is the actual content of the unit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;unit&lt;/span&gt; &lt;span class="n"&gt;RustLib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;{$mode ObjFPC}{$H+}&lt;/span&gt;

&lt;span class="k"&gt;interface&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt;
  &lt;span class="n"&gt;Classes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SysUtils&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;add_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;LongInt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;LongInt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;LongInt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;cdecl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="s"&gt;'librustlaz'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;implementation&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this we declare the interface of the function &lt;em&gt;add_numbers&lt;/em&gt; of our &lt;code&gt;external&lt;/code&gt; libray, so that we can use it in Lazarus freely. Seing how easy it is to call into freing functions in Pascal, no wonder it's a widespread and loved language.&lt;/p&gt;

&lt;p&gt;Now we can go back to our main program and use the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;program&lt;/span&gt; &lt;span class="n"&gt;LazRust&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt; &lt;span class="n"&gt;RustLib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="k"&gt;Writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Rust says 2 + 3 = '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;add_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once compiled (SHIFT+F9), we can launch the program on the command line and see the result:&lt;br&gt;
&lt;/p&gt;

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

Rust says 2 + 3 &lt;span class="o"&gt;=&lt;/span&gt; 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can even make a standard GUI program that uses the library and in the folder &lt;em&gt;LazRust2/&lt;/em&gt; you will find an example that leverages the events &lt;code&gt;onEditingDone&lt;/code&gt; of two edits to update a label. Feel free to take a look at the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Slightly More Complex Example
&lt;/h2&gt;

&lt;p&gt;We can complicatre a little the interface if we create a &lt;code&gt;Point&lt;/code&gt; struct and we pass it around between Rust and Free Pascal.&lt;/p&gt;

&lt;p&gt;In Rust, &lt;em&gt;rustlaz/src/lib.rs&lt;/em&gt;:&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="nn"&gt;os&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[repr(C)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[unsafe(no_mangle)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;move_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="py"&gt;.x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="py"&gt;.y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;dy&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;Now we have a struct and a function to handle that struct.&lt;br&gt;
We can compile it (release mode) and copy again the library wherever visible by Lazarus (see notes above).&lt;/p&gt;

&lt;p&gt;Now in lazarus again, we create a &lt;code&gt;New.. Project/Simple Program&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The RustLib unit must look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;unit&lt;/span&gt; &lt;span class="n"&gt;RustLib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;{$mode ObjFPC}{$H+}&lt;/span&gt;

&lt;span class="k"&gt;interface&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt;
  &lt;span class="n"&gt;Classes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SysUtils&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt;
  &lt;span class="n"&gt;TPoint&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;LongInt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;LongInt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;move_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TPoint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;LongInt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;LongInt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;TPoint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;cdecl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="s"&gt;'librustlaz'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;implementation&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this way we "reconstruct" the Rust struct interface mapping it to a Pascal record called &lt;code&gt;TPoint&lt;/code&gt;, and we link the FFI function to iterface with the &lt;code&gt;TPoint&lt;/code&gt; as it were a Rust struct. &lt;br&gt;
In this way, mapping one to one data structures and functions, we achieve 100% compatibility between the two languages.&lt;/p&gt;

&lt;p&gt;Now onto our &lt;em&gt;lazrust.lpr&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;program&lt;/span&gt; &lt;span class="n"&gt;lazrust&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt; &lt;span class="n"&gt;RustLib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt;
  &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TPoint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;P2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TPoint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;P2&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;move_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;Writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Original: ('&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&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;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&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="k"&gt;Writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Moved:    ('&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&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;P2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&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="k"&gt;end&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 code is easy enough; the usage in fact gets quite natural in Pascal.&lt;/p&gt;

&lt;p&gt;Once compiled (SHIFT+F9), we can launch the program on the command line and see that indeed we are able to pass a Pascal record as a struct to Rust, and get the Rust struct back, mapped onto a record.&lt;br&gt;
&lt;/p&gt;

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

Original: &lt;span class="o"&gt;(&lt;/span&gt;10, 20&lt;span class="o"&gt;)&lt;/span&gt;
Moved:    &lt;span class="o"&gt;(&lt;/span&gt;13, 18&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check the code in &lt;em&gt;lazrust3/&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Strings and Memory
&lt;/h2&gt;

&lt;p&gt;Our third example is more complex still, as it involves managing strings and memory from both Rust and Pascal sides, to avoid memory leaks and unsafe behavior.&lt;/p&gt;

&lt;p&gt;We start from Rust were we create a struct and a function that manipulates it (accepting that struct as a parameter, and returning a changed struct):&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="nn"&gt;ffi&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;CStr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CString&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;os&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[repr(C)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Person&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="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;office&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cd"&gt;/// Utility to convert &amp;amp;str to *mut c_char.&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;make_cstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;CString&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;s&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_raw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cd"&gt;/// Utility to convert *mut c_char to Rust String.&lt;/span&gt;
&lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;to_rust_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&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;ptr&lt;/span&gt;&lt;span class="nf"&gt;.is_null&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;String&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="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;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;CStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.to_string_lossy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.to_string&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="cd"&gt;/// Free CStrings.&lt;/span&gt;
&lt;span class="nd"&gt;#[unsafe(no_mangle)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;free_cstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&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;s&lt;/span&gt;&lt;span class="nf"&gt;.is_null&lt;/span&gt;&lt;span class="p"&gt;()&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="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="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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="nd"&gt;#[unsafe(no_mangle)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;verify_person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Person&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;to_rust_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="py"&gt;.name&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;office&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;to_rust_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="py"&gt;.office&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;phone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;to_rust_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="py"&gt;.phone&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Add "(verified)" to the name&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;new_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;format!&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"(verified)"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;Person&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="nf"&gt;make_cstring&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;new_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;office&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;make_cstring&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;office&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;make_cstring&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;phone&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="py"&gt;.age&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;Besides the &lt;code&gt;Person&lt;/code&gt; struct and the &lt;code&gt;verify_person()&lt;/code&gt; function, in the above code we see two utilities (one to convert CStrings, i.e. &lt;code&gt;*mut c_char&lt;/code&gt;, to Rust Strings, and one to create CStrings starting from &lt;code&gt;&amp;amp;str&lt;/code&gt;). &lt;br&gt;
We can see also a function to free a CString: we will call it from the Pascal side, so that Rust will properly free the allocated CStrings, and those memory spaces will not leak.&lt;/p&gt;

&lt;p&gt;Having seen the Rust side of things, let's go over the Pascal side. We create a projectt as usual, and we map the Rust library with the usual Pascal unit, but this time with a twist:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;unit&lt;/span&gt; &lt;span class="n"&gt;rustlib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;{$mode ObjFPC}{$H+}&lt;/span&gt;

&lt;span class="k"&gt;interface&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt;
  &lt;span class="n"&gt;Classes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SysUtils&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt;
  &lt;span class="n"&gt;PPerson&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;^&lt;/span&gt;&lt;span class="n"&gt;TPerson&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;TPerson&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;pchar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;office&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;pchar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;pchar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;longint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;verify_person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TPerson&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;TPerson&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;cdecl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="s"&gt;'librustlaz'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;free_cstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;pchar&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;longint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;cdecl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="s"&gt;'librustlaz'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;NewCString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;pchar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;implementation&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;NewCString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;pchar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt;
  &lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SizeInt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="n"&gt;Len&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// include null terminator
&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;StrAlloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;StrPLCopy&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="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, besides mapping the &lt;code&gt;Person&lt;/code&gt; struct with a &lt;code&gt;TPerson&lt;/code&gt; record, and besides exposing both the &lt;code&gt;verify_person()&lt;/code&gt; and the &lt;code&gt;free_cstring()&lt;/code&gt; functions, we have an utility in this unit as well: the function &lt;code&gt;NewCString()&lt;/code&gt;.&lt;br&gt;
This utility will allocate the memory needed for a string and copy it over to the caler: we will use it to initialized the CStrings inside the struct to pass over to Rust.&lt;/p&gt;

&lt;p&gt;Let's have a look at the actual program's code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;program&lt;/span&gt; &lt;span class="n"&gt;lazrust&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;uses&lt;/span&gt; &lt;span class="n"&gt;rustlib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SysUtils&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt;
  &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TPerson&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;begin&lt;/span&gt;

  &lt;span class="n"&gt;P&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="n"&gt;NewCString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'John Doe'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;office&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewCString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'IT'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewCString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'555-0101'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;28&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;P2&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;verify_person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;Writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Rust returned:'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;Writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'  name:   '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P2&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;Writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'  office: '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;office&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;Writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'  phone:  '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;Writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'  age:    '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Free Rust-allocated strings
&lt;/span&gt;  &lt;span class="n"&gt;free_cstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P2&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="n"&gt;free_cstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;office&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;free_cstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Free Pascal-allocated strings
&lt;/span&gt;  &lt;span class="n"&gt;StrDispose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&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="n"&gt;StrDispose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;office&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;StrDispose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A you can see, we allocate the strings in the Pascal record to pass over to Rust (we do so with the utility we created above). After we finish, we use the expose Rust function &lt;code&gt;free_cstring()&lt;/code&gt; to dispose of the allocated memory on the Rust side; however, we need to de-allocate the memory also on the Pascal's side: that can leak too.&lt;/p&gt;

&lt;p&gt;Admittedly, we have a lot of clean up to do, but it is so, because we cannot use strings managed entirely by Rust, nor can we use the corresponding strings managed entirely by Pascal. Since we are working on the interoperability of these two language, we have to clean up the used resources by ourselves, intead of relying on managed types.&lt;/p&gt;

&lt;p&gt;Other than the hygene nuissaces, that makes the code a tad more verbose, the interoperativity between the two languages seems really good.&lt;/p&gt;

&lt;p&gt;The above code can be found in the &lt;em&gt;lazrust4/&lt;/em&gt; folder.&lt;/p&gt;

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

&lt;p&gt;All in all the interfacing between Rust and Free Pascal goes really smooth. When facing the problem of renovating a whole legacy codebase, it is comforting to know that so much could be done by just re-writing and extending some key libraries with modern and secure Rust code. The possibilities are endless here. Not the least of them all is the fact that Lazarus can provide a way to create GUIs in an easy and time tested way: instead of chasing the chimera of a Rust only codebase, delegating some key features to other languages, sometimes is the smartest move available.&lt;/p&gt;

&lt;p&gt;Stay tuned for Part II of this mini series.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>lazarus</category>
      <category>pascal</category>
      <category>ffi</category>
    </item>
    <item>
      <title>Leptos + Tauri Tutorial</title>
      <dc:creator>Davide Del Papa</dc:creator>
      <pubDate>Sun, 01 Sep 2024 17:27:45 +0000</pubDate>
      <link>https://dev.to/davidedelpapa/leptos-tauri-tutorial-3k60</link>
      <guid>https://dev.to/davidedelpapa/leptos-tauri-tutorial-3k60</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@heftiba?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Toa Heftiba&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-pair-of-shoes-and-a-bag-on-the-ground-27qbz0So9js?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;, cropped&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Summer for me is over, and I realized it has been a long time since I posted my last blog. Lately, I've accepted a job which involves the programming on a very specific, proprietary and rather backward piece of software (innuendo intended), it's also a long time I have no fun programming.&lt;/p&gt;

&lt;p&gt;Bad, very bad: one should never forget that coding is fun. Let's remedy that.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is the &lt;a href="https://github.com/davidedelpapa/leptos-tauri" rel="noopener noreferrer"&gt;repo&lt;/a&gt; connected to the post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Isometric Rust for Your Stack
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Definitely skip this rant, and start reading from next section: &lt;strong&gt;Setup a basic Envronment&lt;/strong&gt;. I mean it: it's useless stuff for the sake of the tutorial. It's just me doing me stuff.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm not here to present &lt;a href="https://leptos.dev/" rel="noopener noreferrer"&gt;Leptos&lt;/a&gt; or &lt;a href="https://v2.tauri.app/" rel="noopener noreferrer"&gt;Tauri&lt;/a&gt;, for that, just clik the links, ask Goole, or ClaudePilotGPTWhateverLLama... I'm not even here to make just a tutorial on how to get the two working -- if you see &lt;a href="https://v2.tauri.app/start/frontend/leptos/" rel="noopener noreferrer"&gt;Tauri documentation on it&lt;/a&gt; is quite "terse," but still enough.&lt;/p&gt;

&lt;p&gt;What I want to do here is to give you a walkthough, a &lt;a href="https://github.com/davidedelpapa/leptos-tauri" rel="noopener noreferrer"&gt;repo&lt;/a&gt; you can copy from, and also sprinkle it all with some considerations of my own.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I did say to skip this stuff, now it's the moment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First consideration: forget about isometric Rust. It's true, with Leptos + Tauri you can achieve the goal of programming in Rust full-stack. that is, if you want to do just a Hello World program, you can do it entirely in Rust; but, let's face the truth: we cannot truly escape from JavaScript. JS is everywhere in the background, JS is present as glue to various moving parts of the stack. At the actual state of things, it's impossible to create some WASM functions and not have at least some JS snippets that call said WASM  functions. &lt;/p&gt;

&lt;p&gt;Anyway, why would you want to avoid JS? It's full of little, well-written JS libraries out there, ready to be integrated into our stack, so why not take advantage of this ecosystem, instead of re-inventing the wheel over and over again?&lt;/p&gt;

&lt;p&gt;Besides JavaScript there's HTML and CSS, let's not forget it. Leptos own &lt;code&gt;view!&lt;/code&gt; macro syntax mimicks HTML!&lt;/p&gt;

&lt;p&gt;That said, in this tutorial we will not pretend we live on a Rust moon and try to achieve &lt;em&gt;isometric&lt;/em&gt; Rust; instead, we will get down to earth and do things proper.&lt;/p&gt;

&lt;p&gt;Enugh ranting, let's begin!&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup a Basic Environment
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;To follow this part of the tutorial you can &lt;code&gt;git pull https://github.com/davidedelpapa/leptos-tauri.git&lt;/code&gt; and checkout this tag: &lt;code&gt;git checkout v1.1&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First the tools we will need:&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;trunk
cargo &lt;span class="nb"&gt;install &lt;/span&gt;leptosfmt &lt;span class="c"&gt;# optional, but useful&lt;/span&gt;
cargo &lt;span class="nb"&gt;install &lt;/span&gt;create-tauri-app
cargo &lt;span class="nb"&gt;install &lt;/span&gt;tauri-cli &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="s1"&gt;'^2.0.0-rc'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that for Tauri there are some dependencies to set, so &lt;a href="https://v2.tauri.app/guides/prerequisites/#linux" rel="noopener noreferrer"&gt;follow this guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's add the target &lt;code&gt;wasm32&lt;/code&gt; with &lt;code&gt;rustup&lt;/code&gt;, if not already done:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustup target add wasm32-unknown-unknown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's create the Tauri app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo create-tauri-app &lt;span class="nt"&gt;--rc&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; cargo &lt;span class="nt"&gt;-t&lt;/span&gt; leptos &lt;span class="nt"&gt;-y&lt;/span&gt; leptos-tauri &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;leptos-tauri
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will use Rust nightly, at least for this project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustup toolchain &lt;span class="nb"&gt;install &lt;/span&gt;nightly
rustup override &lt;span class="nb"&gt;set &lt;/span&gt;nightly 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last command must be done inside the project root to set it project wide, and leave stable Rust for all your other projects (to set it system-wide: &lt;code&gt;rustup default nightly&lt;/code&gt;, but I wouldn't recommend doing that).&lt;/p&gt;

&lt;p&gt;Now we can add our Leptos dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo add leptos &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;csr,nightly
cargo add console_error_panic_hook
cargo add console_log
cargo add log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first adds leptos with csr and nighlty features, the second adds &lt;code&gt;console_error_panic_hook&lt;/code&gt; which is useful in order to use the browser inspector and get some sensible Rust-like error messages (at least the lines that caused the error), instead of the default link to the wasm bundle and unhelpful messages.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;console_log&lt;/code&gt; is needed in order to log to the browser console.&lt;/p&gt;

&lt;p&gt;Now let's create all the additional files we need to make this work.&lt;/p&gt;

&lt;p&gt;The following is for the formatters. Inside the project root, let's add a &lt;em&gt;rustfmt.toml&lt;/em&gt; file, to set the correct edition:&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="c"&gt;# rustfmt.toml&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's add also a &lt;em&gt;rust-analyzer.toml&lt;/em&gt; that will help us to override the default &lt;code&gt;rustfmt&lt;/code&gt; and use &lt;code&gt;leptosfmt&lt;/code&gt; instead:&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="c"&gt;# rust-analyzer.toml&lt;/span&gt;
&lt;span class="nn"&gt;[rustfmt]&lt;/span&gt; 
&lt;span class="py"&gt;overrideCommand&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"leptosfmt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"--stdin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"--rustfmt"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FInally, let's configure &lt;code&gt;leptosfmt&lt;/code&gt; with the &lt;em&gt;&lt;code&gt;leptosfmt.toml&lt;/code&gt;&lt;/em&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="c"&gt;# leptosfmt.toml&lt;/span&gt;
&lt;span class="py"&gt;max_width&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt; &lt;span class="c"&gt;# Maximum line width&lt;/span&gt;
&lt;span class="py"&gt;tab_spaces&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="c"&gt;# Number of spaces per tab&lt;/span&gt;
&lt;span class="py"&gt;indentation_style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Auto"&lt;/span&gt; &lt;span class="c"&gt;# "Tabs", "Spaces" or "Auto"&lt;/span&gt;
&lt;span class="py"&gt;newline_style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Auto"&lt;/span&gt; &lt;span class="c"&gt;# "Unix", "Windows" or "Auto"&lt;/span&gt;
&lt;span class="py"&gt;attr_value_brace_style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"WhenRequired"&lt;/span&gt; &lt;span class="c"&gt;# "Always", "AlwaysUnlessLit", "WhenRequired" or "Preserve"&lt;/span&gt;
&lt;span class="py"&gt;macro_names&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s"&gt;"leptos::view"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"view"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# Macro to be formatted by leptosfmt&lt;/span&gt;
&lt;span class="py"&gt;closing_tag_style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Preserve"&lt;/span&gt; &lt;span class="c"&gt;# "Preserve", "SelfClosing" or "NonSelfClosing"&lt;/span&gt;

&lt;span class="c"&gt;# Attribute values with custom formatters&lt;/span&gt;
&lt;span class="nn"&gt;[attr_values]&lt;/span&gt;
&lt;span class="py"&gt;class&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Tailwind"&lt;/span&gt; &lt;span class="c"&gt;# "Tailwind" is the only available formatter for now&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Noise. Enough with configuration files, let's do something in &lt;em&gt;src/main.rs&lt;/em&gt;. Tauri already created &lt;code&gt;main.rs&lt;/code&gt; and &lt;code&gt;app.rs&lt;/code&gt; for us, so we need to add few lines to &lt;em&gt;src/main.rs&lt;/em&gt;:&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="c1"&gt;// src/min.rs&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;app&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;app&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;use&lt;/span&gt; &lt;span class="nn"&gt;leptos&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;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="nn"&gt;console_error_panic_hook&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;set_once&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="nn"&gt;console_log&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;init_with_level&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;log&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Level&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;mount_to_body&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;view!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;App&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's explain the code a little bit, for those who are new with Leptos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We initialize &lt;code&gt;console_error_panic_hook&lt;/code&gt; with the &lt;code&gt;set_once()&lt;/code&gt; function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We also use &lt;code&gt;console_log::init_with_level()&lt;/code&gt; to correctly init the logging on the web browser console of any error&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;mount_to_body&lt;/code&gt; is a leptos function to mount a &lt;code&gt;IntoView&lt;/code&gt; type to the body of the page. In this case we pass it a function that returns  a &lt;code&gt;IntoView&lt;/code&gt; type through the &lt;code&gt;view!&lt;/code&gt; macro. This macro accepts HTML-like syntax, and in this case we pass to it a custom component that we need to create in the module &lt;code&gt;mod app&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we need to take care of said &lt;code&gt;App&lt;/code&gt; component inside &lt;em&gt;src/app.rs&lt;/em&gt; (already created by Tauri's template for us); replace all the content of the file with the following:&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="c1"&gt;// src/app.rs&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;leptos&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="nd"&gt;#[component]&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;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;IntoView&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;set_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;view!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&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;set_count&lt;/span&gt;&lt;span class="nf"&gt;.update&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&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="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"+1"&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&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;set_count&lt;/span&gt;&lt;span class="nf"&gt;.update&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&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="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"-1"&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"Counter: "&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;div&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;ul&gt;
&lt;li&gt;&lt;p&gt;At the heart, a component can be just a function that returns an &lt;code&gt;IntoView&lt;/code&gt; type, marked by &lt;code&gt;#[component]&lt;/code&gt;. The name of the function will be the name of the component, that is why we wrote it with a capitalized first letter (yes, it's a React-like style).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;At the beginning of our function, we set a signal, which is a reactive type, meaning that it can change during the WASM app lifecycle, and in turn make the component change because of it. We use &lt;code&gt;create_signal()&lt;/code&gt; which initializes a type given to it as parameter, and returns a getter and a setter for the reactive type thus created, in this case &lt;code&gt;count&lt;/code&gt; and &lt;code&gt;set_count&lt;/code&gt; respectively.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We then use the &lt;code&gt;view!&lt;/code&gt; macro which returns an &lt;code&gt;IntoView&lt;/code&gt;, and accets a HTML-like syntax mixed with Rust. We create a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; containing two &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; and a &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;. We can pass a &lt;code&gt;move&lt;/code&gt; closure to the  &lt;code&gt;on:click&lt;/code&gt; parameter of the button component, where we update the value in the signal we created earlier. We update the signal's value using the &lt;code&gt;update()&lt;/code&gt; function on the signal's setter. The &lt;code&gt;update()&lt;/code&gt; function accepts a closure where the parameter is the current value of the signal. With this method we creatd a button that increases the counter and a button to decrease it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside the &lt;code&gt;view!&lt;/code&gt; macro we also use the signal getter (simply &lt;code&gt;{count}&lt;/code&gt; for the rendering in &lt;code&gt;view!&lt;/code&gt;, but &lt;code&gt;count()&lt;/code&gt; if needed inside a closure). The getter will visualize the current value of the signal. Notice also that we conditionally assign a class to the &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; only if the value of the signal is less than 0, with the syntax &lt;code&gt;class:&amp;lt;value&amp;gt;=&amp;lt;move closure&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To render the &lt;code&gt;view!&lt;/code&gt; inside the &lt;code&gt;fn main()&lt;/code&gt; we decared that it will be mounted to the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; of the page, but which page? Tauri already created for us a &lt;em&gt;index.html&lt;/em&gt; file for it, so we dont need to worry; moreoer the template created also a &lt;em&gt;styles.css&lt;/em&gt; imported in the index. In this way, we just need to add the following style to the already created &lt;em&gt;styles.css&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Append this at the end of styles.css */&lt;/span&gt;
&lt;span class="nc"&gt;.red&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&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;This &lt;code&gt;.red&lt;/code&gt; CSS class will be condiionally assigned to the &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; inside our &lt;code&gt;&amp;lt;App&amp;gt;&lt;/code&gt; component as we saw earlier.&lt;/p&gt;

&lt;p&gt;Now if all went well, running &lt;code&gt;trunk&lt;/code&gt; should show our Leptos app inside our favorite browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;trunk serve &lt;span class="nt"&gt;--open&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that if the &lt;code&gt;--open&lt;/code&gt; flag does not work, it is sufficient to point the browser to &lt;code&gt;localhost:1420&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Back Tauri Integration
&lt;/h3&gt;

&lt;p&gt;We deleted everything in &lt;em&gt;src/app.rs&lt;/em&gt;, but in those lines there was also an example of Tauri integration. Now we can bring back our own integration code and understand things a little better, step by step.&lt;/p&gt;

&lt;p&gt;Presently the first thing we will do is to launch the tauri app proper with:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;With this we launched th app inside a desktop Tauri app, instead of the browser. Notice  that with &lt;code&gt;&amp;lt;ctrl&amp;gt;+&amp;lt;shift&amp;gt;+i&lt;/code&gt;  we have an inspector even in the tauri window... sweet!&lt;/p&gt;

&lt;p&gt;Now, let's take care of creating some Tauri integration, as said.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To follow this part of the tutorial you can checkout this tag: &lt;code&gt;git checkout v1.2&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When we used &lt;code&gt;cargo create-tauri-app&lt;/code&gt; the leptos template we used added a &lt;em&gt;src-tauri/&lt;/em&gt; folder we ignored so far. Inside this foder, we have a &lt;em&gt;src-tauri/main.rs&lt;/em&gt;  and a &lt;em&gt;src-tauri/lib.rs&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;em&gt;main.rs&lt;/em&gt; is minimal and it is used to basically call the &lt;code&gt;leptos_tauri_lib::run()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The  &lt;em&gt;src-tauri/lib.rs&lt;/em&gt; instead is where we can put some functions to be called by the leptos front-end.&lt;/p&gt;

&lt;p&gt;What we have already is the following:&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="c1"&gt;// src-tauri/lib.rs&lt;/span&gt;
&lt;span class="nd"&gt;#[tauri::command]&lt;/span&gt;
&lt;span class="k"&gt;fn&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, {}! You've been greeted from Rust!"&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="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[cfg_attr(mobile,&lt;/span&gt; &lt;span class="nd"&gt;tauri::mobile_entry_point)]&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;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;tauri&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Builder&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;.plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;tauri_plugin_shell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.invoke_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;tauri&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;generate_handler!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;tauri&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;generate_context!&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error while running tauri application"&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 have a custom &lt;code&gt;fn greet()&lt;/code&gt; that is a function annotated as a &lt;code&gt;#[tauri:command]&lt;/code&gt;. This function is passed to the &lt;code&gt;tauri::Builder&lt;/code&gt; in &lt;code&gt;fn run()&lt;/code&gt; by generating a &lt;code&gt;invoke_handler&lt;/code&gt;. Let's change this  file to have an &lt;code&gt;increase&lt;/code&gt; and &lt;code&gt;decrease&lt;/code&gt; command to use for the counter.&lt;/p&gt;

&lt;p&gt;This is the new &lt;em&gt;src-tauri/lib.rs&lt;/em&gt;:&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="c1"&gt;// src-tauri/lib.rs&lt;/span&gt;
&lt;span class="nd"&gt;#[tauri::command]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;increase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;count&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="nd"&gt;#[tauri::command]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;decrease&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;count&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="nd"&gt;#[cfg_attr(mobile,&lt;/span&gt; &lt;span class="nd"&gt;tauri::mobile_entry_point)]&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;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;tauri&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Builder&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;.plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;tauri_plugin_shell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.invoke_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;tauri&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;generate_handler!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;increase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decrease&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;tauri&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;generate_context!&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error while running tauri application"&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 you can see, we created two &lt;code&gt;tauri::command&lt;/code&gt; &lt;em&gt;increase&lt;/em&gt; and &lt;em&gt;decrease&lt;/em&gt;. Then, in the &lt;code&gt;tauri:Builder&lt;/code&gt; inside the &lt;code&gt;run()&lt;/code&gt; function (which is the main entry-point for the tauri app), we pass them to the &lt;code&gt;invoke_handler()&lt;/code&gt;; the rest is all boiler-plate.&lt;/p&gt;

&lt;p&gt;Back to our &lt;em&gt;src/app.rs&lt;/em&gt;, we need to let our &lt;em&gt;App&lt;/em&gt; component use these two functions (tauri commands).&lt;/p&gt;

&lt;p&gt;The first thing we need is to add the needed &lt;code&gt;use&lt;/code&gt; statements:&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="c1"&gt;// src/app.rs&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;leptos&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;use&lt;/span&gt; &lt;span class="nn"&gt;leptos&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;leptos_dom&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MouseEvent&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;serde&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Deserialize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Serialize&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;serde_wasm_bindgen&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;to_value&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;wasm_bindgen&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We added the &lt;code&gt;MouseEvent&lt;/code&gt; from &lt;code&gt;leptos::leptos_dom::ev::MouseEvent&lt;/code&gt;, which will let us handle the creation of a custom closure for the &lt;code&gt;on:click&lt;/code&gt; in our buttons.&lt;/p&gt;

&lt;p&gt;We imported &lt;code&gt;Deserialize&lt;/code&gt; and &lt;code&gt;Serialize&lt;/code&gt; from &lt;code&gt;serde&lt;/code&gt;, and &lt;code&gt;to_value&lt;/code&gt; from the &lt;code&gt;serde_wasm_bindgen&lt;/code&gt;, and of course the &lt;code&gt;wasm_bindgen&lt;/code&gt; itself, because we need to  pass arguments from the Rust frontend to the Tauri backend, passing through JavaScript (Remeber the rant I told you to skip? Just forget it already).&lt;/p&gt;

&lt;p&gt;Now, with an external call to the &lt;em&gt;wasm_bindgen&lt;/em&gt; we bind to a generic JavaScript function &lt;code&gt;invoke&lt;/code&gt; that is meant to call the Tauri commands:&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;#[wasm_bindgen]&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;#[wasm_bindgen(js_namespace&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"window"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"__TAURI__"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"core"&lt;/span&gt;&lt;span class="nd"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;JsValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;JsValue&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;At the end of the day, it's just boiler-plate to setup at the beginning of our components; then we can use this to bridge from the front-end to the back-end.&lt;/p&gt;

&lt;p&gt;Next, we create a struct to pass arguments to our Tauri commands:&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;#[derive(Serialize,&lt;/span&gt; &lt;span class="nd"&gt;Deserialize)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;CounterArgs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&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;The struct will be converted to a &lt;code&gt;JsValue&lt;/code&gt; by &lt;code&gt;serde&lt;/code&gt; and it's ready to be passed to the &lt;code&gt;invoke&lt;/code&gt; function as argument.&lt;/p&gt;

&lt;p&gt;Finall there's our &lt;em&gt;&lt;/em&gt; component. After the signal we need to create two closures to communicate with the Tauri commands. We will discuss just the &lt;em&gt;increase_me&lt;/em&gt;, but the considerations are valid for both closures:&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;let&lt;/span&gt; &lt;span class="n"&gt;increase_me&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="nf"&gt;.prevent_default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;spawn_local&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&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;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="nf"&gt;.get_untracked&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;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;to_value&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;CounterArgs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;count&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="n"&gt;new_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"increase"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="nf"&gt;.as_f64&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="n"&gt;set_count&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_value&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i32&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;In the closure we need to specify that the parameter &lt;code&gt;ev&lt;/code&gt; is a &lt;code&gt;MouseEvent&lt;/code&gt; type, so we can bind the closure to the &lt;code&gt;on:cick&lt;/code&gt; of our button.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;ev.prevent_default();&lt;/code&gt; we prevent the usual event behaviour, since we will provide our own behaviour. This is the same as the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault" rel="noopener noreferrer"&gt;Event: preventDefault() method - Web APIs | MDN&lt;/a&gt; in the Web API. It is particularly useful for closures that have to handle &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; fields.&lt;/p&gt;

&lt;p&gt;We then spawn a thread-local &lt;code&gt;Future&lt;/code&gt; with Leptos' &lt;code&gt;spawn_local()&lt;/code&gt;, providing an &lt;code&gt;async move&lt;/code&gt; closure. This is needed because when we use the &lt;code&gt;invoke&lt;/code&gt; bridge, it will return a &lt;code&gt;Future&lt;/code&gt;, that is a promise in JavaScript and &lt;code&gt;async&lt;/code&gt; in Rust. This is because the Tauri commands are syncronous.&lt;/p&gt;

&lt;p&gt;Inside the closure we get the count signal's value with &lt;code&gt;count.get_untracked()&lt;/code&gt;. We need the &lt;code&gt;get_untracked()&lt;/code&gt; because in this way we prevent the reactive binding that usually is produced with Leptos signals, so that even if the value in the &lt;code&gt;count&lt;/code&gt; changes, Leptos will not try to update the closure.&lt;/p&gt;

&lt;p&gt;We then create the argument to be passed to the &lt;code&gt;invoke&lt;/code&gt;. We use the &lt;code&gt;CounterArgs&lt;/code&gt; structure.&lt;/p&gt;

&lt;p&gt;We finally invoke the &lt;code&gt;increase&lt;/code&gt; command, and retrieve the new value for the counter, which we use to set the signal with its &lt;code&gt;set()&lt;/code&gt; provided method. Since the &lt;code&gt;wasm_bindgen::JsValue&lt;/code&gt; that gets returned by the &lt;code&gt;invoke&lt;/code&gt; bridge does not convert to integers, we need to convert it to &lt;code&gt;f64&lt;/code&gt; first, and then coherce it to a &lt;code&gt;i32&lt;/code&gt; value.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;FYI these are the conversions available for a &lt;code&gt;wasm_bindgen::JsValue&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;as_bool&lt;/code&gt; which returns an &lt;code&gt;Option&amp;lt;bool&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;as_f64&lt;/code&gt; which returns an &lt;code&gt;Option&amp;lt;f64&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;as_string&lt;/code&gt; which returns an &lt;code&gt;Option&amp;lt;String&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is the whole &lt;em&gt;src/app.rs&lt;/em&gt; 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="c1"&gt;// src/app.rs&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;leptos&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;leptos_dom&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MouseEvent&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;leptos&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;use&lt;/span&gt; &lt;span class="nn"&gt;serde&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Deserialize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Serialize&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;serde_wasm_bindgen&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;to_value&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;wasm_bindgen&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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="nd"&gt;#[wasm_bindgen]&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;#[wasm_bindgen(js_namespace&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"window"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"__TAURI__"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"core"&lt;/span&gt;&lt;span class="nd"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;JsValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;JsValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Serialize,&lt;/span&gt; &lt;span class="nd"&gt;Deserialize)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;CounterArgs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[component]&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;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;IntoView&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;set_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;increase_me&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="nf"&gt;.prevent_default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;spawn_local&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&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;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="nf"&gt;.get_untracked&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;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;to_value&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;CounterArgs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;count&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="n"&gt;new_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"increase"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="nf"&gt;.as_f64&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="n"&gt;set_count&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_value&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i32&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;let&lt;/span&gt; &lt;span class="n"&gt;decrease_me&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="nf"&gt;.prevent_default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;spawn_local&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&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;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="nf"&gt;.get_untracked&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;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;to_value&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;CounterArgs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;count&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="n"&gt;new_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"decrease"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="nf"&gt;.as_f64&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="n"&gt;set_count&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_value&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i32&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="nd"&gt;view!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;increase_me&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"+1"&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;decrease_me&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"-1"&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"Counter: "&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;div&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Now with a&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;We can appreciate our counter being increased or decrased as it was before, but using code from the back-end. &lt;/p&gt;

&lt;p&gt;Granted, it feels the same (there should not even be any appreciable decrease in speed), however this example can be adapted to do a whole deal more useful stuff in the back-end and present it on the front-end as needed. &lt;/p&gt;

&lt;p&gt;If you are still here, that means you have successfully glossed over all my rants and (maybe) finished the tutorial. Hope this has been instructive, feel free to comment below.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>tauri</category>
      <category>leptos</category>
      <category>webassembly</category>
    </item>
    <item>
      <title>Redis Hackathon Submission for Whatstore App</title>
      <dc:creator>Davide Del Papa</dc:creator>
      <pubDate>Sun, 28 Aug 2022 23:12:33 +0000</pubDate>
      <link>https://dev.to/davidedelpapa/redis-hackathon-submission-for-whatstore-app-25ol</link>
      <guid>https://dev.to/davidedelpapa/redis-hackathon-submission-for-whatstore-app-25ol</guid>
      <description>&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/davidedelpapa/whatstore"&gt;Link to the Repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Whatstore&lt;/em&gt; is an ecommerce store. However, this is no ordinary web-based store, &lt;em&gt;Whatstore&lt;/em&gt; is a chatbot based on Meta Whatsapp Business platform.&lt;/p&gt;

&lt;p&gt;This has been chosen because many people do not have (easy) access to a computer, or the possibility (and willingness) to browse for an e-commerce, even on mobile. Think for example at the elderly. Instead, many people know and use IM apps, such as Whatsapp, to communicate with friends and family. Many still save their local groceries, pharmacy, or pizza store phone numbers, and text them often to order their groceries. During the Covid 19 pandemic, this has been for many the best option to deal with the rules and needs of social distancing.&lt;/p&gt;

&lt;p&gt;However, many times the little stores are not able to attend all the customers by phone. This actually happened to me one evening, when I phoned four different pizza stores to try to get an order, and had to phone each repeatedly, until at last one of them attended me. This brought me to think that orders could be more efficient if we could just use a chatbot. But, where I am located not every grocery is even on socials, let alone have the funds or time necessary to set up such an interface. It came to my mind that everybody here around passes a lot of time answering to texts (and here around Whatsapp is the most used platform), so why not to take advantage of this? &lt;/p&gt;

&lt;p&gt;This is the spark that brought me to implement this project.&lt;br&gt;
For the project I actually created data for a fake pizza store, set in a touristic location nearby (where I actually am sure there are no pizza stores, just not to incur in some copyright violations). So when you install this app, you can actually start to order my favorite pizzas!&lt;/p&gt;
&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Microservice Mavens&lt;/p&gt;
&lt;h3&gt;
  
  
  Language Used
&lt;/h3&gt;

&lt;p&gt;Node.js&lt;/p&gt;
&lt;h3&gt;
  
  
  Link to Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davidedelpapa"&gt;
        davidedelpapa
      &lt;/a&gt; / &lt;a href="https://github.com/davidedelpapa/whatstore"&gt;
        whatstore
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Whatsapp Business Chat Store
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Whatstore&lt;/h1&gt;
&lt;p&gt;Whatsapp Business app to implement a chat-based e-commerce store&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/davidedelpapa/whatstorereadme_img/app_select_product_categories.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--INohnipX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/davidedelpapa/whatstorereadme_img/app_select_product_categories.png" alt="App: Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
How it works&lt;/h2&gt;
&lt;h3&gt;
How the data is stored:&lt;/h3&gt;
&lt;p&gt;Data is stored as JSON objects with the RedisJSON module.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The e-commerce data is stored in various keys
&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;store:info&lt;/code&gt; key holds all the info related to the store&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;product:*&lt;/code&gt; keys hold data for the products&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;category:*&lt;/code&gt; keys hold data for the products' categories&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;user:*&lt;/code&gt; keys hold information about the user-sessions, like the cart&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;purchase:*&lt;/code&gt; keys hold information about completed purchases&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
How the data is accessed:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Store info
&lt;ul&gt;
&lt;li&gt;Get store info: &lt;code&gt;JSON.GET store:info $&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Set store info: &lt;code&gt;JSON.SET store:info $ {store-info-objec}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Product info
&lt;ul&gt;
&lt;li&gt;Get product info: &lt;code&gt;JSON.GET product:{product-id} $&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Set product info: &lt;code&gt;JSON.SET product:{product-id} $ {product-info-objec}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Product category info
&lt;ul&gt;
&lt;li&gt;Get category info: &lt;code&gt;JSON.GET category:{category-id} $&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Set category info: &lt;code&gt;JSON.SET category:{category-id} $  {category-info-objec}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Get all categories: &lt;code&gt;KEYS category:*&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;User information
&lt;ul&gt;
&lt;li&gt;Get user info: &lt;code&gt;JSON.GET user:{user-phone-number} $&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Set user info: &lt;code&gt;JSON.SET user:{user-phone-number} $  {user-info-objec}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/davidedelpapa/whatstore"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;I'm using Node.js, NPM, &lt;a href="https://ngrok.com/"&gt;ngrok&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/express"&gt;express&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/whatsappcloudapi_wrapper"&gt;whatsappcloudapi_wrapper&lt;/a&gt;, as well as &lt;a href="https://www.npmjs.com/package/pdfkit"&gt;pdfkit&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/uuid"&gt;uuid&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/node-fetch"&gt;node-fetch v.2&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/loglevel"&gt;loglevel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And of course, &lt;a href="https://www.npmjs.com/package/redis"&gt;Redis&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/redis"&gt;RedisJSON&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the actual workflow of the app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First you need to ping the business number from you number, it does not matter what you write. It will answer with a choice to either view the products or to speak to a human.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wMI-MFpM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bhva4c4a7tpqoen26d0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wMI-MFpM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bhva4c4a7tpqoen26d0g.png" alt="App: Init Message" width="880" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you choose "Speak to a human" it sends a vCard for the customer care contact; otherwise the app will present to you the product categories choice.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---yeZOulq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2tkryj2q5psbxons4zne.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---yeZOulq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2tkryj2q5psbxons4zne.png" alt="App: Select Product Categories" width="880" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now you can choose a category and then be presented with a choice of products in that category.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qD9tjpkH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sfnphgm0dvszkadge8a8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qD9tjpkH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sfnphgm0dvszkadge8a8.png" alt="App: Select Product" width="548" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Here we selected the classic pizzas, and now we are going to select a "Salame(Pepperoni)"&lt;/li&gt;
&lt;li&gt;We are presented with the details of our selection, and we can now choose to add the product to the cart or browse for some more products. Let's add it to the cart.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MT-jwvAy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p8y5kl5ik4umn757pq1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MT-jwvAy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p8y5kl5ik4umn757pq1z.png" alt="App: Add to Cart" width="880" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can now review the cart, before checking out, or browse some more products to add. Let's review and checkout!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yjw8FnWs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lmeh8chpf0kiu1z1kcyz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yjw8FnWs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lmeh8chpf0kiu1z1kcyz.png" alt="App: Review Cart" width="880" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can also modify the cart before checkout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_FCQGJPp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3bi7c37m6g6v0oxx1wjg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_FCQGJPp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3bi7c37m6g6v0oxx1wjg.png" alt="App: checkout" width="745" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After checking out, the app notifies the seller of a new incoming order, and presents to the buyer some options to either again talk to a human or browse more products to shop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have accomplished our purchase!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On the seller side, the seller number gets notified of the incoming order, together with all the info needed to prepare the order. The seller has the possibility  to send the buyer a notification of when the order will be ready, or fulfill the order right away. Finally the seller can review all pending orders.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VwHjsHCq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zjr7ccgz9trz8nxxgnt4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VwHjsHCq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zjr7ccgz9trz8nxxgnt4.png" alt="App: Seller side" width="880" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---hhmOVK3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/92t82ppb493lo1u2vtvy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---hhmOVK3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/92t82ppb493lo1u2vtvy.png" alt="App: Seller side again" width="414" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At any time the seller can ping their app to check how many pending order are present and view each of them.&lt;/li&gt;
&lt;li&gt;Finally, when the order is fulfilled (ideally when the buyer comes to pick up the orders), the app saves the purchased order to the database as a purchase order. This could be used for statistics.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Collaborators
&lt;/h3&gt;

&lt;p&gt;Just me, &lt;a href="https://dev.to/davidedelpapa"&gt;davidedelpapa - Davide Del Papa&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>redishackathon</category>
    </item>
    <item>
      <title>Rust for Data Science: Tutorial 1</title>
      <dc:creator>Davide Del Papa</dc:creator>
      <pubDate>Tue, 24 Aug 2021 15:14:37 +0000</pubDate>
      <link>https://dev.to/davidedelpapa/rust-for-data-science-tutorial-1-4g5j</link>
      <guid>https://dev.to/davidedelpapa/rust-for-data-science-tutorial-1-4g5j</guid>
      <description>&lt;p&gt;[Photo by &lt;a href="https://unsplash.com/@jimgade?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;jim gade&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/sand?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;,&lt;br&gt;
  modified]&lt;br&gt;
Data Science: a branch of computer science that studies how to use, store, and analyze data in order to derive information from it.&lt;/p&gt;

&lt;p&gt;With this mini-series we are going to explore how to use some Rusty tools to accomplish the tasks that are the bread and butter of any Data Scientist.&lt;/p&gt;

&lt;p&gt;The final goal is to show that Rust can be employed in this field, and how so. Ultimately our goal is also to sparkle interest in this field of application: the author is persuaded that Rust should prove very useful in the field of Data Science (as well as Machine Learning and ultimately AI).&lt;/p&gt;

&lt;p&gt;You can find this article's code in the repo: &lt;a href="https://github.com/davidedelpapa/rdatascience-tut1" rel="noopener noreferrer"&gt;github.com/davidedelpapa/rdatascience-tut1&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting the stage for this tutorial
&lt;/h2&gt;

&lt;p&gt;There are few crates we are going to cover in this tutorial. However, we are going to introduce them as we go.&lt;/p&gt;

&lt;p&gt;Let's start our project the standard rusty way.&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 rdatascience-tut1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;rdatascience-tut1
cargo add ndarray ndarray-rand ndarray-stats noisy_float poloto
code &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am using currently &lt;code&gt;cargo add&lt;/code&gt; from the good &lt;a href="https://crates.io/crates/cargo-edit" rel="noopener noreferrer"&gt;cargo-edit&lt;/a&gt; (quick inst: &lt;code&gt;cargo install cargo-edit&lt;/code&gt;) to handle dependencies, and &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VisualStudio Code&lt;/a&gt; as dev IDE.&lt;/p&gt;

&lt;p&gt;Feel free to handle &lt;em&gt;Cargo.toml&lt;/em&gt; dependencies by hand, or use a different IDE.&lt;/p&gt;

&lt;h3&gt;
  
  
  ndarray: what is it, and why to use it?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/ndarray" rel="noopener noreferrer"&gt;ndarray&lt;/a&gt; is a Rust crate used to work with arrays. &lt;/p&gt;

&lt;p&gt;It covers all the classic uses of an array handling framework (such as &lt;code&gt;numpy&lt;/code&gt; for Python). Some use cases which are not covered by the main crate, are covered through some corollary crates, such as &lt;a href="https://crates.io/crates/ndarray-linalg" rel="noopener noreferrer"&gt;ndarray-linalg&lt;/a&gt; for linear algebra, &lt;a href="https://crates.io/crates/ndarray-rand" rel="noopener noreferrer"&gt;ndarray-rand&lt;/a&gt; to generate randomness, and &lt;a href="https://crates.io/crates/ndarray-stats" rel="noopener noreferrer"&gt;ndarray-stats&lt;/a&gt; for statistics.&lt;/p&gt;

&lt;p&gt;Additionally, &lt;code&gt;ndarray&lt;/code&gt; has got also some nice extra, such as support for &lt;a href="https://crates.io/crates/rayon" rel="noopener noreferrer"&gt;rayon&lt;/a&gt; for parallelization, or the popular &lt;a href="http://www.netlib.org/blas/" rel="noopener noreferrer"&gt;BLAS&lt;/a&gt; low-level specs, through one of the working back-ends (using &lt;a href="https://crates.io/crates/blas-src" rel="noopener noreferrer"&gt;blas-src&lt;/a&gt; ).&lt;/p&gt;

&lt;h4&gt;
  
  
  Why to use ndarray?
&lt;/h4&gt;

&lt;p&gt;In Rust there are already arrays (or lists), and also vectors, and the language itself allows for many different types of manipulation through powerful iterators.&lt;/p&gt;

&lt;p&gt;What is more, what is offered by the bare Rust language (enhanced by the &lt;code&gt;std&lt;/code&gt;) is many times even faster than other more popular languages; still, &lt;code&gt;ndarray&lt;/code&gt; is specialized to handle n-dimensional arrays with a mathematical end in view. &lt;/p&gt;

&lt;p&gt;Thus &lt;code&gt;ndarray&lt;/code&gt; builds over the power already provided by the language; Rust power is one of the reasons why the author is persuaded that Rust will be the language of Data Science in the next few years.&lt;/p&gt;

&lt;h2&gt;
  
  
  ndarray Quick-Start
&lt;/h2&gt;

&lt;p&gt;At the top of our &lt;em&gt;src/main.rs&lt;/em&gt; we are going to import as usual:&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;ndarray&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have almost everything we need in the prelude.&lt;/p&gt;

&lt;p&gt;We can start to put stuff inside the &lt;code&gt;fn main()&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Array creation
&lt;/h3&gt;

&lt;p&gt;Let's start to see how we can create arrays:&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;let&lt;/span&gt; &lt;span class="n"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;array!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.&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;"1D array: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arr1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ndarray&lt;/code&gt; provides the &lt;code&gt;array!&lt;/code&gt; macro that detects which type of &lt;code&gt;ArrayBase&lt;/code&gt; is needed. In this case this is a 1-D, that is, a one dimensional array. Notice that the underlying &lt;code&gt;ArrayBase&lt;/code&gt; already implements a &lt;code&gt;std::fmt::Display&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Compare it to the standard Rust array (let's call them &lt;em&gt;lists&lt;/em&gt; in order not to confuse them with &lt;code&gt;ndarray&lt;/code&gt;'s arrays) and Vec:&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="c1"&gt;// 1D array VS 1D array VS 1D Vec&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;array!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.&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;"1D array: &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;arr1&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;ls1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.&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;"1D list: &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;ls1&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;vec1&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="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.&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;"1D vector: &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;vec1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1D array:       [1, 2, 3, 4, 5, 6]
1D list:        [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
1D vector:      [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice too that &lt;code&gt;array!&lt;/code&gt; has written the floats as integers, since they are all &lt;code&gt;.0&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Array Sum
&lt;/h3&gt;

&lt;p&gt;Let's try to sum 2 arrays element by element:&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;let&lt;/span&gt; &lt;span class="n"&gt;arr2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;array!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.&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;arr3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;arr2&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;"1D array: &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;arr3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let see how it compares with standard arrays(lists) and vectors:&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;let&lt;/span&gt; &lt;span class="n"&gt;arr2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;array!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.&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;arr3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;arr2&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;"1D array: &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;arr3&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;ls2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.&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;ls3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ls1&lt;/span&gt;&lt;span class="nf"&gt;.clone&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;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;ls2&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="n"&gt;ls3&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ls1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ls2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&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;"1D list: &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;ls3&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;vec2&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="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.&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;vec3&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="nb"&gt;f64&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;vec1&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;.zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vec2&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;.map&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;e1&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;e2&lt;/span&gt;&lt;span class="p"&gt;)|&lt;/span&gt; &lt;span class="n"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;e2&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="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1D vec: &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;vec3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1D array:       [2, 4.2, 6.3, 8, 10, 12]
1D list:        [1.0, 4.2, 6.3, 8.0, 10.0, 12.0]
1D vec:         [2.0, 4.2, 6.3, 8.0, 10.0, 12.0]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, with Rust standard tools it became more complicated very soon. To perform an element by element sum we need a &lt;code&gt;for&lt;/code&gt; or (only for Vec) we need to use iterators, which are powerful, but very complicated to use in such a day-to-day Data Science scenario.&lt;/p&gt;

&lt;h2&gt;
  
  
  2D arrays &amp;amp; more
&lt;/h2&gt;

&lt;p&gt;let's just abandon quickly the examples using Rust's standard constructs, since as we have shown, they are more complex, and let us focus on &lt;code&gt;ndarray&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ndarray&lt;/code&gt; offers various methods to create and instantiate (and use) 2D arrays.&lt;/p&gt;

&lt;p&gt;Just look at this example:&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;let&lt;/span&gt; &lt;span class="n"&gt;arr4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;array!&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.&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;arr5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_elem&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mf"&gt;1.&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;arr6&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;arr5&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;"2D array:&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;arr6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with its output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2D array:
[[2, 3, 4],
 [5, 6, 7]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the macro &lt;code&gt;array!&lt;/code&gt; we need to specify all elements, while with &lt;code&gt;Array::from_elem&lt;/code&gt; we need to offer a &lt;code&gt;Shape&lt;/code&gt;, in this case &lt;code&gt;(2,1)&lt;/code&gt; and an element to fill the array, in this case &lt;code&gt;1.0&lt;/code&gt;: it will fill for us the whole shape with the selected element.&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;let&lt;/span&gt; &lt;span class="n"&gt;arr7&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&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="nf"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr6&lt;/span&gt;&lt;span class="nf"&gt;.raw_dim&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;arr8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr6&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;arr7&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;\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;arr8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[0, 0, 0],
 [0, 0, 0]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Array::zeros(Shape)&lt;/code&gt; creates an array of &lt;code&gt;Shape&lt;/code&gt; filled with zero's. &lt;/p&gt;

&lt;p&gt;Notice that sometimes the compiler cannot infer the type of zero to feed in (you almost forgot Rust has got a &lt;em&gt;nice&lt;/em&gt; type system, didn't you?), so we help it with the annotation &lt;code&gt;Array::&amp;lt;f64, _&amp;gt;&lt;/code&gt;, which gives the type, letting the compiler infer the shape (&lt;code&gt;_&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The function &lt;code&gt;.raw_dim()&lt;/code&gt;, as you can imagine, gives the shape of the matrix.&lt;/p&gt;

&lt;p&gt;Let's create an identity matrix now (a 2 dimensional array with all 0 but the diagonal)&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;let&lt;/span&gt; &lt;span class="n"&gt;identity&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;Array2&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f64&lt;/span&gt;&lt;span class="o"&gt;&amp;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="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;eye&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&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;\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;identity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[1, 0, 0],
 [0, 1, 0],
 [0, 0, 1]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We helped the compiler providing the shape and type, but this time using a specialized form of &lt;code&gt;ArrayBase&lt;/code&gt;, that is, &lt;code&gt;Array2&lt;/code&gt; that represents 2-dimensional arrays. Notice that we created a reference so that we can re-use the variable without incurring in the ire of the borrow checker (yes, always working, did you forget that as well?)&lt;/p&gt;

&lt;p&gt;Let's explore now the use of an identity matrix:&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;let&lt;/span&gt; &lt;span class="n"&gt;arr9&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;array!&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;8.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;9.&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;arr10&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;arr9&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;identity&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;\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;arr10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[1, 0, 0],
 [0, 5, 0],
 [0, 0, 9]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From my math classes I remember something like that the identity matrix should give back the same matrix when multiplied...&lt;/p&gt;

&lt;p&gt;Yes, of course, we are not doing &lt;em&gt;dot&lt;/em&gt; multiplications! With normal multiplication it does not work.&lt;/p&gt;

&lt;p&gt;In fact, when using matrices there is a element-wise multiplication, which is done by &lt;code&gt;arr9 * identity&lt;/code&gt;, but there's too a matrix multiplication, which is done by&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;let&lt;/span&gt; &lt;span class="n"&gt;arr11&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr9&lt;/span&gt;&lt;span class="nf"&gt;.dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;identity&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;\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;arr11&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which finally outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[1, 2, 3],
 [4, 5, 6],
 [7, 8, 9]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, &lt;code&gt;ndarray&lt;/code&gt; can handle also a 0-D array, with 0 meaning that it is just an element:&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;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;\n&lt;/span&gt;&lt;span class="s"&gt;{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;array!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;2.&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;"Dimensions: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;array!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.ndim&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which correctly outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[2]
Dimensions: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Likewise, we could go to 3D or more&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;let&lt;/span&gt; &lt;span class="n"&gt;arr12&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&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="nf"&gt;ones&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&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;\n&lt;/span&gt;&lt;span class="s"&gt;MULTIDIMENSIONAL&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;arr12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Guessed its output?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MULTIDIMENSIONAL
[[[[1, 1],
   [1, 1]],

  [[1, 1],
   [1, 1]],

  [[1, 1],
   [1, 1]]],


 [[[1, 1],
   [1, 1]],

  [[1, 1],
   [1, 1]],

  [[1, 1],
   [1, 1]]]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a 2-elements 2 vectors, repeated 3 times, repeated 2 times; just go from right to left to unpack it from smaller to bigger (and vice-versa).&lt;/p&gt;

&lt;p&gt;If it is still unclear, don't worry: we are here for the programming more than for the math/stats behind it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's add some randomness to the mess!
&lt;/h2&gt;

&lt;p&gt;We also loaded &lt;code&gt;ndarray-rand&lt;/code&gt; into our &lt;em&gt;Cargo.toml&lt;/em&gt;, which we briefly described earlier.&lt;/p&gt;

&lt;p&gt;This package adds the power of the &lt;a href="https://crates.io/crates/rand" rel="noopener noreferrer"&gt;rand&lt;/a&gt; crate (which it re-exports as sub-module) to your &lt;em&gt;ndarray ecosystem&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In order to see some examples, let's add the following in the &lt;code&gt;use&lt;/code&gt; section of our &lt;em&gt;src/main.rs&lt;/em&gt;&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;ndarray_rand&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;RandomExt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SamplingStrategy&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;ndarray_rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;rand_distr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Uniform&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we can get an array of shape &lt;code&gt;(5, 2)&lt;/code&gt;, for example, filled with a uniform distribution between 1 and 10 (floats, though):&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;let&lt;/span&gt; &lt;span class="n"&gt;arr13&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nn"&gt;Uniform&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="mf"&gt;0.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;10.&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;"{:5.2}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arr13&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which results, for example, in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[ 2.04,  0.15,  6.66,  3.06,  0.91],
 [ 8.18,  6.08,  6.99,  4.45,  5.27]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Results should vary at each run, being the distribution (pseudo)random.&lt;/p&gt;

&lt;p&gt;We can also &lt;em&gt;"pick"&lt;/em&gt; data from an array (sampling) in the following way:&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;let&lt;/span&gt; &lt;span class="n"&gt;arr14&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;array!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.&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;arr15&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr14&lt;/span&gt;&lt;span class="nf"&gt;.sample_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;SamplingStrategy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;WithoutReplacement&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;\n&lt;/span&gt;&lt;span class="s"&gt;Sampling from:&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;Two elements:&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;arr14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arr15&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which may result in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sampling from:  [1, 2, 3, 4, 5, 6]
Two elements:   [4, 2]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me show another way of sampling, which involves the use of the &lt;code&gt;rand&lt;/code&gt; crate and the creation of an array from a vector:&lt;/p&gt;

&lt;p&gt;We first need the following added to the &lt;code&gt;use&lt;/code&gt; section:&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;ndarray_rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;rand&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;rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;IteratorRandom&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we use the &lt;code&gt;rand&lt;/code&gt; crate as re-exported by &lt;code&gt;ndarray-rand&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we can do the following (example in the &lt;a href="https://rust-random.github.io/rand/rand/seq/trait.IteratorRandom.html" rel="noopener noreferrer"&gt;rand docs&lt;/a&gt;, adapted):&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;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;rng&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;thread_rng&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;faces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&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;arr16&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_shape_vec&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;faces&lt;/span&gt;&lt;span class="nf"&gt;.chars&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.choose_multiple&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;rng&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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="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;\n&lt;/span&gt;&lt;span class="s"&gt;Sampling from:&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;faces&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;"Elements:&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;arr16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We define the &lt;code&gt;thread_rng&lt;/code&gt; to be used first, then we set a string containing the emoji we want to select.&lt;/p&gt;

&lt;p&gt;Then we create an array from a vector, giving a shape. The shape we chose is &lt;code&gt;(2, 2)&lt;/code&gt;, but the vector is created using a particular &lt;code&gt;IteratorRandom&lt;/code&gt;, i.e., &lt;code&gt;choose_multiple&lt;/code&gt;, extracting 4 elements (chars) at random from the string.&lt;/p&gt;

&lt;p&gt;The output is obvious:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sampling from:  😀😎😐😕😠😢
Elements:
[[😀, 😎],
 [😢, 😠]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beware though not to over-sample, otherwise &lt;code&gt;choose_multiple&lt;/code&gt; will simply panic.&lt;br&gt;
Instead, &lt;code&gt;Array::from_shape_vec&lt;/code&gt; returns a &lt;code&gt;Result&lt;/code&gt; stating if it could create an array or not (Result which we simply unwrap).&lt;/p&gt;
&lt;h2&gt;
  
  
  Let's do some stats and visualize something, shall we?
&lt;/h2&gt;

&lt;p&gt;Before introducing visualization, let's introduce the crate &lt;a href="https://crates.io/crates/ndarray-stats" rel="noopener noreferrer"&gt;ndarray-stats&lt;/a&gt;, actually, also the crate &lt;a href="https://crates.io/crates/noisy_float" rel="noopener noreferrer"&gt;noisy_float&lt;/a&gt; which is a must when using &lt;code&gt;ndarray-stats&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First of all, we start with a Standard Normal Distribution, randomly created.&lt;/p&gt;

&lt;p&gt;First we add:&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;ndarray_rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;rand_distr&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Uniform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StandardNormal&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in its proper place, then:&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;let&lt;/span&gt; &lt;span class="n"&gt;arr17&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&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="nf"&gt;random_using&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;StandardNormal&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="nn"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;thread_rng&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way we have a 2D array with 10,000 couples of elements&lt;/p&gt;

&lt;p&gt;Then we add to the &lt;code&gt;use&lt;/code&gt; section also the imports we need to do statistics:&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;ndarray_stats&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HistogramExt&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;ndarray_stats&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;histogram&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="nn"&gt;strategies&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Sqrt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GridBuilder&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;noisy_float&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;types&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;N64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n64&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to transform each element from float into a noisy float; I will not go into explaining a noisy float, just consider it as a float that can't silently fail (be a &lt;code&gt;NaN&lt;/code&gt;); besides this way it is order-able, which is what is needed by &lt;code&gt;ndarray-stats&lt;/code&gt; to create an histogram.&lt;/p&gt;

&lt;p&gt;In order to perform by value an operation on each element of the ndarray, we will use the function &lt;code&gt;mapv()&lt;/code&gt; which is akin to the standard &lt;code&gt;map()&lt;/code&gt; for iterators.&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;let&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr17&lt;/span&gt;&lt;span class="nf"&gt;.mapv&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="nf"&gt;n64&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, we can create a grid for our histogram (a grid is needed to divide the data into bins); we try to infer the best way, using the &lt;code&gt;strategies::Sqrt&lt;/code&gt; (a strategy used by many programs, including MS Excel):&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;let&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;GridBuilder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Sqrt&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;N64&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="nf"&gt;from_array&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;data&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;.build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have a grid, that is, a way to divide our raw data to prepare our histogram, we can create such histogram:&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;let&lt;/span&gt; &lt;span class="n"&gt;histogram&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="nf"&gt;.histogram&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to get the underlying counts matrix, we can simply state:&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;let&lt;/span&gt; &lt;span class="n"&gt;histogram_matrix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;histogram&lt;/span&gt;&lt;span class="nf"&gt;.counts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The count matrix just states how many elements are present in each bin and each height, in the grid.&lt;/p&gt;

&lt;p&gt;Ok, now we have a histogram... but how could we visualize it?&lt;br&gt;
Well, before visualizing our data we should prepare it for visualization.&lt;/p&gt;

&lt;p&gt;The problem we face is that we have the counts of a grid, but to plot it we should really have a number of bin and all elements in that bin, meaning, we should sum vertically all elements.&lt;/p&gt;

&lt;p&gt;In order to do so, we need to sum on axis(0) of the ndarray:&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;let&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;histogram_matrix&lt;/span&gt;&lt;span class="nf"&gt;.sum_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have a 1D ndarray containing all the sums of the grid. At this point we can establish that each sum is a different bin, and enumerate them. We will transform it all to a vector of tuples, in order to prepare it for the visualization tool, where the first element of the tuple is the number of bin, and the second is the height of the bin.&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;let&lt;/span&gt; &lt;span class="n"&gt;his_data&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="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;f32&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;data&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;.enumerate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&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="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="p"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember: this is just a hoax dataset, based on a pseudorandom generator of a normal distribution (i.e., a Gaussian distribution centered in &lt;code&gt;0.0&lt;/code&gt;, with radius approx. &lt;code&gt;1&lt;/code&gt;). Still, we should see a rough Gaussian on a histogram.&lt;/p&gt;

&lt;h3&gt;
  
  
  DataViz
&lt;/h3&gt;

&lt;p&gt;In order to visualize things we will use &lt;a href="https://crates.io/crates/poloto" rel="noopener noreferrer"&gt;poloto&lt;/a&gt;, which is one of many plotting crates for Rust. &lt;/p&gt;

&lt;p&gt;It is a simple one, meaning we do not need many lines of code to have something to see on our screen.&lt;/p&gt;

&lt;p&gt;We will not import it in the &lt;code&gt;use&lt;/code&gt; section, because it is very simple. Let me explain how to plot a histogram in three steps:&lt;/p&gt;

&lt;p&gt;Step one - create a file to store our graph:&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;let&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&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;fs&lt;/span&gt;&lt;span class="p"&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;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"standard_normal_hist.svg"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step two - create a histogram out of the data:&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;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;poloto&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Histogram"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"y"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="nf"&gt;.histogram&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Stand.Norm.Dist."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;his_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.xmarker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.ymarker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create a &lt;code&gt;Plotter&lt;/code&gt; object, assigning it a title, and legend for each axis.&lt;br&gt;
Then, we plot our histogram on it, assigning the title in the legend (&lt;code&gt;"Stand.Norm.Dist."&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Step three - write the graph on disk:&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;graph&lt;/span&gt;&lt;span class="nf"&gt;.simple_theme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;poloto&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;upgrade_write&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As simple as that!&lt;/p&gt;

&lt;p&gt;Let's admire our work of (random) art:&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%2F0a4e1lazjh80hy497cuc.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%2F0a4e1lazjh80hy497cuc.png" alt="Histogram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OK, let's try something different: let's view our graph as a scatter plot. Since our hoax data is a Standard Normal Distribution, if we have N pairs of coordinates, the scatter plot should be like a cloud centered on the &lt;code&gt;0,0&lt;/code&gt; coordinates.&lt;/p&gt;

&lt;p&gt;Let's visualize it!&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;let&lt;/span&gt; &lt;span class="n"&gt;arr18&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&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="nf"&gt;random_using&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;StandardNormal&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="nn"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;thread_rng&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;data&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="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;f64&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;arr18&lt;/span&gt;&lt;span class="nf"&gt;.axis_iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="nf"&gt;.map&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="nf"&gt;.to_vec&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We created 300 pairs of random numbered centered around &lt;code&gt;(0, 0)&lt;/code&gt;, according to a Standard Normal Distribution.&lt;/p&gt;

&lt;p&gt;Then we transformed that array to a &lt;code&gt;Vec&amp;lt;(f64, f64)&amp;gt;&lt;/code&gt;, because the &lt;code&gt;poloto&lt;/code&gt; library only graphs &lt;code&gt;[f64; 2]&lt;/code&gt; or whatever can be converted to a &lt;code&gt;AsF64&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We will add also two lines to show the center of our graph:&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;let&lt;/span&gt; &lt;span class="n"&gt;x_line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&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;y_line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we create a file, plot, and save, just as we did for the histogram:&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;let&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&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;fs&lt;/span&gt;&lt;span class="p"&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;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"standard_normal_scatter.svg"&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;// create file on disk&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;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;poloto&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Scatter Plot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"y"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// create graph&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="nf"&gt;.line&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x_line&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="nf"&gt;.line&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;y_line&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="nf"&gt;.scatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Stand.Norm.Dist."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.ymarker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="nf"&gt;.simple_theme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;poloto&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;upgrade_write&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! We can admire our random creation now:&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%2Fe0e1sxz8b5pkui59cck8.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%2Fe0e1sxz8b5pkui59cck8.png" alt="Scatter Plot"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;I think this should wrap it up for today.&lt;/p&gt;

&lt;p&gt;We saw how to use &lt;code&gt;ndarray&lt;/code&gt; (in a basic form), and how it differs from Rust arrays and vectors.&lt;/p&gt;

&lt;p&gt;We saw also some of its companion crates that complete the ecosystem, to provide randomness and some statistic feats.&lt;br&gt;
We saw also a way to plot graphs with data, showing how to plot a histogram, a scatter plot, and some lines.&lt;/p&gt;

&lt;p&gt;I hope this will be a good starting point to delve deeper into the use of Rust for Data Science.&lt;/p&gt;

&lt;p&gt;That's all folks for today, see you next time!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>datascience</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Rust GUI: Introduction, a.k.a. the state of Rust GUI libraries (As of January 2021)</title>
      <dc:creator>Davide Del Papa</dc:creator>
      <pubDate>Mon, 18 Jan 2021 17:07:07 +0000</pubDate>
      <link>https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl</link>
      <guid>https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl</guid>
      <description>&lt;p&gt;[&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@kellysikkema?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Kelly Sikkema&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/user-interface?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;, modified (cropped)]&lt;/p&gt;

&lt;p&gt;This article follows up on a discussion. Please share your experience there, I'd gladly hear about it!&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/davidedelpapa" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w0W8im7---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--5nOKenrB--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/280018/ed530d51-2395-49e7-9ef3-16b2c69bfe4b.png" alt="davidedelpapa"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/davidedelpapa/which-rust-crate-to-use-as-gui-framework-right-now-jan-2021-4opm" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Which Rust crate to use as GUI framework right now (Jan 2021)?&lt;/h2&gt;
      &lt;h3&gt;Davide Del Papa ・ Jan 16 '21 ・ 1 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#discuss&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#rust&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


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

&lt;p&gt;Some months ago I was surveying a little the state of GUI in Rust. Let me tell you, the quest has been horrible. &lt;/p&gt;

&lt;p&gt;Starting off some searches on internet, apart some questions on Reddit and other sites, you get some (very old) articles. &lt;/p&gt;


&lt;div class="ltag__reddit--container"&gt;
  &lt;div class="ltag__reddit--title-container"&gt;
    
      &lt;div class="ltag__reddit--title"&gt;
        &lt;h1&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bCqI7Yj---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/reddit-icon-c6851eed10026b5707e2e8c814b5bbcbb4823de68d5b611a6f4b99c8beed6f05.svg" alt="Reddit Logo"&gt;
          &lt;a href="https://www.reddit.com/r/rust/comments/d68b6t/whats_the_state_of_rust_guis/" rel="noopener noreferrer"&gt;
            What’s the state of Rust GUIs?
          &lt;/a&gt;
        &lt;/h1&gt;
        &lt;div class="ltag__reddit--post-metadata"&gt;
          &lt;span&gt;Sep 19 '19&lt;/span&gt;
          &lt;span&gt;Author: [deleted]&lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__reddit--body"&gt;
    
&lt;p&gt;Rust has always seemed super interesting to me since learning of its existence a few months ago. However one thing that turned me off at the time was the lack of (structured) GUI bindings for cross platform devices. But fast forward a few months, is there a good GUI library to use that can make “complex” applications? Or maybe a…&lt;/p&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__reddit--btn--container"&gt;
    
      &lt;a href="https://www.reddit.com/r/rust/comments/d68b6t/whats_the_state_of_rust_guis/" rel="noopener noreferrer"&gt;See Full Post&lt;/a&gt;
    
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Old and stale.&lt;/p&gt;

&lt;p&gt;The only guide you get at the end of the day (referenced by all) is the site &lt;a href="https://www.areweguiyet.com/"&gt;Are We GUI Yet&lt;/a&gt; which is not helpful at all. &lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/areweguiyet"&gt;
        areweguiyet
      &lt;/a&gt; / &lt;a href="https://github.com/areweguiyet/areweguiyet"&gt;
        areweguiyet
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A website built for the Rust community
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Readme&lt;/h1&gt;
&lt;p&gt;Want to find crates for GUI in Rust? Then you've come to the right place!&lt;/p&gt;
&lt;h2&gt;
Status&lt;/h2&gt;
&lt;p&gt;This site is maintained as best as possible. The next steps likely involve
replacing it with an automated system more like &lt;a href="https://lib.rs" rel="nofollow"&gt;lib.rs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;CI runs weekly to update crate information from crates.io, if it is not
overriden by the crate's configuration in this repo.&lt;/p&gt;
&lt;h2&gt;
What is this?&lt;/h2&gt;
&lt;p&gt;Companion website to
&lt;a href="http://arewegameyet.com" rel="nofollow"&gt;arewegameyet&lt;/a&gt;
&lt;a href="http://www.arewewebyet.org" rel="nofollow"&gt;arewewebyet&lt;/a&gt;, and
&lt;a href="http://www.arewelearningyet.com" rel="nofollow"&gt;arewelearningyet&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
Contributing&lt;/h2&gt;
&lt;p&gt;To make it easy for people (hey, that's you! 😊) to contribute, AreWeGuiYet uses a custom
Rust CLI. It's currently a work in progress and is a little rough around the edges.&lt;/p&gt;
&lt;p&gt;The workflow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fork AreWeGuiYet&lt;/li&gt;
&lt;li&gt;clone your fork&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cd&lt;/code&gt; to the CLI directory (&lt;code&gt;cli&lt;/code&gt;) (it currently uses relative paths 😬)&lt;/li&gt;
&lt;li&gt;Build and run the CLI
&lt;ul&gt;
&lt;li&gt;Usage: &lt;code&gt;cargo run -- [--clean] &amp;lt;command&amp;gt; [flags]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Help: &lt;code&gt;cargo run -- help&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;When you're done…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/areweguiyet/areweguiyet"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;It seems that &lt;em&gt;AreWeGUIYet&lt;/em&gt; has not been updated since 2019, and the interface does not help in the least to search for a suitable library. The only tags it has is on the kind of implementations the crates have. Not many articles, not a useful tutorial, no understanding about the status of the crates that are showcased there. &lt;/p&gt;

&lt;p&gt;Some featured crates seem pretty rough, some more advanced... but there's no way to know it other than trying each and every one. &lt;/p&gt;

&lt;p&gt;Oh. &lt;br&gt;
My.&lt;/p&gt;

&lt;p&gt;And I did install some, but the results were a disaster, because at least the ones I tried sucked a lot. &lt;/p&gt;

&lt;p&gt;Then, over the summer I found an &lt;a href="https://www.boringcactus.com/2020/08/21/survey-of-rust-gui-libraries.html"&gt;article by boringcactus&lt;/a&gt;. They had much my same experience, but I realized that I actually managed to make many more things to work than they did...&lt;/p&gt;

&lt;p&gt;Flash forward to early November. Here I was, trying again the old way. I was serious with my intention to try each and every crate in the list.&lt;/p&gt;

&lt;p&gt;This time around I got even luckier. At least I did not only succeeded in make some libraries to work, I actually got material to write some tutorials to help others.&lt;/p&gt;

&lt;p&gt;Here I'll wet your appetite: there's more to come!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimers&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I only tried the following on my Linux laptop: sorry, I do not own a Windows or a Mac!&lt;/li&gt;
&lt;li&gt;I usually employ &lt;code&gt;cargo add&lt;/code&gt; from &lt;a href="https://crates.io/crates/cargo-edit"&gt;cargo edit&lt;/a&gt; (to install it: &lt;code&gt;cargo install cargo-edit&lt;/code&gt;), but you can add the dependency straight to &lt;em&gt;Cargo.toml&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;I tried to make the crates work in every possible way, and I meant it. I even patched them locally, and even submitted some issues or even a PR. I wanted to honestly do my homework&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Summary Table &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Below a summary of the crates I tried, with the status I found them in:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Working&lt;/td&gt;
&lt;td&gt;&lt;a href="https://crates.io/crates/druid"&gt;Druid&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;It relies on &lt;a href="https://github.com/linebender/piet"&gt;piet&lt;/a&gt; 2D graphic library; on Linux that means GTK/Cairo 2D primitives&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://crates.io/crates/fltk"&gt;FLTK&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;FLTK for Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://gtk-rs.org/"&gt;GTK+&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Official GTK+ Rust support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://crates.io/crates/Iced"&gt;Iced&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Elm Inspired&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/NoraCodes/libui-rs"&gt;IUI&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Based on &lt;a href="https://github.com/andlabs/libui"&gt;libui&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/redox-os/orbtk"&gt;OrbTK&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Even if it is designed for Redox, it still works on other systems&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://crates.io/crates/qmetaobject"&gt;QMetaObject&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;QT based: it relies heavily on QML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://crates.io/crates/relm"&gt;Relm&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Elm-inspired, GTK improvement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://crates.io/crates/sciter-rs"&gt;Sciter&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Bindings to Sciter, a commercial Library&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://tauri.studio/"&gt;Tauri&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;This is a different beast altogether: it transforms a web app to a desktop app, while adding the possibility to interface with Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/bodil/vgtk"&gt;VGTK&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Built on top of GTK, and Elm-inspired&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Other/Could not try&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/pistondevelopers/conrod"&gt;Conrod&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;The examples work. How to build a GUI is still a mystery though.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://crates.io/crates/imgui"&gt;ImGui&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Same thing as &lt;em&gt;Conrod&lt;/em&gt;, no way to understand how it works, besides the examples&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/servo/core-foundation-rs"&gt;Core-Foundation&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Could not try: I do not have a Mac&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://crates.io/crates/lvgl"&gt;LittlevGL&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Could not try: it runs on embedded systems&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://crates.io/crates/KAS"&gt;kas&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Could not try: I don't have Vulkan hardware, and the GTK backend is not working at all&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Not Working&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/maps4print/azul"&gt;Azul&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;Based on WebRender. I tried many times over to make it work... It refuses!&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://crates.io/crates/qt_widgets"&gt;QT_Widgets&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;There's a small issue, but it does not work until it is solved&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There are also two entries that I excluded completely, because I do not think they belong to Rust GUIs: WebRender and Rust-QT-Binding-Generator. Tauri almost got kicked out as well, but it stayed in, since it is another beast altogether (because it is a bridge between technologies, more than between languages as Rust-QT-Binding-Generator is).&lt;/p&gt;



&lt;h1&gt;
  
  
  Working
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Druid &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;One of the crates I could not make to work the first time around (I don't remember why), but in reality &lt;a href="https://crates.io/crates/druid"&gt;Druid&lt;/a&gt; works like a charm now. &lt;br&gt;
It relies on &lt;a href="https://github.com/linebender/piet"&gt;piet&lt;/a&gt; which is a 2D graphic library. On Linux it wraps &lt;a href="https://www.gtk.org/docs/installations/linux/"&gt;GTK3&lt;/a&gt; and its &lt;em&gt;cairo&lt;/em&gt; 2D primitives, so check out all the &lt;a href="http://gtk-rs.org/docs/requirements.html"&gt;requirements&lt;/a&gt; needed on your distro.&lt;br&gt;
It has also a web based render engine, and it uses &lt;em&gt;wasm&lt;/em&gt; and &lt;a href="https://github.com/rustwasm/wasm-pack"&gt;wasm-pack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's give it a try.&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 rust-ui-druid
&lt;span class="nb"&gt;cd &lt;/span&gt;rust-ui-druid
cargo add druid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then we can set up our first app in &lt;em&gt;src/main.rs&lt;/em&gt;:&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;druid&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Flex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Label&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;druid&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;AppLauncher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LocalizedString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PlatformError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WidgetExt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WindowDesc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Clone,&lt;/span&gt; &lt;span class="nd"&gt;Data)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;i32&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="k"&gt;-&amp;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="n"&gt;PlatformError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Window builder. We set title and size&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;main_window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;WindowDesc&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;ui_builder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, Druid!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.window_size&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mf"&gt;200.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// Data to be used in the app (=state)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Run the app&lt;/span&gt;
    &lt;span class="nn"&gt;AppLauncher&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with_window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main_window&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.use_simple_logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Neat!&lt;/span&gt;
        &lt;span class="nf"&gt;.launch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&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;ui_builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// The label text will be computed dynamically based on the current locale and count&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;LocalizedString&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="s"&gt;"hello-counter"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.with_arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;data&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;Counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_env&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="nf"&gt;.into&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;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Label&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;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.center&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Two buttons with on_click callback&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;button_plus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Button&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="s"&gt;"+1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.on_click&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;_ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&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;Counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_env&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="na"&gt;.0&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="nf"&gt;.padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.0&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;button_minus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Button&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="s"&gt;"-1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.on_click&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;_ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&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;Counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_env&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="na"&gt;.0&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="nf"&gt;.padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Container for the two buttons&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Flex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;row&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.with_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button_plus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.with_spacer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.with_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button_minus&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Container for the whole UI&lt;/span&gt;
    &lt;span class="nn"&gt;Flex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;column&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.with_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.with_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flex&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;Druid is pretty data-driven, so you see that widgets implement data-types: they are not a type unto themselves. That explains why a Widget type has to be declared as &lt;code&gt;Widget&amp;lt;T&amp;gt;&lt;/code&gt;. We notice also that Druid employs the constructor pattern a lot.&lt;/p&gt;

&lt;p&gt;Code notes:&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;#[derive(Clone,&lt;/span&gt; &lt;span class="nd"&gt;Data)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We create a custom data structure to employ as our app's state. It has to derive &lt;code&gt;druid::Data&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fn main()&lt;/code&gt; has to return a &lt;code&gt;Result&amp;lt;(), PlatformError&amp;gt;&lt;/code&gt;, because the &lt;code&gt;AppLauncher&lt;/code&gt; might fail.&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;main()&lt;/code&gt; we create a new main widow descriptor &lt;code&gt;WindowDesc&lt;/code&gt; out of a widget we'll create with the function &lt;code&gt;ui_builder()&lt;/code&gt;. We set title and state of the main window.&lt;/p&gt;

&lt;p&gt;We init the custom state (&lt;code&gt;Data&lt;/code&gt; in druid's jargon), and we pass the window and the state to the &lt;code&gt;AppLauncher&lt;/code&gt;, which will manage the app's cycle for us.&lt;/p&gt;

&lt;p&gt;Notice that Druid implements a simple logger to the &lt;code&gt;stderr&lt;/code&gt;, which I think it's a neat function for debugging.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;fn ui_builder()&lt;/code&gt; we first create a localized string (&lt;code&gt;LocalizedString&lt;/code&gt;), which renders a translatable text. Also this is a neat function, to have localization embedded in the regular flow of development. We assign the &lt;code&gt;"hello-counter"&lt;/code&gt; key to it; since this is bundled as a default (for example's purpose) the translation will be automatically created for us, according to the locale (by now only English, French and German). we assign this localized string to a label (we set the center position and a padding to it).&lt;/p&gt;

&lt;p&gt;The we create two buttons, one to increase and the other to decrease our state counter, with a callback on the &lt;code&gt;on_click()&lt;/code&gt; event. The state will be increased (decreased), and Druid will take care to update the interface to reflect the state for us (no need to signal to the label to update its text, it's Druid's duty... Very nice!)&lt;/p&gt;

&lt;p&gt;We create a &lt;code&gt;Flex&lt;/code&gt; which is a container, and we stack the two button horizontally, with a space in between.&lt;/p&gt;

&lt;p&gt;Then we return another &lt;code&gt;Flex&lt;/code&gt; where we stack vertically the label and the &lt;code&gt;Flex&lt;/code&gt; that contains the buttons. This is the UI that our window descriptor takes as argument.&lt;/p&gt;

&lt;p&gt;We can now run our first Druid application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N4xdNdF_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/q2lititadekfc25sfkob.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N4xdNdF_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/q2lititadekfc25sfkob.jpg" alt="Druid example app" width="209" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example Repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davidedelpapa"&gt;
        davidedelpapa
      &lt;/a&gt; / &lt;a href="https://github.com/davidedelpapa/rust-ui-druid"&gt;
        rust-ui-druid
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Rust UI Rundown: Druid
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;Code for part of &lt;a href="https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl" rel="nofollow"&gt;rust-ui-rundown article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/davidedelpapa/rust-ui-druid"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h3&gt;
  
  
  FLTK &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Next in the list is FLTK. The first time around, I admit that I didn't even consider it: having a little C/C++ background I have actually used FLTK sometime before and, let me tell you, it's quite &lt;em&gt;"complicated"&lt;/em&gt;, and with poor results. It is not feature filled as wxWidgets or QT (it's much more bare-bones actually), but still it manages to have a way in which you have to code that... ugh! Well, I didn't even consider it because of my negative experiences in the past. However, now I'm told that FLTK has come a long way since the times I was using it in C++, so this should teach me something about having prejudices.&lt;/p&gt;

&lt;p&gt;In fact, this time I was going to try each crate in the list, and when the FLTK bindigs turn came, I was fully blown away by this crate as soon as I gave it a try: I fell in love with it! Somehow the author managed to take away the complexity of writing a FLTK interface, and made it &lt;strong&gt;Rust-y&lt;/strong&gt; (read it with a &lt;em&gt;sex-y&lt;/em&gt; voice please!). I mean, it feels as if it was only Rust, no bindings whatsoever involved. It clearly does not feel as a wrapper, around a FFI wrapper, around a C library (too many chinese boxes I reckon), as many crates that bind C libraries (try one of the QT crates and then come beck here imploring!).&lt;br&gt;
Instead, it feels like true Rust native. In order to do so, sometimes it wraps around widgets in a different way than the underlying FLTK libs. But this is really nice, I found out.&lt;/p&gt;

&lt;p&gt;Like Druid, FLTK employs the constructor pattern a lot.&lt;/p&gt;

&lt;p&gt;As first thing, let's check (and in case, fix), &lt;a href="https://docs.rs/fltk/0.10.6/fltk/#dependencies"&gt;FLTK's dependencies&lt;/a&gt;:&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;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;libx11-dev libxext-dev libxft-dev libxinerama-dev libxcursor-dev libxrender-dev libxfixes-dev libpango1.0-dev libgl1-mesa-dev libglu1-mesa-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then, we can start a new project and declare FLTK dependency:&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 rust-ui-fltk
&lt;span class="nb"&gt;cd &lt;/span&gt;rust-ui-fltk
cargo add fltk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's take a look at the &lt;em&gt;src/main.rs&lt;/em&gt;:&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;fltk&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="nn"&gt;app&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="nn"&gt;button&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="nn"&gt;frame&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="nn"&gt;window&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;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;let&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;App&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;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;wind&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Window&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="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello, FLTK!"&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;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Frame&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Boring label"&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;but&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Button&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="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;210&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Click me!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;wind&lt;/span&gt;&lt;span class="nf"&gt;.end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;wind&lt;/span&gt;&lt;span class="nf"&gt;.show&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Remember: Callbacks after initializing the interface&lt;/span&gt;
    &lt;span class="n"&gt;but&lt;/span&gt;&lt;span class="nf"&gt;.set_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="nf"&gt;.set_label&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="n"&gt;app&lt;/span&gt;&lt;span class="nf"&gt;.run&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We set the App with it's defaults, then in order to start the &lt;code&gt;Window&lt;/code&gt;, we specify X,Y position and width,height dimensions, plus the title; then we create a &lt;code&gt;Frame&lt;/code&gt; (equivalent of FLTK Box), again with position and dimensions, plus a label; finally a button (pos., dim., label as well).&lt;/p&gt;

&lt;p&gt;We did not employ the constructor pattern here, but we could have done the following with the button, for example:&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;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;but&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Button&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;.with_pos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;210&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.with_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.with_label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Click me!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Which is equivalent to the above &lt;code&gt;Button::new(160, 210, 80, 40, "Click me!")&lt;/code&gt; initializing method.&lt;/p&gt;

&lt;p&gt;Once the UI is done, we finalize the UI (with &lt;code&gt;.end()&lt;/code&gt;), then we show the window(with &lt;code&gt;.show()&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Callbacks are to be set once the UI is finalized; so we set a callback to the button (it gets called on the click event), and in its closure we change the label of the frame.&lt;/p&gt;

&lt;p&gt;At the end we just run the app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JKuUgdN1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/incv4ab4qa4x8gfptrrk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JKuUgdN1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/incv4ab4qa4x8gfptrrk.jpg" alt="FLTK sample app" width="442" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Maybe you didn't realize, but this is also maybe the simplest of the example here present, yet it is fully functional!&lt;/p&gt;

&lt;p&gt;This crate is very promising: &lt;a href="https://youtu.be/3jW_vxGmxt0"&gt;the author even manged to use it on the Android system&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Example Repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davidedelpapa"&gt;
        davidedelpapa
      &lt;/a&gt; / &lt;a href="https://github.com/davidedelpapa/rust-ui-fltk"&gt;
        rust-ui-fltk
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Rust UI Rundown: FLTK
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;Code for part of &lt;a href="https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl" rel="nofollow"&gt;rust-ui-rundown article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/davidedelpapa/rust-ui-fltk"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h3&gt;
  
  
  GTK &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Official &lt;a href="https://gtk-rs.org/"&gt;GTK&lt;/a&gt; bindings, this should be the go to crate for "serious" projects. That said, please be prepared for a non ergonomic experience. You know, this is a full featured crate, binding to one of the 3 most humongous GUI libraries out there, so it is totally fitting that it has some complexity, as the full control that it brings is much bigger than any "simplistic" other project.&lt;/p&gt;

&lt;p&gt;In fact, there are other crates that bind to GTK, and they all try to simplify it, but at the expense of full control. It's just a trade off.&lt;/p&gt;

&lt;p&gt;That said, I have to say, the Rust bindings to GTK are much more ergonomic than the C/C++/c#. I think there's something in Rust that makes many implementations much more ergonomic than their C counterpart. Don't expect the treats &lt;em&gt;fltk&lt;/em&gt; provides though; let's say it's a gracious compromise.&lt;/p&gt;

&lt;p&gt;The project gives also the possibility to use &lt;a href="https://glade.gnome.org/"&gt;Glade&lt;/a&gt; and its XML based interface descriptor.&lt;/p&gt;

&lt;p&gt;Time to start off:&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 rust-ui-gtk
&lt;span class="nb"&gt;cd &lt;/span&gt;rust-ui-gtk
cargo add gtk &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v3_16
cargo add gio &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v2_44
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, let's write our &lt;em&gt;src/main.rs&lt;/em&gt;&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;gtk&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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;use&lt;/span&gt; &lt;span class="nn"&gt;gio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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;use&lt;/span&gt; &lt;span class="nn"&gt;gtk&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ApplicationWindow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Label&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;let&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Application&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;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.github.rust-ui-rundown.rust-ui-gtk"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nn"&gt;Default&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="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to initialize GTK application"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="nf"&gt;.connect_activate&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;app&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;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;ApplicationWindow&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;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="nf"&gt;.set_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, GTK+!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="nf"&gt;.set_default_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;350&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;70&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;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Box&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="nn"&gt;gtk&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Orientation&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Vertical&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&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;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Label&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="nb"&gt;None&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;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with_label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Click me!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="nf"&gt;.add&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;label&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="nf"&gt;.add&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;button&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="nf"&gt;.add&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;container&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="nf"&gt;.connect_clicked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&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;label&lt;/span&gt;&lt;span class="nf"&gt;.set_label&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;span class="n"&gt;window&lt;/span&gt;&lt;span class="nf"&gt;.show_all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&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 create first an Application. We have to pass to it an identifier (an &lt;code&gt;Option&lt;/code&gt; wrapped &lt;code&gt;str&lt;/code&gt;) and the application's flags. We are passing to it the default ones.&lt;/p&gt;

&lt;p&gt;Next we apply the method &lt;code&gt;connect_activate&lt;/code&gt; which creates the UI in a closure. In this closure we declare a window for the app (&lt;code&gt;ApplicationWindow&lt;/code&gt;), setting title and default dimensions. Then we create a &lt;code&gt;Box&lt;/code&gt; container with vertical orientation and spacing.&lt;/p&gt;

&lt;p&gt;We set a label, with no text (with &lt;code&gt;None&lt;/code&gt;) and a button. We add these to the container; then we add the container itself to the window.&lt;/p&gt;

&lt;p&gt;Next, we declare a callback for our button, with a closure that sets the label text, once the button is clicked.&lt;/p&gt;

&lt;p&gt;We end the closure of &lt;code&gt;connect_activate()&lt;/code&gt; by showing all widgets. Finally, we run the application.&lt;/p&gt;

&lt;p&gt;The program works as intended, and at this stage is not even much too complex to create simple GUIs like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jJCEK_cs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6knnfm18zqldn7p69q9m.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jJCEK_cs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6knnfm18zqldn7p69q9m.jpg" alt="GTK sample app" width="370" height="131"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example Repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davidedelpapa"&gt;
        davidedelpapa
      &lt;/a&gt; / &lt;a href="https://github.com/davidedelpapa/rust-ui-gtk"&gt;
        rust-ui-gtk
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Rust UI Rundown: GTK
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;Code for part of &lt;a href="https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl" rel="nofollow"&gt;rust-ui-rundown article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/davidedelpapa/rust-ui-gtk"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h3&gt;
  
  
  Iced &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A cross-platform, elm inspired framework, &lt;a href="https://crates.io/crates/Iced"&gt;Iced&lt;/a&gt; is a good small solution. The Elm like architecture has been used in many Rust projects already (think &lt;a href="https://yew.rs/"&gt;Yew&lt;/a&gt; or &lt;a href="https://github.com/seed-rs/seed"&gt;Seed&lt;/a&gt;). Like Druid, Iced is data centered.&lt;/p&gt;

&lt;p&gt;The first time around I could not make it run, because I do not have Vulkan (and I made a mess with some tricks trying to install it: I do not have a compatible hardware). Since then, though, Iced has got a new OpenGL back-end through &lt;a href="https://crates.io/crates/glow"&gt;glow&lt;/a&gt;; the problem is, it is not yet on the &lt;em&gt;crates.io&lt;/em&gt; version, so I needed to add it thorugh the GitHub repo:&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 rust-ui-iced
&lt;span class="nb"&gt;cd &lt;/span&gt;rust-ui-iced
cargo add iced &lt;span class="nt"&gt;--git&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/hecrj/iced.git"&lt;/span&gt; &lt;span class="nt"&gt;--features&lt;/span&gt; glow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And now, let's head to the &lt;em&gt;src/main.rs&lt;/em&gt;:&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;iced&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Sandbox&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Sandbox&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;MyApp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="o"&gt;=&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;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;MyApp&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;title&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;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, Iced"&lt;/span&gt;&lt;span class="p"&gt;)&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;update&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="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&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;view&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="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;Text&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="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.into&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;pub&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="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;iced&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Settings&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This example is a bit simplified. We need to declare a struct that we need to impl as an app. In this case it is a &lt;code&gt;Sandboxed&lt;/code&gt; type of app, that is more simplified than a regular app (and with less customizing available).&lt;/p&gt;

&lt;p&gt;The app has to impl several functions that will be called during the application cycle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;new()&lt;/code&gt; to init the app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;title()&lt;/code&gt; to assign its title (it can be dynamic: neat!)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;update()&lt;/code&gt; to check and react to the app messages (given by the &lt;code&gt;Message&lt;/code&gt; type, but in this case its an empty object &lt;code&gt;()&lt;/code&gt;). Here we have nothing to react to.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;view()&lt;/code&gt; to render the app graphics part (the UI), in this case a simple text that does nothing but stand still.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We init the App, running it on &lt;code&gt;main()&lt;/code&gt; with the default options.&lt;/p&gt;

&lt;p&gt;This is how it looks like when run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sbcUbg1h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wgku5rs8ffocslx67d5j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sbcUbg1h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wgku5rs8ffocslx67d5j.png" alt="Iced sample app" width="353" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example Repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davidedelpapa"&gt;
        davidedelpapa
      &lt;/a&gt; / &lt;a href="https://github.com/davidedelpapa/rust-ui-iced"&gt;
        rust-ui-iced
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Rust UI Rundown: Iced
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;Code for part of &lt;a href="https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl" rel="nofollow"&gt;rust-ui-rundown article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/davidedelpapa/rust-ui-iced"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h3&gt;
  
  
  IUI &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/NoraCodes/libui-rs"&gt;IUI&lt;/a&gt; is a cross platform wrapper for &lt;a href="https://github.com/andlabs/libui"&gt;libui&lt;/a&gt;, which in turns uses native frameworks: the usual GTK+, cocoa, and Win32API.&lt;/p&gt;

&lt;p&gt;It is a simple yet very usable framework, at least for small projects. Let's see it with an example.&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 rust-ui-iui
&lt;span class="nb"&gt;cd &lt;/span&gt;rust-ui-iui
cargo add iui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the &lt;em&gt;src/main.rs&lt;/em&gt;:&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;iui&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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;use&lt;/span&gt; &lt;span class="nn"&gt;iui&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;controls&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VerticalBox&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;rc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Rc&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;cell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RefCell&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&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="c1"&gt;// Initialize the UI and State&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ui&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;UI&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Couldn't initialize UI library"&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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Rc&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="nn"&gt;RefCell&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;State&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a window into which controls can be placed&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;win&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Window&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;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello, IUI!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;WindowType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NoMenubar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a vertical layout to hold the controls&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;vbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;VerticalBox&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;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;vbox&lt;/span&gt;&lt;span class="nf"&gt;.set_padded&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;ui&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;// Create a new label.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Label&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;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ui&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="c1"&gt;// Create a button and its callback&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;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Button&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;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Click me!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="nf"&gt;.on_clicked&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;ui&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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&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;state&lt;/span&gt;&lt;span class="nf"&gt;.borrow_mut&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello, world"&lt;/span&gt;&lt;span class="nf"&gt;.to_owned&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="c1"&gt;// Adding controls to the box, and box to window&lt;/span&gt;
    &lt;span class="n"&gt;vbox&lt;/span&gt;&lt;span class="nf"&gt;.append&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;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;LayoutStrategy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Stretchy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;vbox&lt;/span&gt;&lt;span class="nf"&gt;.append&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;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;LayoutStrategy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Compact&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;win&lt;/span&gt;&lt;span class="nf"&gt;.set_child&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;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vbox&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Show the window&lt;/span&gt;
    &lt;span class="n"&gt;win&lt;/span&gt;&lt;span class="nf"&gt;.show&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;ui&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Run the application&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;event_loop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="nf"&gt;.event_loop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;event_loop&lt;/span&gt;&lt;span class="nf"&gt;.on_tick&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;ui&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;ui&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="nf"&gt;.clone&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;ui_label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;move&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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="nf"&gt;.borrow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c1"&gt;// Update all the labels&lt;/span&gt;
            &lt;span class="n"&gt;ui_label&lt;/span&gt;&lt;span class="nf"&gt;.set_text&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;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;format!&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;state&lt;/span&gt;&lt;span class="py"&gt;.label&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;event_loop&lt;/span&gt;&lt;span class="nf"&gt;.run&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;ui&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 first define a struct to hold the global state, then initialize it as a &lt;code&gt;RefCell&lt;/code&gt;, to clone safely.&lt;/p&gt;

&lt;p&gt;We initialize a window, with some settings, and a vertical box. We then initialize two controls: a label and a button, with its callback. Once clicked, the button changes the global state, in order to update the text label.&lt;/p&gt;

&lt;p&gt;We then add the controls to the layout, and the layout to the window. Up to this point it works mostly as any other UI framework&lt;/p&gt;

&lt;p&gt;When running the app, there's a little difference: we have to manage the refreshes with the &lt;code&gt;on_tick()&lt;/code&gt; callback in the event loop. &lt;br&gt;
It is conceptually similar to the &lt;a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller"&gt;MVC pattern&lt;/a&gt;, however, we insert our logic inside the event loop itself. This means we have to centralize all the updating of the app in one function. &lt;/p&gt;

&lt;p&gt;This means that in order to decouple the refresh from the cycle we would need to create a function for each component, then call it in sequence in the event loop &lt;code&gt;on_tick&lt;/code&gt;.&lt;br&gt;
This is not a problem &lt;em&gt;per se&lt;/em&gt;, but it must be considered when architecting the apps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4svU5gYp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fbirtqb0j7a057zyjk2s.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4svU5gYp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fbirtqb0j7a057zyjk2s.jpg" alt="IUI sample APP" width="233" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the general side, I find IUI quite simple, yet usable. &lt;del&gt;It is a pity that its development seems halted.&lt;/del&gt; EDIT: Good news! As you can see in the comments, the development on this library has not halted at all, it was just slowed down by the underlying C lib.&lt;/p&gt;

&lt;p&gt;Example Repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davidedelpapa"&gt;
        davidedelpapa
      &lt;/a&gt; / &lt;a href="https://github.com/davidedelpapa/rust-ui-iui"&gt;
        rust-ui-iui
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Rust UI Rundown: IUI
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;Code for part of &lt;a href="https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl" rel="nofollow"&gt;rust-ui-rundown article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/davidedelpapa/rust-ui-iui"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h3&gt;
  
  
  OrbTK &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/redox-os/orbtk"&gt;orbtk&lt;/a&gt; is the base of the &lt;a href="https://www.redox-os.org/"&gt;Redox Operative System&lt;/a&gt; widgets. It can be used also on other systems (even Android is on the plate, but the support is not yet completed).&lt;br&gt;
I do not know if it's my configuration, but sometimes it feels slow. Compilation too takes a long time, even for small changes, and it seems it recompiles quite few things every time.&lt;/p&gt;

&lt;p&gt;Remember to install &lt;em&gt;xkb&lt;/em&gt; and &lt;em&gt;wayland&lt;/em&gt; as dependencies:&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;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;libxkbcommon-dev libwayland-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's get down to business.&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 rust-ui-orbtk
&lt;span class="nb"&gt;cd &lt;/span&gt;rust-ui-orbtk
cargo add orbtk &lt;span class="nt"&gt;--git&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/redox-os/orbtk.git"&lt;/span&gt; &lt;span class="nt"&gt;--branch&lt;/span&gt; develop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As for the &lt;em&gt;src/main.rs&lt;/em&gt;:&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;orbtk&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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;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="nn"&gt;orbtk&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="nn"&gt;Application&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;.window&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="nn"&gt;Window&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;.title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, OrbTk!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.position&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="nf"&gt;.size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;200.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nn"&gt;TextBlock&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;.text&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;.v_align&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="nf"&gt;.h_align&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;.run&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;It is a very small example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;first we initialize the &lt;code&gt;orbtk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;then we create a new &lt;code&gt;Application&lt;/code&gt;, and we build its window;&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;window&lt;/code&gt; method gets a closure to which the context gets passed on. Inside it we create a &lt;code&gt;Window&lt;/code&gt;, again with a builder pattern.&lt;/li&gt;
&lt;li&gt;for the new window we set some properties, like title, size, and position, and we declare a &lt;code&gt;TextBlock&lt;/code&gt; as its child&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;TextBlock&lt;/code&gt; is build with a builder pattern as well, setting the alignment (vertical and horizontal) inside the container, and its text&lt;/li&gt;
&lt;li&gt;both &lt;code&gt;TextBlock&lt;/code&gt; and &lt;code&gt;Window&lt;/code&gt; take the context as parameter of the &lt;code&gt;build()&lt;/code&gt; method, that init the widget.&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;Application&lt;/code&gt;, which is the top-level "container", and provides the context for the contained widgets, uses a &lt;code&gt;run()&lt;/code&gt; method, instead, in order to build and run.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vjw98pji--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xbyt0wzzu96kbs81j8ge.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vjw98pji--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xbyt0wzzu96kbs81j8ge.jpg" alt="OrbTK sample app" width="222" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example Repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davidedelpapa"&gt;
        davidedelpapa
      &lt;/a&gt; / &lt;a href="https://github.com/davidedelpapa/rust-ui-orbtk"&gt;
        rust-ui-orbtk
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Rust UI Rundown: OrbTK
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;Code for part of &lt;a href="https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl" rel="nofollow"&gt;rust-ui-rundown article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/davidedelpapa/rust-ui-orbtk"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h3&gt;
  
  
  QMetaObject &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/qmetaobject"&gt;QMetaObject&lt;/a&gt; relies on  the QT Widgets, and it is written in order to support directly the QML interface language, that is a JSON like declarative language, with some JavaScript like constructs.&lt;/p&gt;

&lt;p&gt;Needless to say, QT Widgets must be installed. But first, we need some libraries installed as well (if you do not have them already):&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;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;libclang-dev libsqlite3-dev
apt-get &lt;span class="nb"&gt;install &lt;/span&gt;libllvm-11-ocaml-dev libllvm11 llvm-11 llvm-11-dev llvm-11-doc llvm-11-examples llvm-11-runtime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now we need also QT:&lt;/p&gt;

&lt;p&gt;Download the open source versions from the &lt;a href="https://www.qt.io/download"&gt;QT Download Page&lt;/a&gt;: in the next page scroll down and &lt;code&gt;Download the QT Online Installer&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Once downloaded you have to execute the script:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./qt-unified-linux-x64-4.0.1-online.run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Please install a &lt;strong&gt;Desktop&lt;/strong&gt; setting.&lt;/p&gt;

&lt;p&gt;After this, we need to export the paths:&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;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"~/Qt/5.15.2/gcc_64/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"~/Qt/5.15.2/gcc_64/lib:&lt;/span&gt;&lt;span class="nv"&gt;$LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Substitute the &lt;code&gt;5.15.2&lt;/code&gt; with your actual version.&lt;/p&gt;

&lt;p&gt;Now we can pass to the Rust side.&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 rust-ui-qmetaobject
&lt;span class="nb"&gt;cd &lt;/span&gt;rust-ui-qmetaobject
cargo add qmetaobject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We can now see an example &lt;em&gt;main.rs&lt;/em&gt; adapted from the repo's README (adapted to use standard &lt;code&gt;CStr&lt;/code&gt; actually):&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="nn"&gt;ffi&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;CStr&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;qmetaobject&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="nd"&gt;#[allow(non_snake_case)]&lt;/span&gt;
&lt;span class="nd"&gt;#[derive(Default,&lt;/span&gt; &lt;span class="nd"&gt;QObject)]&lt;/span&gt;
&lt;span class="k"&gt;struct&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;base&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nd"&gt;qt_base_class!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;QObject&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="nd"&gt;qt_property!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;NOTIFY&lt;/span&gt; &lt;span class="n"&gt;name_changed&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;name_changed&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nd"&gt;qt_signal!&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;compute_greetings&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nd"&gt;qt_method!&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;compute_greetings&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;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verb&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;QString&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;verb&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&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="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.name&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.into&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;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="nn"&gt;qml_register_type&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Greeter&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nn"&gt;CStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_bytes_with_nul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;b"Greeter&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;"&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;CStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_bytes_with_nul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;b"Greeter&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;"&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="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;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;QmlEngine&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;engine&lt;/span&gt;&lt;span class="nf"&gt;.load_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r#"
        import QtQuick 2.6; import QtQuick.Window 2.0;
        import Greeter 1.0
        Window {
            visible: true;
            title: "Hello, QMetaObject";
            Greeter { id: greeter; name: 'World'; }
            Text { anchors.centerIn: parent; text: greeter.compute_greetings('hello'); }            
        }
    "#&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="nf"&gt;.exec&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;In the above we create a custom class to "implement" a C++ &lt;code&gt;QObject&lt;/code&gt;. Of course a Rust &lt;em&gt;struct&lt;/em&gt; cannot implement a C++ object, so in order for it to work, &lt;em&gt;QMetaObject&lt;/em&gt; needs you to derive &lt;code&gt;QObject&lt;/code&gt;, and then specify in the &lt;code&gt;base&lt;/code&gt; field the C++ class to inherit from, with the macro &lt;code&gt;qt_base_class!(trait QObject)&lt;/code&gt;.&lt;br&gt;
In the &lt;em&gt;struct&lt;/em&gt; you can then add any custom field, besides a &lt;code&gt;name&lt;/code&gt; that is the means by which the class can be render visible to the underlying C++.&lt;br&gt;
In this case we added a &lt;code&gt;compute_greetings&lt;/code&gt; which is rendered as a QT Method with the macro &lt;code&gt;qt_method!()&lt;/code&gt; which takes a closure.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;main()&lt;/code&gt; we need to register our custom &lt;em&gt;struct&lt;/em&gt; with &lt;code&gt;qml_register_type&lt;/code&gt; which takes a &lt;em&gt;uri&lt;/em&gt;, a version major and minor (in this case &lt;code&gt;1.0&lt;/code&gt; therefore &lt;code&gt;1,0&lt;/code&gt;), and the name of the object (the version is needed in QML). Both uri and name have to be passed as C strings, in this case using &lt;code&gt;std::ffi::CStr&lt;/code&gt; and the method &lt;code&gt;from_bytes_with_nul&lt;/code&gt;; the null terminating the string (totally FFI C++ style) is rendered with &lt;code&gt;\0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now the object is available in QML, and we can refer to it by the selected name and version (&lt;code&gt;Greeter 1.0&lt;/code&gt; in this case).&lt;br&gt;
We can create a &lt;code&gt;QmlEngine&lt;/code&gt; and load the QML either as a string or as a file (in our case a Rust literal string with &lt;code&gt;#" ... "#&lt;/code&gt;). As you can see we use our &lt;code&gt;Greeter&lt;/code&gt; and its method &lt;code&gt;compute_greetings&lt;/code&gt; inside the QML.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yKOz13EP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ee0h3tt8hb4ztbnf9o3a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yKOz13EP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ee0h3tt8hb4ztbnf9o3a.png" alt="QMetaObject sample app" width="430" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example Repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davidedelpapa"&gt;
        davidedelpapa
      &lt;/a&gt; / &lt;a href="https://github.com/davidedelpapa/rust-ui-qmetaobject"&gt;
        rust-ui-qmetaobject
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Rust UI Rundown: QMetaObject
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;Code for part of &lt;a href="https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl" rel="nofollow"&gt;rust-ui-rundown article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/davidedelpapa/rust-ui-qmetaobject"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h3&gt;
  
  
  Relm &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A framework that aims to simplify GTK and give it a behaviour like Elm. Check &lt;em&gt;gtk-rs&lt;/em&gt; requirements/dependencies.&lt;/p&gt;

&lt;p&gt;In reality it does not simplify GTK, it just renders it elm-like. In fact, you need to know how to design UIs with &lt;em&gt;gtk&lt;/em&gt; in order to use Relm. A nice thing is that Relm can use the &lt;em&gt;Glade&lt;/em&gt; interface and descriptor as well. Another good perk is that in the examples it shows clearly how to test the interface, not a thing to underestimate!&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 rust-ui-relm
&lt;span class="nb"&gt;cd &lt;/span&gt;rust-ui-relm
cargo add relm relm-derive gtk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Onto &lt;em&gt;src/main.rs&lt;/em&gt; now:&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;gtk&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ButtonExt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ContainerExt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Inhibit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LabelExt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WidgetExt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WindowType&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;relm&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Relm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Widget&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;relm_derive&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Msg)]&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Msg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Quit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Clone)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Widgets&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;lbl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;but&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[allow(dead_code)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Win&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;widgets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Widgets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Update&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Win&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ModelParam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Msg&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;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&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;Relm&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&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;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;{}&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;update&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="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Msg&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;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.widgets.lbl&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;event&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Hello&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;label&lt;/span&gt;&lt;span class="nf"&gt;.set_text&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;span class="nn"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Quit&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;gtk&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;main_quit&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="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Win&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Window&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;root&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;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.widgets.window&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&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;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relm&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;Relm&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&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;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Create the view using the normal GTK+ method calls.&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Window&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="nn"&gt;WindowType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Toplevel&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;lbl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Label&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="nb"&gt;None&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;but&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with_label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Click Me"&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;vbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;gtk&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Box&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="nn"&gt;Orientation&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Vertical&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;vbox&lt;/span&gt;&lt;span class="nf"&gt;.add&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;lbl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;vbox&lt;/span&gt;&lt;span class="nf"&gt;.add&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;but&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="nf"&gt;.add&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;vbox&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="nf"&gt;.show_all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nd"&gt;connect!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;but&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;connect_clicked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nn"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nd"&gt;connect!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;connect_delete_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&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="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Quit&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;Inhibit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

        &lt;span class="n"&gt;Win&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;widgets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Widgets&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;lbl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;but&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;window&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="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="nn"&gt;Win&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Win::run failed"&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 you can see from the &lt;code&gt;use&lt;/code&gt; section, &lt;code&gt;gtk&lt;/code&gt; is not really hidden behind Relm with wrappers, but is forefront.&lt;/p&gt;

&lt;p&gt;We need four data structures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;code&gt;struct&lt;/code&gt; for the &lt;code&gt;Model&lt;/code&gt;, that holds the App's state (none in this case)&lt;/li&gt;
&lt;li&gt;a  &lt;code&gt;enum&lt;/code&gt; &lt;code&gt;Msg&lt;/code&gt; for the messages (callbacks), for which we derive &lt;code&gt;relm_derive::Msg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;struct&lt;/code&gt; &lt;code&gt;Widgts&lt;/code&gt; to hold the widgets list (we need to allow dead code, because we are not using the Model, as it has no state)&lt;/li&gt;
&lt;li&gt;a struct &lt;code&gt;Win&lt;/code&gt; for the main window (it holds the Model and the widgets)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For &lt;code&gt;Win&lt;/code&gt; we impl the &lt;code&gt;Update&lt;/code&gt; cycle, setting the &lt;code&gt;model()&lt;/code&gt; function to create the model, and the &lt;code&gt;update()&lt;/code&gt; function to set the behavior for each message (we &lt;code&gt;match&lt;/code&gt; over the two messages, assigning the &lt;code&gt;gtk::main_quit()&lt;/code&gt; when the message to &lt;code&gt;Quit&lt;/code&gt; is fired, and setting the label's text when the &lt;code&gt;Hello&lt;/code&gt; message is fired).&lt;/p&gt;

&lt;p&gt;We need to impl also the &lt;code&gt;Widget&lt;/code&gt; for our &lt;code&gt;Win&lt;/code&gt;, setting the type of the root window (in this case single window &lt;code&gt;gtk::Window&lt;/code&gt;). The &lt;code&gt;root()&lt;/code&gt; function is needed to init the root window, while the &lt;code&gt;view()&lt;/code&gt; function draws the UI, using the &lt;code&gt;gtk&lt;/code&gt; widgets and conventions.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fn view()&lt;/code&gt; has to return the &lt;code&gt;Widget&lt;/code&gt; &lt;code&gt;struct&lt;/code&gt; initialized. We start declaring a &lt;code&gt;gtk::WindowType::Toplevel&lt;/code&gt; window. Then we declare a label (with &lt;code&gt;text = None&lt;/code&gt;) and a button.&lt;br&gt;
We create a container and place the label and button in it, and then we place the container as the root widget of the window.&lt;br&gt;
After showing the window (&lt;code&gt;window.show_all()&lt;/code&gt;), we can set the callbacks, using the interesting &lt;em&gt;Relm&lt;/em&gt; macro &lt;code&gt;connect!&lt;/code&gt;. We connect the quit message of the window to the &lt;code&gt;Msg::Quit&lt;/code&gt;, and the click of the button to the &lt;code&gt;Msg::Hello&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After running the app, we have our window showing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kM-Wp908--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2dz9b3k7cwh776xbyh92.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kM-Wp908--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2dz9b3k7cwh776xbyh92.jpg" alt="Relm sample app" width="308" height="130"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can notice that the interface is quite similar to that of the base GTK app.&lt;/p&gt;

&lt;p&gt;Example Repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davidedelpapa"&gt;
        davidedelpapa
      &lt;/a&gt; / &lt;a href="https://github.com/davidedelpapa/rust-ui-relm"&gt;
        rust-ui-relm
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Rust UI Rundown: Relm
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;Code for part of &lt;a href="https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl" rel="nofollow"&gt;rust-ui-rundown article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/davidedelpapa/rust-ui-relm"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h3&gt;
  
  
  Sciter &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://sciter.com"&gt;Sciter&lt;/a&gt; is a C-API commercial library (by &lt;em&gt;Terra Informatica&lt;/em&gt;) used to create UIs based on web technologies. It has (amongst many others) a Rust binding, &lt;a href="https://crates.io/crates/sciter-rs"&gt;sciter-rs&lt;/a&gt;. There is a freeware version that we can use, and it seems that it is possible to use it also in commercial software. The only clause is to include somewhere, maybe in an &lt;code&gt;about&lt;/code&gt; section, the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This Application (or Component) uses Sciter Engine (http://sciter.com/), copyright Terra Informatica Software, Inc.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The other caveat is that the executable &lt;strong&gt;may&lt;/strong&gt; send diagnostic data to one of &lt;em&gt;Terra Informatica&lt;/em&gt; 's servers. They are very clear that it may, and maybe (for what I read) it's just diagnostic (it should not infringe the EU protection laws in matters of personal data...). Anyway, the important thing is that you are aware.&lt;/p&gt;

&lt;p&gt;By the way, between September and Octobr 2020 the author has &lt;a href="https://www.kickstarter.com/projects/c-smile/open-source-sciter-engine/posts"&gt;campaigned on Kikstarter&lt;/a&gt; in order to raise funds to open-source the project. The campaign ended and the goal was not reached, but the author started to disclose some part of the code replacing the Javascript engine, with a BSD 3-clause license, found on &lt;a href="https://github.com/c-smile/sciter-js-sdk"&gt;github.com/c-smile/sciter-js-sdk&lt;/a&gt;. It seems all very promising.&lt;/p&gt;

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

&lt;p&gt;First we need to download the sdk from the &lt;a href="https://sciter.com/download/"&gt;sdk download page&lt;/a&gt; and extract it. Let's copy in a folder accessible in your PATH the &lt;em&gt;libsciter-gtk.so&lt;/em&gt; found in &lt;em&gt;bin.lnx/x64&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If it's not installed we need to install the GTK development files as well&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;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;libgtk-3-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And now, for the Rust part.&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 rust-ui-sciter
&lt;span class="nb"&gt;cd &lt;/span&gt;rust-ui-sciter
cargo add sciter-rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now for our &lt;em&gt;src/main.rs&lt;/em&gt;:&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;fs&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;path&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PathBuf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;sciter&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;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;sciter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Window&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;html_file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;PathBuf&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./app.html"&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;html_file&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;canonicalize&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;html_file_path&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="n"&gt;frame&lt;/span&gt;&lt;span class="nf"&gt;.load_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="nf"&gt;.to_str&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="n"&gt;frame&lt;/span&gt;&lt;span class="nf"&gt;.run_app&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;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We create a new &lt;em&gt;Window&lt;/em&gt; frame with &lt;code&gt;sciter::Window::new()&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;in order to use the &lt;code&gt;.load_file()&lt;/code&gt; we have to pass to it the absolute path of the file &lt;code&gt;.html&lt;/code&gt; to load (or a URL of an online resource). That is why we went to some lenghts to get a &lt;code&gt;PathBuf&lt;/code&gt; and &lt;code&gt;canonicalize&lt;/code&gt; it.&lt;/li&gt;
&lt;li&gt;At the end we just run the app with &lt;code&gt;run_app()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see the content of &lt;em&gt;app.html&lt;/em&gt; (to be put at the root of the project):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Hello, Sciter&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/tiscript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;$append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;#label&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;#click&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click me!&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It is easy enough. By the way, we did not explore the interoperability between Rust and the HTML, and the &lt;em&gt;TIscript&lt;/em&gt; (the Javascript used in Sciter), but of course it is possible (just a little more complex)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GjD1hFJp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/82ttpi2bqnp8g4xlk8m7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GjD1hFJp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/82ttpi2bqnp8g4xlk8m7.jpg" alt="Sciter sample app" width="347" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example Repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davidedelpapa"&gt;
        davidedelpapa
      &lt;/a&gt; / &lt;a href="https://github.com/davidedelpapa/rust-ui-sciter"&gt;
        rust-ui-sciter
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Rust UI Rundown: Sciter
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;Code for part of &lt;a href="https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl" rel="nofollow"&gt;rust-ui-rundown article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/davidedelpapa/rust-ui-sciter"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h3&gt;
  
  
  Tauri &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Getting into some heavy bindings (hevier maybe than even &lt;em&gt;Sciter&lt;/em&gt;). &lt;a href="https://tauri.studio/"&gt;Tauri&lt;/a&gt; lets you give a Desktop GUI to a web based project (&lt;code&gt;HTML&lt;/code&gt;, &lt;code&gt;CSS&lt;/code&gt;, and &lt;code&gt;Javascript&lt;/code&gt;). What is it doing in this list, then? Legitimate question, and in fact I was tempted to kick it out, just like Rust-QT-Binding-Generator. However, there are two considerations in order here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Tauri&lt;/em&gt; bridges the web world to the desktop using Rust, and in fact it allows to use the JavaScript just to give the Graphical side of GUI (exactly as Rust-QT-Binding-Generator uses QML, and this one stayed in the list)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Tauri&lt;/em&gt; bridges two technologies, web and desktop, with Rust as the man-in-the-middle (no security theats involved... maybe!). And since Rust has a good permeation inside the web world with WASM, indeed you start to see how &lt;em&gt;Tauri&lt;/em&gt; can be beneficial in its own right as a GUI option (&lt;em&gt;Tauri&lt;/em&gt; works well also with &lt;em&gt;Yew&lt;/em&gt;, and the likes of it, meaning there can be more than one level of Rust integration)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We'll use &lt;em&gt;Tauri&lt;/em&gt; in conjunction with &lt;a href="https://vuejs.org/"&gt;Vue&lt;/a&gt;, so you have to have a &lt;em&gt;node/npm/yarn&lt;/em&gt; environment first.&lt;br&gt;
EDIT: &lt;code&gt;nodejs&lt;/code&gt; is not required &lt;em&gt;per se&lt;/em&gt; for the project to be ported (it could be just HTML/CSS/JS), but for now it is needed for the CLI, and in future release there's a plan to provide also a pure Rust CLI. &lt;/p&gt;

&lt;p&gt;If you do not have already the Vue cli installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn global add @vue/cli @vue/cli-service-global
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now let's install also the Rust counterpart:&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;tauri-bundler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And finally let's create our project (with Vue this time!!!)&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vue create rust-ui-tauri
&lt;span class="nb"&gt;cd &lt;/span&gt;rust-ui-tauri
vue add tauri
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With &lt;code&gt;vue add tauri&lt;/code&gt; we take care of the Rust part of the project. Wee have to answer some questions like app name (you can leave the default), and Window title.&lt;/p&gt;

&lt;p&gt;Then we can test everything with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn tauri:serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We will see the default Vue homepage, inside a desktop window!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4kv8NwdG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/btxeggmyhrapsi8sgp39.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4kv8NwdG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/btxeggmyhrapsi8sgp39.jpg" alt="VUE in your desktop!" width="803" height="639"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's write some code, shall we?&lt;/p&gt;
&lt;h4&gt;
  
  
  Vue Side
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;src/&lt;/em&gt; is taken by Vue, while &lt;em&gt;src-tauri/&lt;/em&gt; is the Rust root.&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;src/components/&lt;/em&gt; we add another &lt;code&gt;.vue&lt;/code&gt; file besides &lt;code&gt;HelloWorld.vue&lt;/code&gt; which is already there. We call it &lt;em&gt;RustButton.vue&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;{{ msg }}&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"call_rust"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            Click Me!
        &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
import { promisified } from 'tauri/api/tauri'
export default {
  name: 'RustButton',
  methods: {
    call_rust() {
        promisified({
            cmd: 'getResponse',
            payload: {
                state: 1
            }
        }).then(response =&amp;gt; {
            // do something with the Ok() response
            const { message } = response;
            this.msg_set = message;
        }).catch(error =&amp;gt; {
            // do something with the Err() string
            console.log(error);
        })
        console.log('Rust invoked with Promisified!');
    }
  },
  data: function () {
    return {
      msg: ''
    }
  },
  computed: {
    msg_set: {
        set: function (newValue) {
        this.msg = newValue
        },
        get: function () {
            return this.msg
        },
    }
  }
};
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;There could be an optional &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; part, but we do not care for this example.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; contains the rendered part, the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; the logic.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; we set an &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; that will display a variable's value (double brackets as &lt;a href="https://handlebarsjs.com/"&gt;handlebars&lt;/a&gt;). We have also a button with the &lt;code&gt;@click&lt;/code&gt; property that will cull a custom function.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; part we import &lt;code&gt;promisified&lt;/code&gt; from &lt;em&gt;tauri&lt;/em&gt; to use the interface with Rust, and we export a default object with the custom method &lt;code&gt;call_rust()&lt;/code&gt; which is called by the button. This method in turn calls a Rust function &lt;code&gt;getResponse&lt;/code&gt; with a payload object (it is there just to show the interaction between Rust and JS). This is achieved with &lt;code&gt;promisified&lt;/code&gt; which returns a JS &lt;code&gt;promise&lt;/code&gt; that we can consume with &lt;code&gt;.then()&lt;/code&gt; (setting the &lt;code&gt;msg&lt;/code&gt; data to the response of Rust with a custom computed setter). This will be called when the Rust answer comes, only if the answer is a &lt;code&gt;Result::Ok&lt;/code&gt;; if it is a &lt;code&gt;Result::Err&lt;/code&gt; we can catch the error with &lt;code&gt;.catch()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As you can see this is a one-to-one match of a Rust function that returns a &lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;/code&gt;. &lt;code&gt;T&lt;/code&gt; must be serialized, while Tauri takes care of the error with the crate &lt;code&gt;anyhow&lt;/code&gt; (for which we will implement a custom error, just because...)&lt;/p&gt;

&lt;p&gt;There's also another JS function that can call Rust, &lt;code&gt;invoke&lt;/code&gt;, but is more suitable for a one-way communication with Rust.&lt;/p&gt;

&lt;p&gt;As for the rest of Vue, we just need to modify &lt;em&gt;src/App.vue&lt;/em&gt; to call our custom component:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Vue logo"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./assets/logo.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;RustButton&lt;/span&gt; &lt;span class="na"&gt;msg=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;RustButton&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/RustButton.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;RustButton&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; part we can leave as is.&lt;/p&gt;

&lt;p&gt;In practice in the &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt;, instead of calling &lt;code&gt;&amp;lt;HelloWorld&amp;gt;&lt;/code&gt; we call our custom component &lt;code&gt;&amp;lt;RustButton&amp;gt;&lt;/code&gt; with an empty &lt;code&gt;msg&lt;/code&gt; property. We need to import it in the &lt;code&gt;&amp;lt;/script&amp;gt;&lt;/code&gt;, of course, and export it as a custom component in the default object.&lt;/p&gt;

&lt;p&gt;And with this we took care of the Vue side.&lt;/p&gt;
&lt;h4&gt;
  
  
  Rust Side
&lt;/h4&gt;

&lt;p&gt;The Rust side of the force is very strong, as usual... sorry, I mean: it's easy to set everything since Tauri already did some scaffolding for us.&lt;/p&gt;

&lt;p&gt;Inside &lt;em&gt;src-tauri&lt;/em&gt; we have the usual Rust crate root, with &lt;em&gt;Cargo.toml&lt;/em&gt;, the &lt;em&gt;.lock&lt;/em&gt;, even a &lt;em&gt;rustfmt.toml&lt;/em&gt; (I set the indentation to 4 spaces instead of the default 2, :-) )&lt;br&gt;
There's also a configuration file for Tauri in &lt;code&gt;json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What we are interested in is the &lt;em&gt;src/cmd.rs&lt;/em&gt;. Here we need to put some custom data structures to interface with JS, namely the &lt;code&gt;Cmd&lt;/code&gt; itself (which is an &lt;code&gt;enum&lt;/code&gt;), that declares the data for our custom function &lt;code&gt;getResponse&lt;/code&gt; that we set in JS, with &lt;code&gt;payload&lt;/code&gt;, &lt;code&gt;callback&lt;/code&gt;, and &lt;code&gt;error&lt;/code&gt;. We have also to declare the struct &lt;code&gt;Response&lt;/code&gt; to be sent to JS, and a struct representing the payload, which has to mimick the data we get from JS.&lt;/p&gt;

&lt;p&gt;We'll use &lt;em&gt;serde&lt;/em&gt;, that is already set as dependency in the &lt;em&gt;Cargo.toml&lt;/em&gt;&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;serde&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Deserialize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Deserialize)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;GetResponsePayload&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;state&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="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Deserialize)]&lt;/span&gt;
&lt;span class="nd"&gt;#[serde(tag&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cmd"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;rename_all&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"camelCase"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Cmd&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GetResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;GetResponsePayload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&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="nd"&gt;#[derive(Serialize)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&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;pub&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="nb"&gt;str&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;In &lt;em&gt;main.rs&lt;/em&gt; we define a custom Error type (that's just boilerplate). We are more interested in the &lt;em&gt;main()&lt;/em&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;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="nn"&gt;tauri&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;AppBuilder&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;.invoke_handler&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;_webview&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;|&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;cmd&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Cmd&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;match&lt;/span&gt; &lt;span class="nn"&gt;serde_json&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&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="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="nf"&gt;.to_string&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;command&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="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="c1"&gt;// definitions for your custom commands from Cmd here&lt;/span&gt;
                        &lt;span class="n"&gt;GetResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&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;tauri&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;execute_promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                            &lt;span class="n"&gt;_webview&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="k"&gt;move&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;payload&lt;/span&gt;&lt;span class="py"&gt;.state&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                                        &lt;span class="n"&gt;message&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;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&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="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;CommandError&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="s"&gt;"State not OK"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.into&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;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;error&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="nf"&gt;Ok&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="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.run&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 build a Tauri App, with the builder pattern, then we use a closure to manage the interface with JS, using &lt;code&gt;invoke_handler()&lt;/code&gt;, before &lt;code&gt;build()&lt;/code&gt; and &lt;code&gt;run()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside the closure we convert the json object handler and &lt;code&gt;match&lt;/code&gt; over it: if it is &lt;code&gt;Ok&lt;/code&gt; we match the command to see which one we got (there can be more than one invoked by the JS of course).&lt;/p&gt;

&lt;p&gt;If it is our &lt;code&gt;GetResponse&lt;/code&gt;, we execute the promise, that is, we send back the answer. I put an &lt;code&gt;if&lt;/code&gt; guard on the state that we got from JS, just to show the interaction...&lt;/p&gt;

&lt;p&gt;Now everything is set, we can proudly run our app:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rqus7Fc1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/otfjci7mwsh9gso0u3r2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rqus7Fc1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/otfjci7mwsh9gso0u3r2.jpg" alt="tauri sample app" width="804" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example Repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davidedelpapa"&gt;
        davidedelpapa
      &lt;/a&gt; / &lt;a href="https://github.com/davidedelpapa/rust-ui-tauri"&gt;
        rust-ui-tauri
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Rust UI Rundown: Tauri
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;Code for part of &lt;a href="https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl" rel="nofollow"&gt;rust-ui-rundown article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/davidedelpapa/rust-ui-tauri"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h3&gt;
  
  
  VGTK &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/bodil/vgtk"&gt;VGTK&lt;/a&gt;: built on GTK and gtk-rs, above in the list, inspired by Elm, and its inspired Rust counterparts, with a virtualDOM of sorts, like React, and with a sort of JSX for Rust interfaces... Lots to take in at a first date... Ok let's go in to this blind date, and see if it's a love at first glance or not... or maybe if it will become a steady friendhip, why not?&lt;/p&gt;

&lt;p&gt;We need, as for the other GTK based frameworks, a working GTK environment.&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 rust-ui-vgtk
&lt;span class="nb"&gt;cd &lt;/span&gt;rust-ui-vgtk
cargo add vgtk &lt;span class="nt"&gt;--git&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://github.com/bodil/vgtk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If we tried now to build a project from &lt;em&gt;crates.io&lt;/em&gt; version, we would have some weird compilation error. The point is, something strange happened with &lt;code&gt;gdk-pixbuf&lt;/code&gt; version "0.9.0", which is referenced to by &lt;code&gt;vgtk&lt;/code&gt; "0.3.0" in &lt;em&gt;crates.io&lt;/em&gt;. Instead, upon compilation from GitHub, those problems disappear. The only thing is that the compilations times are larger... It seems to be something connected to compiling by default also the docs, but I didn't have time to check it out better.&lt;/p&gt;

&lt;p&gt;And now, let's take a look at our &lt;em&gt;src/main.rs&lt;/em&gt;:&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;vgtk&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ext&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;use&lt;/span&gt; &lt;span class="nn"&gt;vgtk&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;gio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ApplicationFlags&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;vgtk&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;gtk&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;use&lt;/span&gt; &lt;span class="nn"&gt;vgtk&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;gtk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UpdateAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VNode&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Clone,&lt;/span&gt; &lt;span class="nd"&gt;Debug,&lt;/span&gt; &lt;span class="nd"&gt;Default)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Clone,&lt;/span&gt; &lt;span class="nd"&gt;Debug)]&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;UpdateLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Component&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Properties&lt;/span&gt; &lt;span class="o"&gt;=&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;update&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="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;UpdateAction&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&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;match&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nn"&gt;vgtk&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="nn"&gt;UpdateAction&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;UpdateLabel&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="nf"&gt;.to_owned&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="nn"&gt;UpdateAction&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Render&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;fn&lt;/span&gt; &lt;span class="nf"&gt;view&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;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;VNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;gtk!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new_unwrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.example.rustuivgtk"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nn"&gt;ApplicationFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&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;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Window&lt;/span&gt; &lt;span class="n"&gt;border_width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;destroy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HeaderBar&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;"Hello VGTK!"&lt;/span&gt; &lt;span class="n"&gt;show_close_button&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt; &lt;span class="n"&gt;spacing&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nn"&gt;Orientation&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Vertical&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.msg&lt;/span&gt;&lt;span class="nf"&gt;.clone&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;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Button&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Click Me!"&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;clicked&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;UpdateLabel&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Window&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Application&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="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="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;process&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;run&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Model&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;To be honest, according to me it reminds of a fusion between VUE and Yew..., VUE for the code organization, and Yew (inspired by Elm in this) for the pretty recognizable MVC pattern (which is not a classic MVC, there's something peculiar to this that I can't put my finger on... yet).&lt;/p&gt;

&lt;p&gt;As for the code, it is simple enough:&lt;/p&gt;

&lt;p&gt;We have to build a model and a message system, as usual in these Elm-inspired frameworks; then we need to implement a model with an &lt;code&gt;update()&lt;/code&gt; function to handle the messages, and a &lt;code&gt;view()&lt;/code&gt; function to render the interface.&lt;/p&gt;

&lt;p&gt;The model derives &lt;code&gt;Default&lt;/code&gt;, so there's no need for initialization (which would get much more verbose).&lt;br&gt;
The &lt;code&gt;view()&lt;/code&gt; employs the macro &lt;code&gt;gtk!&lt;/code&gt; which is like JSX, but for GTK interfaces.&lt;/p&gt;

&lt;p&gt;The result, for you:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZWaTLeJY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sggs5eboiw6919dwyvyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZWaTLeJY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sggs5eboiw6919dwyvyq.png" alt="VGTK sample app" width="274" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All in all it's not bad, the structure is clean enough, and the handling of the &lt;code&gt;gtk!&lt;/code&gt; is neat: it seems really to be in a web based environment, and the limited testing I have done show that the framework is powerful enough. I will definitely go deeper with this framework.&lt;/p&gt;

&lt;p&gt;Example Repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davidedelpapa"&gt;
        davidedelpapa
      &lt;/a&gt; / &lt;a href="https://github.com/davidedelpapa/rust-ui-vgtk"&gt;
        rust-ui-vgtk
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Rust UI Rundown: VGTK
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;Code for part of &lt;a href="https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl" rel="nofollow"&gt;rust-ui-rundown article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/davidedelpapa/rust-ui-vgtk"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Back to Summary&lt;/p&gt;



&lt;h1&gt;
  
  
  Not working at all!
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Azul &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/maps4print/azul"&gt;Azul&lt;/a&gt;: there was a broken dependencies. This crates is being developed, &lt;strong&gt;slowly&lt;/strong&gt; so the bug might me fixed any time soon. Still, right now it is very promising, but unusable.&lt;/p&gt;

&lt;p&gt;Back to Summary&lt;/p&gt;
&lt;h2&gt;
  
  
  QT_Widgets &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/qt_widgets"&gt;QT_Widgets&lt;/a&gt; is a Rust Qt binder from &lt;a href="https://github.com/rust-qt/ritual"&gt;Ritual&lt;/a&gt;, a C++ to Rust wrapping project. Not too well documented, it is a series of &lt;code&gt;unsafe&lt;/code&gt; wrappers for the various C++ QT libraries.&lt;/p&gt;

&lt;p&gt;I tried to make it work in a few ways, I even submitted an issue and a pull request for a bug, but as is the crate is not working. Maybe the situation will change, and I'll inform you soon.&lt;/p&gt;

&lt;p&gt;Back to Summary&lt;/p&gt;



&lt;h1&gt;
  
  
  Other Issues
&lt;/h1&gt;

&lt;p&gt;In fairness I have collected here some other crates that I didn't even try or that I tried but have some other issues:&lt;/p&gt;
&lt;h2&gt;
  
  
  Don't belong to the list according to me
&lt;/h2&gt;

&lt;p&gt;Maybe I am a little too opinionated, but still:&lt;/p&gt;
&lt;h3&gt;
  
  
  Rust-QT-Binding-Generator &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/rust-qt-binding-generator"&gt;Rust-QT-Binding-Generator&lt;/a&gt;: it creates bindings for Rust and QT so that you can call Rust code from inside a QT interface. &lt;/p&gt;

&lt;p&gt;The homepage says "it helps to create a Qt based GUI on top of Rust code". In reality it is not the case that you can use QT from a Rust program, but instead you have to write a QT program (in C++ and/or QML) and import the Rust code.&lt;/p&gt;

&lt;p&gt;No way I am considering this as a Rust GUI project. It is useful in its own right, but not as a Rust GUI.&lt;/p&gt;

&lt;p&gt;Back to Summary&lt;/p&gt;
&lt;h3&gt;
  
  
  WebRender &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The folks at &lt;em&gt;AreWeGuiYet&lt;/em&gt; put in the list also &lt;a href="https://crates.io/crates/WebRender"&gt;WebRender&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This does not belong to a GUI framework list, sorry: it is very low level! At this point we should add also the bindings for GDK, Cairo, etc... &lt;/p&gt;

&lt;p&gt;In this I disagree: it is true you can render a GUI with WebRender (as you could with the bare cairo bindings, why not?), but this does not mean WebRender is a GUI framework.&lt;/p&gt;

&lt;p&gt;Back to Summary&lt;/p&gt;
&lt;h2&gt;
  
  
  Immediate Mode "GUIs"
&lt;/h2&gt;

&lt;p&gt;I have found a lot of immediate mode GUIs, which I purposely took out of the list: immediate mode GUIs belong to the gaming world, not to the Desktop Applications world. &lt;/p&gt;

&lt;p&gt;Unless you have done a GUI in Blender's Style, that is useful also outside the realm of Graphics... at this point, let's discuss about it!&lt;/p&gt;

&lt;p&gt;Here I present the two most used (and that are present in &lt;em&gt;AreWeGUIYet&lt;/em&gt;, but shouldn't):&lt;/p&gt;
&lt;h3&gt;
  
  
  Conrod &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/pistondevelopers/conrod"&gt;Conrod&lt;/a&gt; is tied to the &lt;a href="https://docs.rs/piston/latest"&gt;Piston Game Engine&lt;/a&gt;. Indeed it is its conception of User Interface.&lt;/p&gt;

&lt;p&gt;There's often some dependency issue with &lt;a href="https://xcb.freedesktop.org/"&gt;XCB&lt;/a&gt;, needed by the &lt;a href="https://crates.io/crates/xcb"&gt;xcb crate&lt;/a&gt;. In that case, you might need some or all of the following:&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;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;xcb xcb-proto libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxcb-xrm-dev libxcb1-dev libxkbcommon-dev  libxcb-keysyms1-dev libxcb-xrm0 libxcb-shape0-dev&lt;span class="se"&gt;\&lt;/span&gt;
libxcb-util0-dev libxcb-cursor-dev  libxkbcommon-x11-dev libxcb-xfixes0-dev   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just check what the linker complains about (remember to take off the initial "l"; so if it's "-lxcb-shape: missing", you know you need &lt;code&gt;xcb-shape&lt;/code&gt;, found in &lt;code&gt;libxcb-shape0-dev&lt;/code&gt;, etc...)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What works&lt;/strong&gt;: the examples&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/PistonDevelopers/conrod.git
&lt;span class="nb"&gt;cd &lt;/span&gt;conrod
cargo run &lt;span class="nt"&gt;--release&lt;/span&gt; &lt;span class="nt"&gt;--example&lt;/span&gt; all_winit_glium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The examples are found in &lt;em&gt;conrod/backends/conrod_glium/examples&lt;/em&gt; take a look there if you are interested.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does not work&lt;/strong&gt;: making a simple UI by yourself.&lt;/p&gt;

&lt;p&gt;Now, I could not reproduce any of the examples and modify it: all the examples depend on some other module that is in there, with no explanation.&lt;/p&gt;

&lt;p&gt;There's also an unfinished &lt;a href="https://docs.rs/conrod_core/0.71.0/conrod_core/guide/"&gt;official guide&lt;/a&gt;, but I found myself at loss nevertheless.&lt;/p&gt;

&lt;p&gt;There is not a single/simple way of understanding what is going on, what we are required to do, and most of all, why.&lt;/p&gt;

&lt;p&gt;What can I say? Maybe if you are in the know about Piston you swim easily in &lt;em&gt;Conrod&lt;/em&gt;, but otherwise it seems just mumbo-jumbo to me.&lt;/p&gt;

&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h3&gt;
  
  
  ImGui &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/Gekkio/imgui-rs"&gt;imgui&lt;/a&gt; is a Rust binding for &lt;a href="https://github.com/ocornut/imgui"&gt;Dear ImGui&lt;/a&gt;... Oh, dear! This is the same blessed way of doing things as &lt;em&gt;Conrod&lt;/em&gt;: a lot of boilerplate inside a folder in the examples, that even if you copy it to your own project doesn't work!&lt;/p&gt;

&lt;p&gt;Why, I say, why don't they make all the support boilerplate &lt;strong&gt;inside&lt;/strong&gt; of the project? why a stupid folder in the examples? Is it too much to ask for a &lt;strong&gt;working minimal example&lt;/strong&gt; when you are just learning about a new library?&lt;/p&gt;

&lt;p&gt;Anyway, the working examples are as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Gekkio/imgui-rs
&lt;span class="nb"&gt;cd &lt;/span&gt;imgui-rs
git submodule update &lt;span class="nt"&gt;--init&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;imgui-examples
cargo &lt;span class="nb"&gt;test
&lt;/span&gt;cargo run &lt;span class="nt"&gt;--example&lt;/span&gt; hello_world
cargo run &lt;span class="nt"&gt;--example&lt;/span&gt; test_window
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The state of these projects is a pity, but I wonder: there are 70 contributors to this package, and the GitHub repo has 1.1k stars.&lt;/p&gt;

&lt;p&gt;Can anybody make a stupid example, a tutorial, something for the rest of us? Please! Searching online gets results dated 2018 at best, on stuff I could not try, or even some 404 errors!!!&lt;/p&gt;

&lt;p&gt;I would expect something, even minimal, to grasp at, from a project with 1.1k stars!&lt;/p&gt;

&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h2&gt;
  
  
  Could Not Try: Core-Foundation &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Maybe it's the best tool around in the Mac world, I don't know, but I could not try &lt;a href="https://github.com/servo/core-foundation-rs"&gt;Core-Foundation&lt;/a&gt;, because I do not own a Mac.&lt;/p&gt;

&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h2&gt;
  
  
  Could Not Try: LittlevGL &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This one is different: &lt;a href="https://crates.io/crates/lvgl"&gt;LittlevGL&lt;/a&gt; runs on embedded systems. I could not try it, but I look forward to get a Raspberry o something similar, and play a little with Rust in embedded systems.&lt;/p&gt;

&lt;p&gt;Back to Summary&lt;/p&gt;

&lt;h2&gt;
  
  
  Could Not Try: KAS &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I tried with the GTK back-end, which is not working at all, but the main &lt;a href="https://crates.io/crates/KAS"&gt;KAS&lt;/a&gt; crate employs Vulkan, for which I do not have any compatible hardware...&lt;br&gt;
I could not try it out, sorry.&lt;/p&gt;

&lt;p&gt;Currently, KAS's only drawing method is WebGPU which requires DirectX 11/12, Vulkan or Metal. In the future, there may be support for OpenGL and software rendering.&lt;/p&gt;

&lt;p&gt;I do not have hardware support for vulkan. I tryed the &lt;a href="https://crates.io/crates/kas-gtk"&gt;GTK backend&lt;/a&gt; enabling Rust nightly (&lt;code&gt;rustup override set nightly&lt;/code&gt; in the project root folder). Sadly it didn't work&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Compiling kas-gtk v0.0.2
error[E0635]: unknown feature `const_vec_new`
 --&amp;gt; /home/&amp;lt;*&amp;gt;/.cargo/registry/src/github.com-1ecc6299db9ec823/kas-gtk-0.0.2/src/lib.rs:8:12
  |
8 | #![feature(const_vec_new)]
  |            ^^^^^^^^^^^^^

error: aborting due to previous error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope to see improvements on the GTK back-end, so that at least I can try it on my machine (or to see an improvement in my salary in order to start owning better machines... but I do not think that is coming around any time soon).&lt;/p&gt;

&lt;p&gt;Back to Summary&lt;/p&gt;



&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;I tried over the past three months a lot of different crates. Right before publishing I even made sure they are all working properly.&lt;/p&gt;

&lt;p&gt;Some crates do work, some crated do not. In my opinion, those who work should be merit-signalled, those who don't should be helped to get to a minimal usable product.&lt;/p&gt;

&lt;p&gt;It is a shame that in the Rust ecosystem the GUI world is so mistreated. Granted, even in other languages the situation is not simple at all, but if Rust wants to take a spot out of the niche, as a mainstream language, curating the GUI state would be largely profitable.&lt;/p&gt;

&lt;p&gt;Hope this little work of mine can help you getting your hands dirty with Rust GUI programming.&lt;/p&gt;

&lt;p&gt;'Till next time!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>gui</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Which Rust crate to use as GUI framework right now (Jan 2021)?</title>
      <dc:creator>Davide Del Papa</dc:creator>
      <pubDate>Sat, 16 Jan 2021 23:48:55 +0000</pubDate>
      <link>https://dev.to/davidedelpapa/which-rust-crate-to-use-as-gui-framework-right-now-jan-2021-4opm</link>
      <guid>https://dev.to/davidedelpapa/which-rust-crate-to-use-as-gui-framework-right-now-jan-2021-4opm</guid>
      <description>&lt;p&gt;[&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@aquatium?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Harpal Singh&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/ui-design?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;, modified]&lt;/p&gt;

&lt;p&gt;I am writing a post on the subject of Rust GUI, and sadly I am realizing that no much progress has been done in this area lately.&lt;/p&gt;

&lt;p&gt;The site &lt;a href="https://www.areweguiyet.com/"&gt;AreWeGUIYet&lt;/a&gt; seems almost abandoned to its own fate...&lt;/p&gt;

&lt;p&gt;Thus I am polling you guys to know which Rust crate would you recommend to use in 2021 in order to give a Rust program a nice GUI?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>rust</category>
    </item>
    <item>
      <title>Dev DigitalOcean Hackathon: Geobot, a Geography Python Twitter Bot - Submission Form</title>
      <dc:creator>Davide Del Papa</dc:creator>
      <pubDate>Mon, 11 Jan 2021 01:04:47 +0000</pubDate>
      <link>https://dev.to/davidedelpapa/dev-digitalocean-hackathon-geobot-a-geography-python-twitter-bot-submission-form-250a</link>
      <guid>https://dev.to/davidedelpapa/dev-digitalocean-hackathon-geobot-a-geography-python-twitter-bot-submission-form-250a</guid>
      <description>&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;Geobot, a Geography Python Server and Twitter Bot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Category Submission:
&lt;/h3&gt;

&lt;p&gt;Program for the People&lt;/p&gt;

&lt;h3&gt;
  
  
  App Link
&lt;/h3&gt;

&lt;p&gt;Main server: &lt;a href="https://geobot-hcm6d.ondigitalocean.app/"&gt;https://geobot-hcm6d.ondigitalocean.app/&lt;/a&gt;&lt;br&gt;
The Twitter handle is: &lt;a href="https://twitter.com/geobotshow/"&gt;@geobotshow&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ISDNAvcg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/i4ohiux5ay19azxsb233.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ISDNAvcg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/i4ohiux5ay19azxsb233.png" alt="The TwitterBot showing a location" width="599" height="398"&gt;&lt;/a&gt;&lt;br&gt;
The TwitterBot showing a location.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cSVliOGN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vy4horop0c3h4czzpvkq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cSVliOGN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vy4horop0c3h4czzpvkq.png" alt="The API showing a bounding-box location" width="600" height="600"&gt;&lt;/a&gt;&lt;br&gt;
The API showing a bounding-box location.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4ebWex2W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lcmpckgtd4524n3j9uj4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4ebWex2W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lcmpckgtd4524n3j9uj4.png" alt="The API showing a location with some POI" width="600" height="480"&gt;&lt;/a&gt;&lt;br&gt;
The API showing a location near a point, with some Points of Interest (POI): fountains and drinkable water.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E3c88wQB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/te1jkxb7z5ft7ayl49nu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E3c88wQB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/te1jkxb7z5ft7ayl49nu.png" alt="The TwitterBot showing an earthquake" width="610" height="435"&gt;&lt;/a&gt;&lt;br&gt;
The TwitterBot showing an earthquake.&lt;/p&gt;

&lt;h3&gt;
  
  
  Description
&lt;/h3&gt;

&lt;p&gt;The project aims to provide a platform for  geographic data images and enhancements such a search of Points of Interest (POI). The server relies on a custom library that is quite extensible.&lt;/p&gt;

&lt;p&gt;Besides the server, as a showcase, there's a TwitterBot that can show the user's location upon request, and has a service to shows location and info on recent earthquakes (data from USGS)&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Source Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/davidedelpapa/geobot"&gt;Geo-Server: https://github.com/davidedelpapa/geobot&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/davidedelpapa/geobotshow"&gt;TwitterBot: https://github.com/davidedelpapa/geobotshow&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Permissive License
&lt;/h3&gt;

&lt;p&gt;MIT for both&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I was always interested in geography and visualization. The point is that a map is the most packed and effective data visualization created by man, and yet everyone can read it quite profitably. &lt;/p&gt;

&lt;p&gt;The recent years' satellite development has shown that we can combine maps with satellite images, that is, using actual images of some places, instead of mere representations (classic maps), and still map on them also some representations (points of interest, roads, color the map according to some pattern...). This demonstrates how far can the boundaries of visualization being pushed, and still obtain easily understandable results.&lt;/p&gt;

&lt;p&gt;Besides these considerations, many think the market for end consumers geography applications is getting reaper by the day. The ecosystem to use as source is ripe enough (with free and opensource geographic datasets and imagery). Yet, there's quite a lack on the other side of the spectrum, the end customers applications: it seems as we did not yet understand how to profit of the immense power of geographic data.&lt;/p&gt;

&lt;p&gt;This app shows an example of how to build a simple, yet extensible geographic system. In fact the server can be extended to add more endpoints, in order to exploit the power of the library, and also the twitterbot can take advantage of other aspects of the API.&lt;/p&gt;

&lt;p&gt;Moreover, the twitterbot can be swapped for, or paired with, many other communication bots, all referring to the same GeoServer, such as a TelegrmBot, or any other bot that can be built on top of social networks or communication systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I built it
&lt;/h3&gt;

&lt;p&gt;The app actually uses two components. This means that there is not only a container for the main app (the server), but also one for a worker (the twitterbot).&lt;/p&gt;

&lt;p&gt;Sadly, there are not many information on how to pair a service with a worker, so I had to find ways by exploring by myself. &lt;/p&gt;

&lt;p&gt;At the beginning I explored ways to use directly the Python components inside a Docker image.&lt;br&gt;
In fact, preparation for the Hackathon, I made some tests and a tutorial on how to deploy, through Docker images, any non supported Language. See &lt;a href="https://dev.to/davidedelpapa/digital-ocean-app-platform-hackathon-using-not-natively-supported-platforms-rust-rocket-55og"&gt;here my article on deploying a Rust server&lt;/a&gt;. At the beginning in fact I was leaning on building the server in Rust, and the bot in Python.&lt;/p&gt;

&lt;p&gt;However, after some trial and error I made it to work as intended, with two components.&lt;/p&gt;

&lt;p&gt;The procedure though is not yet perfect; for example I could manage to put a Deploy to Do button to work correctly only with one component at a time. I did not find a way to reproduce my two components setting so far.&lt;/p&gt;

&lt;p&gt;I also abandoned the idea of developing the server in Rust, mainly because it is still a niche language, not profitable by many people. I wanted this to be a project that many people can pick up, thinker with, extend, adapt... Of course I did not abandon completely the idea of rewriting a server in Rust, but I'm waiting also to see if it will be supported by the DigitalOcean App Platform natively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources/Info
&lt;/h3&gt;

&lt;p&gt;Data Providers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.mapbox.com/"&gt;Mapbox&lt;/a&gt;: The tiles images&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wiki.openstreetmap.org/"&gt;OpenStreetMap&lt;/a&gt;: PoI location&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.usgs.gov/"&gt;USGS&lt;/a&gt;: Earthquakes position and information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Useful information and algorithms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://wiki.openstreetmap.org/wiki/Slippy_Map"&gt;Slippy Map Introduction&lt;/a&gt;: What is a slippy map? Useful for total beginners&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames"&gt;Tiles to LongLat and viceversa&lt;/a&gt;: an article by OpenStreetMap with many languages implementation of the basic algorithms&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.edwilliams.org/avform.htm"&gt;Aviation Formulary&lt;/a&gt;: It has got many formulas, many approximation algorithms... It is a mine for geo-math&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dohackathon</category>
    </item>
    <item>
      <title>Dev DigitalOcean Hackathon: Geobot, a Geography Python Twitter Bot - Tut 03</title>
      <dc:creator>Davide Del Papa</dc:creator>
      <pubDate>Mon, 11 Jan 2021 00:06:00 +0000</pubDate>
      <link>https://dev.to/davidedelpapa/dev-digitalocean-hackathon-geobot-a-geography-python-twitter-bot-tut-03-9mk</link>
      <guid>https://dev.to/davidedelpapa/dev-digitalocean-hackathon-geobot-a-geography-python-twitter-bot-tut-03-9mk</guid>
      <description>&lt;p&gt;[&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@andrewtneel?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Andrew Neel&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/map?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;, modified(crop)]&lt;/p&gt;

&lt;p&gt;In the previous installments we laid the foundations for our infrastructure.&lt;br&gt;
It is time now to produce some maps!&lt;/p&gt;

&lt;p&gt;Please notice that this cannot be a detailed tutorial, it is more like a quick summary of the work done, with some commentary.&lt;/p&gt;
&lt;h2&gt;
  
  
  Mapbox
&lt;/h2&gt;

&lt;p&gt;When I first started doing web maps there were less tools and companies involved in the process. As of today many companies have come and gone, so it is difficult sometimes for an lay man to get started in geography. &lt;/p&gt;

&lt;p&gt;That is why you have to sort of trust me in this. For this project we will not use Google Maps, although it is a very popular and trusty too. We will use &lt;a href="https://www.mapbox.com/"&gt;Mapbox&lt;/a&gt;, also because even though it s less known, in the open source web map world is gaining lot of traction.&lt;/p&gt;

&lt;p&gt;Point your browser to the &lt;a href="https://account.mapbox.com/auth/signup/"&gt;Mapbox registration page&lt;/a&gt; if you do not yet have an account, and follow the easy instructions&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IgWWpSxH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aqxj89vv9ddbhxbh6qbt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IgWWpSxH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aqxj89vv9ddbhxbh6qbt.png" alt="Alt Text" width="880" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After confirming your email you can go to your &lt;a href="https://account.mapbox.com/"&gt;account page&lt;/a&gt; in order to generate a new &lt;code&gt;token&lt;/code&gt; (an API key)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kJRtxJ2f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k8lpw7psqmwkebvg24i7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kJRtxJ2f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k8lpw7psqmwkebvg24i7.png" alt="Alt Text" width="880" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have created a token, we need to save it on an &lt;em&gt;.env&lt;/em&gt; file to be put inside the &lt;strong&gt;service&lt;/strong&gt; repository, not the bot.&lt;/p&gt;

&lt;p&gt;Here we did not have an &lt;em&gt;.env&lt;/em&gt; file, so just create one&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAPBOX_TOKEN=***
MAPBOX_URL=https://api.mapbox.com/v4/mapbox.satellite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will use the URL later on.&lt;/p&gt;

&lt;p&gt;Now we will see how to use that token&lt;/p&gt;

&lt;h2&gt;
  
  
  Web Maps
&lt;/h2&gt;

&lt;p&gt;There are several standards for web maps, however here we will use a not so standard &lt;a href="https://wiki.openstreetmap.org/wiki/Slippy_Map"&gt;slippy map&lt;/a&gt;, which is sort of WTMS, but it follows the standards loosely.&lt;/p&gt;

&lt;p&gt;What we need to know is the following: the map gets rendered at different zoom levels as a &lt;em&gt;mosaic&lt;/em&gt;, that is, a series of tiles, or square 256×256 pixel images, one besides the other. if you zoom in, each tile is subdivided in 4 tile, if you zoom out, 4 tiles are collapsed into one tile.&lt;/p&gt;

&lt;p&gt;The zoom level &lt;code&gt;1&lt;/code&gt; shows the whole world inside a single tile, at zoom level 2 the world fits neatly in 4 tiles, while at zoom level 3 there are 16 tiles to represent the whole world.&lt;/p&gt;

&lt;p&gt;I think this is sufficient as a quick introduction to the subject matter.&lt;br&gt;
However, there's still a problem: how to get locate on a map any geographic point (usually given in the latitude/longitude notation)?&lt;/p&gt;

&lt;p&gt;There's a mathematical equation that does this, and if you want to know more, read &lt;a href="https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames"&gt;this article by OpenStreetMap&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These are the two formulas:&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;deg2num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lat_deg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lon_deg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zoom&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;lat_rad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;radians&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lat_deg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;zoom&lt;/span&gt;
    &lt;span class="n"&gt;xtile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;lon_deg&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;180.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;360.0&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ytile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;asinh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lat_rad&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&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;xtile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ytile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the reverse:&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;num2deg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xtile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ytile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zoom&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;zoom&lt;/span&gt;
    &lt;span class="n"&gt;lon_deg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xtile&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;360.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;180.0&lt;/span&gt;
    &lt;span class="n"&gt;lat_rad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;atan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sinh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ytile&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="n"&gt;lat_deg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;degrees&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lat_rad&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;lat_deg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lon_deg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For both we need to &lt;code&gt;import Math&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Get a Map of a Bounding Box
&lt;/h2&gt;

&lt;p&gt;Time for action!&lt;/p&gt;

&lt;p&gt;We will do the following&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define an API interface to get a Map as an image, given a bounding box (W, N, E, S)&lt;/li&gt;
&lt;li&gt;Retrieve the necessary tiles&lt;/li&gt;
&lt;li&gt;Process those tiles into an image&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Easy? Let's see...&lt;/p&gt;

&lt;p&gt;First things first: &lt;a href="https://docs.mapbox.com/api/maps/static-images/"&gt;Mapbox already has a static image API&lt;/a&gt;, that gets you an image out of a bounding box (it actually has some good advanced options).&lt;/p&gt;

&lt;p&gt;So, why don't we use it? Well, we could use it, but we will not be able to customize much the experience for our users, let alone making this a more universal geography system.&lt;/p&gt;

&lt;p&gt;Therefore, if it is needed as quick-fix to scaffold the structure we can use ready made functions, but if we want to squeeze out something more for the user experience, we need to go the indie way.&lt;/p&gt;

&lt;p&gt;That said, let's go forth and create the API interface.&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;source &lt;/span&gt;venv/bin/activate
pip &lt;span class="nb"&gt;install &lt;/span&gt;urllib3 Pillow geojson overpy
pip freeze &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We installed the following packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;urllib3&lt;/code&gt; handles connections&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Pillow&lt;/code&gt; is for image manipulations&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;geojson&lt;/code&gt; handle a specification of JSON called GeoJSON used for transferring geographic data as JSON (&lt;a href="https://en.wikipedia.org/wiki/GeoJSON"&gt;Wiki article&lt;/a&gt; and the &lt;a href="https://tools.ietf.org/html/rfc7946"&gt;Official Specification&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;overpy&lt;/code&gt; is a tiny layer for requests to the &lt;a href="https://wiki.openstreetmap.org/wiki/Overpass_API"&gt;Overass API&lt;/a&gt;; it allows to query the data from the &lt;a href="https://wiki.openstreetmap.org"&gt;OpenStreetMap&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The API will be defined as follows:&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="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/api/bbox/&amp;lt;float:w&amp;gt;/&amp;lt;float:n&amp;gt;/&amp;lt;float:e&amp;gt;/&amp;lt;float:s&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show_bbox&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;n&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="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need a function to retrieve the tiles from the tile-server and one to process those tiles into a single file.&lt;/p&gt;

&lt;p&gt;I've made a custom library that does just that. But it took me the most part of this hackathon!&lt;/p&gt;

&lt;p&gt;The library is in the folder &lt;em&gt;geobot/&lt;/em&gt; of the repository. I will quickly review what each component does.&lt;br&gt;
Bear in mind that this was a quick development, not everything has been documented properly. &lt;/p&gt;
&lt;h3&gt;
  
  
  The geo.py Geographic utilities
&lt;/h3&gt;

&lt;p&gt;Here there are some classes (some dataclass actually) and helper functions to deal with the geographic coordinates (Latitude, Longitude)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;LonLat&lt;/code&gt; represents a point as (Latitude, Longitude) coordinates&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Tile&lt;/code&gt; represents a bounding box, with coordinates (West, North, East, South)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Tile&lt;/code&gt; represents a tile to be got from the tile-server&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  The tileget.py Interface with the tile-server
&lt;/h3&gt;

&lt;p&gt;It contains a class, &lt;code&gt;Tileget&lt;/code&gt;, that handles the tile retrieval from the tile-server&lt;/p&gt;
&lt;h3&gt;
  
  
  The temps.py Temporary Files and Folders Utilities
&lt;/h3&gt;

&lt;p&gt;In the Python standard library there are already means to get Temporary Files and Folders ; however, here we need them temporary, but they have to get around quite a lot... We needed something different to handle our images.&lt;/p&gt;
&lt;h3&gt;
  
  
  The tiledraw.py Tile-to-Image Interface
&lt;/h3&gt;

&lt;p&gt;Tiles from a tile-server are not only images. They are geo-referenced images, that is, they carry their geographic location information about them.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Dtile&lt;/code&gt; class handles tiles that can be drawn upon. It has got a simplistic (for now) way of rendering GeoJSON on them, add a watermark for copyright notices, resize and crop, maintaining the geographic information needed even after the image manipulations.&lt;/p&gt;
&lt;h3&gt;
  
  
  The overpass.py OSM Data Interface for GeoJSON
&lt;/h3&gt;

&lt;p&gt;There are some helper classes and functions to retrieve information from OpenStreetMap, and render it as GeoJSON. &lt;/p&gt;

&lt;p&gt;As for now it is just a stub, but it should be more developed, in order to get some POI, Points of Interests out of the map and mark them on the images&lt;/p&gt;
&lt;h3&gt;
  
  
  The tiledraw.py Tile Render Engine
&lt;/h3&gt;

&lt;p&gt;Here we have the utilities to download the tiles, prepare an image out of those tiles, and render it as normal image&lt;/p&gt;
&lt;h2&gt;
  
  
  The Working Endpoints
&lt;/h2&gt;

&lt;p&gt;For now, only two endpoints are working&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="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/api/bbox/&amp;lt;float:w&amp;gt;/&amp;lt;float:n&amp;gt;/&amp;lt;float:e&amp;gt;/&amp;lt;float:s&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This endpoint returns a bounding box image.&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="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/api/point/&amp;lt;float:lon&amp;gt;/&amp;lt;float:lat&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This endpoint calculates a bounding box near the specified point and returns the image.&lt;/p&gt;

&lt;p&gt;Testing locally, we can see that easily working.&lt;br&gt;
We need to run the local gunicorn server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gunicorn app:app 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NOTE, if it is not working, maybe you need to get the environment file to be read by the virtualenv:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deactivate
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"set -a; source &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/.env; set +a"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; venv/bin/activate
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$MAPBOX_URL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it works, in a separate shell, we ask for the file image:&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;--output&lt;/span&gt; file.png &lt;span class="s1"&gt;'http://127.0.0.1:8000/api/bbox/14.141636/42.522977/14.184637/42.497605'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7_YB28sv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m1p9e87gqvaxjjf7fwiz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7_YB28sv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m1p9e87gqvaxjjf7fwiz.png" alt="Alt Text" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also ask for an image near a point, let's say, in a 30 meters radius:&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;--output&lt;/span&gt; file.png &lt;span class="s1"&gt;'http://127.0.0.1:8000/api/point/14.141636/42.522977?near=30'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZljQ2qqv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wf7105vahqjeoox2wnrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZljQ2qqv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wf7105vahqjeoox2wnrw.png" alt="Alt Text" width="300" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that the Geobot performs an harmonious scaling, basically maintaining some of the proportions of the tile-set it retrieved according to the geographic detail needed. In this way, if a bounding-box belongs to 2 vertical tiles, you will see an image taller than higher, not a square image. &lt;/p&gt;

&lt;p&gt;If you want to search for bounding box to try to show, I recommend visiting the following site:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://bboxfinder.com/"&gt;http://bboxfinder.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try it, and build your own queries.&lt;/p&gt;

&lt;p&gt;Last, but not least, the GeoJSON capabilities. Both endpoints in fact can render arbitrary GeoJSON&lt;/p&gt;

&lt;p&gt;I left a GeoJSON test file in &lt;em&gt;examples/&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can use it as follows:&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;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; @examples/fountains.geojson &lt;span class="nt"&gt;--output&lt;/span&gt; file.png &lt;span class="s1"&gt;'http://127.0.0.1:8000/api/bbox/14.141636/42.522977/14.184637/42.497605?cropped=1'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that adding the cropped parameter crops the image to the bounding-box, before scaling it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ScClYHRA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jawal3yu9b773dkixfyt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ScClYHRA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jawal3yu9b773dkixfyt.png" alt="Alt Text" width="600" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The GeoJSON used was extracted with a Overpass Query from OSM data, transformed to GeoJSON and fed to the endpoint.&lt;/p&gt;

&lt;p&gt;The same result can be obtained using the &lt;code&gt;api/poi_bbox/&lt;/code&gt; endpoint. This endpoint accepts some Point of Interest (PoI) names to search with Overpass inside the bounding-box.&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;examples/&lt;/em&gt; there's a file calld &lt;em&gt;poi.json&lt;/em&gt; containing the query to be fed to the &lt;code&gt;api/poi_bbox/&lt;/code&gt; endpoint. The format is really simple: an object with a &lt;code&gt;'poi'&lt;/code&gt; key, and a list of names of Point of Interest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"poi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"fountain"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"drinking_water"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can feed it to the API as such:&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;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; @examples/poi.json &lt;span class="nt"&gt;--output&lt;/span&gt; file.png &lt;span class="s1"&gt;'http://127.0.0.1:8000/api/poi_bbox/14.141636/42.522977/14.184637/42.497605'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YuW4vVY0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/r8yuh9zk9fv02jm9ec69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YuW4vVY0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/r8yuh9zk9fv02jm9ec69.png" alt="Alt Text" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This time the resulting image was not cropped, but the search has been done only inside the bounding-box, that is why the image covers more area (according to the tiles downloaded), but the markers are shown only for certain elements (again, only those inside the bounding-box). That is why in this setting the cropping utility works best.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interfacing the TwitterBot
&lt;/h2&gt;

&lt;p&gt;From a tweet we can get the location; we are going to exploit this in order to get a map near the user location.&lt;/p&gt;

&lt;p&gt;Notice that the user has to have allowed beforehand the position in their Twitter interface, otherwise there will not be any information.&lt;/p&gt;

&lt;p&gt;The information itself can be in several places, marked as &lt;code&gt;coordinates&lt;/code&gt;. For this reason, we have to try several things. Also the information can be as a pint, or as a bounding box, according as the user specified a simple point location or a place (extended).&lt;/p&gt;

&lt;p&gt;Besides, the information can be presented as a Geometry or otherwise... We will use a regex to extract the coordinates, and parse them.&lt;/p&gt;

&lt;p&gt;It's long and tedious, but it must be done... &lt;/p&gt;

&lt;p&gt;At the end, mentioning the bot in a geo-located setting works...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LAsF06Ca--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pyn9d38pyfmn9illf3xe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LAsF06Ca--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pyn9d38pyfmn9illf3xe.png" alt="Alt Text" width="484" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, if the location is not precise (for example, selecting the city, instead than the neighborhood or a nearby Point of Interest) results in more errors than nothing&lt;/p&gt;

&lt;p&gt;In fact, above I was hoping it showed the city, and instead it showed an arbitrary point inside the city.&lt;/p&gt;

&lt;p&gt;This happens because the coordinates provided by Twitter are not so ideal&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LnVCyoRU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4996c10zkoppqm1nh5b3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LnVCyoRU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4996c10zkoppqm1nh5b3.png" alt="Alt Text" width="599" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here instead I put a famous local bar as location, and it got me the image all-right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developing some more
&lt;/h2&gt;

&lt;p&gt;Just to show a little bit the power of the underlying platform, I refactored the code and added a new function.&lt;/p&gt;

&lt;p&gt;THis new function basically checks for earthquakes through the &lt;a href="https://pypi.org/project/quakefeeds/"&gt;quakefeeds&lt;/a&gt; library, which uses the web services provided by the &lt;a href="https://earthquake.usgs.gov/fdsnws/event/1/"&gt;USGS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In practice it searches for the last earthquakes (last hours), for new ones. The level is set to retrieve only the significant ones, but it can be tweaked to some magnitude levels, or to get them all.&lt;/p&gt;

&lt;p&gt;Once it retrieves the information, it creates a message with the most important points, and a link to the info on the earthquake at the USGS's site.&lt;/p&gt;

&lt;p&gt;Then it retrieves a map centered on the epicenter with a 10km radius from the Geobot server.&lt;br&gt;
Finally it posts the picture with the relevant information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XXUe5-eC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2eib7nds66aqtdhzd8g9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XXUe5-eC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2eib7nds66aqtdhzd8g9.png" alt="Alt Text" width="610" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and future developments
&lt;/h2&gt;

&lt;p&gt;We have shown so far a series of capabilities of the library we've created, and the API developed so far.&lt;br&gt;
However, the library allows for much more than what covered in the API.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the library is capable of customize the markers, the colors, using different icons as marker&lt;/li&gt;
&lt;li&gt;the library can return GeoJSON in exchange for a Overpass Query (there's a more generic builder for it), or a search by PoI&lt;/li&gt;
&lt;li&gt;the library can return the tile-sets as GeoJSON bounding boxes, useful in order to extrapolate these info while browsing maps online (to add functionalities to layers of map rendering software, as for example &lt;em&gt;leaflet.js&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these capabilities are already present in the library: it is just a matter of finding the best way to expose them with a web API.&lt;/p&gt;

&lt;p&gt;In addition to these, there can be much more functionality to be added to the API with a minimal effort.&lt;/p&gt;

&lt;p&gt;For example an endpoint could be created to easily search for bounding-boxes based on names (for example the name of a city, and a rough bounding-box covering it).&lt;/p&gt;

&lt;p&gt;The bot can be further developed, either with new possibilities, or copying the same functions over to other networks or communications systems (Facebook, Telegram, Slack...)&lt;/p&gt;

&lt;p&gt;Again, there are many possibilities for such a fast growing field.&lt;/p&gt;

&lt;p&gt;In fact, the market for end-customer geographic web application is getting reaper and reaper by the day, and niche products can still cut a slice of shares out of bigger companies, in my honest opinion. &lt;/p&gt;

</description>
      <category>dohackathon</category>
      <category>twitter</category>
      <category>webgeography</category>
    </item>
    <item>
      <title>Dev DigitalOcean Hackathon: Geobot, a Geography Python Twitter Bot - Tut 02</title>
      <dc:creator>Davide Del Papa</dc:creator>
      <pubDate>Sun, 10 Jan 2021 09:46:16 +0000</pubDate>
      <link>https://dev.to/davidedelpapa/dev-digitalocean-hackathon-geobot-a-geography-python-twitter-bot-tut-02-20j9</link>
      <guid>https://dev.to/davidedelpapa/dev-digitalocean-hackathon-geobot-a-geography-python-twitter-bot-tut-02-20j9</guid>
      <description>&lt;p&gt;[&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@dulceylima?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Dulcey Lima&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/bird-branch?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;, modified(crop)]&lt;/p&gt;

&lt;p&gt;The first installment of this series we just built a phony Python app and deployed it to DO App Platform.&lt;/p&gt;

&lt;p&gt;Today we will lay the foundations of what is to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plan of Action
&lt;/h2&gt;

&lt;p&gt;As the man-month story teaches, I had some time (Christmas Holidays), and we have a project to develop. I needed a plan!&lt;br&gt;
This is what happened, faithfully reported... more or less!&lt;/p&gt;

&lt;p&gt;This was what I thought:&lt;/p&gt;

&lt;p&gt;Well... we do not know as yet what we are building at the end, leave alone a plan!&lt;/p&gt;

&lt;p&gt;OK, the project sounds like this: we will create a bot (in this case a Twitter Bot to keep focused just on one platform, but we could port it as well). This bot is Geography oriented, that is, it should produce maps.&lt;/p&gt;

&lt;p&gt;The basic functioning is this: you mention the bot in Twitter, and the bot answers your tweet with a tweet of an image containing the map.&lt;/p&gt;

&lt;p&gt;The basics is this, we can extend it at will (and we WILL).&lt;/p&gt;

&lt;p&gt;As for the plan (roughly):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Build a server API with the same characteristics of the BOT (both to test the functionalities apart from the BOT, and to allow for composition)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a BOT to the server (or more than one)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will use an incremental functions development methodology, such as that from today onward we will have always a usable server and a usable BOT at least, adding functionalities as we go. &lt;/p&gt;

&lt;p&gt;It doesn't matter that we do not show images as yet, but it is important that we keep paired the server-BOT interface.&lt;/p&gt;
&lt;h2&gt;
  
  
  We need a BOT (and a Twitter Developer Account)
&lt;/h2&gt;

&lt;p&gt;As per the above, we have a server that shows us a message: we need a BOT that does the same.&lt;/p&gt;

&lt;p&gt;Let's create a new repo for this, with the usual:&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;geobotshow
&lt;span class="nb"&gt;cd &lt;/span&gt;geobotshow
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
curl &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; .gitignore https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore
git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will use &lt;a href="https://github.com/tweepy/tweepy"&gt;tweepy&lt;/a&gt; for this project. First let's activate, then we install all that is needed&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;source &lt;/span&gt;venv/bin/activate
pip &lt;span class="nb"&gt;install &lt;/span&gt;tweepy requests
pip freeze &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tweepy uses OAuth to authenticate to Twitter. You need up to 4 keys in order to use it. Time to get those!&lt;/p&gt;

&lt;p&gt;To create a new twitter app for your bot, go to the &lt;a href="https://developer.twitter.com/"&gt;twitter developer page&lt;/a&gt; and &lt;code&gt;Apply&lt;/code&gt; (top right).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PdYzOSGK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ajg0yvjfek60tpe4jhmu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PdYzOSGK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ajg0yvjfek60tpe4jhmu.png" alt="Alt Text" width="866" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, I chose in the welcome page the hobbyist reason that... I'm building a bot!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5BW9DcoA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/iipmuajhyawkjkhpzexw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5BW9DcoA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/iipmuajhyawkjkhpzexw.png" alt="Alt Text" width="880" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It then asks if it's me! Well, duh!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AL4Ncpo---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mq4kfj5zep276c2ivjlx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AL4Ncpo---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mq4kfj5zep276c2ivjlx.png" alt="Alt Text" width="880" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OK, kidding, just select the country, and other options (if applicable). Next it will ask you to explain what you need the account for. &lt;/p&gt;

&lt;p&gt;"How will you use the Twitter API or Twitter data?"&lt;/p&gt;

&lt;p&gt;Go ahead and write your reasons!&lt;br&gt;
Mine were kind of: "Create a useful geography bot" (okay, maybe I spent some few additional words for the concept to be accepted, at least 200 char!).&lt;/p&gt;

&lt;p&gt;OK, go ahead and answer all questions. Switch off those that do not apply (such as showing tweets outside Twitter &amp;amp; the sharing with government entities... unless you are from the Gov, following this: in that case, I declare I have nothing to do with everything is written in this post series!!!)&lt;/p&gt;

&lt;p&gt;After this you have to review, and to accept the agreement and submit.&lt;/p&gt;

&lt;p&gt;At the end you should get an email confirmation to activate the developer's account.&lt;/p&gt;

&lt;p&gt;When you do, you'll be redirected to the app creation page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uhxe4-ng--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/w75270wu4y1np9kth070.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uhxe4-ng--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/w75270wu4y1np9kth070.png" alt="Alt Text" width="809" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now thou can finally &lt;code&gt;Get the Keys&lt;/code&gt; Yeahhh!&lt;/p&gt;

&lt;p&gt;Now you have to copy them. I suggest you create a &lt;code&gt;.env&lt;/code&gt; file in your project, with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TWITTER_API_KEY=***
TWITTER_API_SECRET_KEY=***
TWITTER_BEARER_TOKEN=***
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The bearer token is better saved somewhere, even though we are not going to use it.&lt;/p&gt;

&lt;p&gt;If you copied the &lt;em&gt;.gitignore&lt;/em&gt; as I showed in the first tutorial, it is already ignored by git, otherwise you should add &lt;em&gt;.env&lt;/em&gt; to your &lt;em&gt;.gitignore&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now go to the app page, and edit the "App Permissions"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rj2gp28N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/teizaywig86iddgwy7bf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rj2gp28N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/teizaywig86iddgwy7bf.png" alt="Alt Text" width="597" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set it to both &lt;code&gt;Read&amp;amp;Write&lt;/code&gt;. Then save.&lt;/p&gt;

&lt;p&gt;We need to go to the app &lt;code&gt;Keys and tokens&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xK-IkJbE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ipncqrp6ncs21awqztaz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xK-IkJbE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ipncqrp6ncs21awqztaz.png" alt="Alt Text" width="382" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the bottom, we need to generate the &lt;code&gt;Access token &amp;amp; secret&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bWn8K8Pm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rr1kfo0tkaf1bw0vs0uc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bWn8K8Pm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rr1kfo0tkaf1bw0vs0uc.png" alt="Alt Text" width="588" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can update our &lt;em&gt;.env&lt;/em&gt; with 2 new fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TWITTER_ACCESS_TOKEN=***
TWITTER_ACCESS_SECRET=***
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally we need these variables available in the virtual environment.&lt;/p&gt;

&lt;p&gt;We first deactivate the environment (if active), then append the load commands to the &lt;em&gt;activate&lt;/em&gt; file itself&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deactivate
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"set -a; source &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/.env; set +a"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can re-activate the environment and check if the variables were set&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;source &lt;/span&gt;venv/bin/activate
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$TWITTER_API_KEY&lt;/span&gt;
&lt;span class="k"&gt;***&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should get your API KEY printed out&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the Tweepy Communications
&lt;/h2&gt;

&lt;p&gt;We should check that everything is going well.&lt;br&gt;
On the terminal get a Python shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python
Python 3.8.6 &lt;span class="o"&gt;(&lt;/span&gt;default, Sep 25 2020, 09:36:53&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;span class="o"&gt;[&lt;/span&gt;GCC 10.2.0] on linux
Type &lt;span class="s2"&gt;"help"&lt;/span&gt;, &lt;span class="s2"&gt;"copyright"&lt;/span&gt;, &lt;span class="s2"&gt;"credits"&lt;/span&gt; or &lt;span class="s2"&gt;"license"&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;more information.
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can import Tweepy and test the access:&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="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tweepy&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OAuthHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TWITTER_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TWITTER_API_SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_access_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TWITTER_ACCESS_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TWITTER_ACCESS_SECRET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;API&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verify_credentials&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above, substitute the key names with the actual values (or import them from the &lt;em&gt;.env&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Basically we first create a authorization object, then we set for it the access tokens.&lt;/p&gt;

&lt;p&gt;We pass the keys to an API object, and then we use the &lt;code&gt;verify_credentials()&lt;/code&gt; method to verify that it is working as expected.&lt;/p&gt;

&lt;p&gt;You should see the terminal flooded with info, and that means that it is working. Towards the beginning you should get info on the real name and the screen name, but if you do not spot them among all the rest, try the following:&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="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;your-twitter-name&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;your&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;twitter&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Your&lt;/span&gt; &lt;span class="n"&gt;Real&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Substitute in the above your twitter handle inside &lt;code&gt;api.get_user()&lt;/code&gt;, and you should see the correct info printed.&lt;/p&gt;

&lt;p&gt;Now you can &lt;code&gt;quit()&lt;/code&gt; the Python shell (just write that function name and press enter).&lt;/p&gt;

&lt;h2&gt;
  
  
  We Can Implement the BOT Now
&lt;/h2&gt;

&lt;p&gt;We need a configuration file to load configurations for the Twitter bot; we call it &lt;em&gt;config_tweepy.py&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import tweepy
import logging
import os

logger = logging.getLogger()

def get_api():
    api_key = os.getenv("TWITTER_API_KEY")
    api_secret = os.getenv("TWITTER_API_SECRET_KEY")
    access_token = os.getenv("TWITTER_ACCESS_TOKEN")
    access_secret = os.getenv("TWITTER_ACCESS_SECRET")

    auth = tweepy.OAuthHandler(api_key, api_secret)
    auth.set_access_token(access_token, access_secret)
    # Set some useful alerts
    api = tweepy.API(auth, wait_on_rate_limit=True, 
        wait_on_rate_limit_notify=True)
    try:
        api.verify_credentials()
    except Exception as e:
        logger.error("Error connecting to the Account", exc_info=True)
        raise e
    logger.info("Connected to the API")
    return api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will put it to use inside a bot called &lt;em&gt;tweet.bot.py&lt;/em&gt;:&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tweepy&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;config_tweepy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_api&lt;/span&gt;

&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_mentions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;since_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&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;"Retrieving mentions"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;new_since_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;since_id&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tweet&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mentions_timeline&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;since_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;since_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;new_since_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tweet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_since_id&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;tweet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;in_reply_to_status_id&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"Answering to &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tweet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&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="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tweet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# getting the API response
&lt;/span&gt;        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"API_HTTPS"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="c1"&gt;# reply to mention
&lt;/span&gt;        &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"@&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tweet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&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;in_reply_to_status_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tweet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"Since_id: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;new_since_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;new_since_id&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_api&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;since_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BOT_SINCEID"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;since_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;check_mentions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;since_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&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;"Waiting..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&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;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can infer from the above, we need two additional env variables,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API_HTTPS=https://&amp;lt;appname-id&amp;gt;.ondigitalocean.app/
BOT_SINCEID=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first holds the URL of your service, to retrieve the data from (you can check that easily underneath the name of your DO App Service).&lt;/p&gt;

&lt;p&gt;The second holds a sort of pagination of the tweets id, so that it keeps track of what it has already answered to, in order not to start always to answer from the beginning. We start with 1, and it will get automatically updated. Also check on it, since it goes on the logs: this way if the app crashes, or gets updated, we can resume from the last one, and not start back from the beginning &lt;/p&gt;

&lt;p&gt;Time to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 tweet.bot.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can tweet something mentioning our bot, in order to test if it works&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@geobotshow test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And after a while we should see in the console the logging of the action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INFO:root:Retrieving mentions
INFO:root:Answering to Davide Del Papa
INFO:root:@geobotshow test 4
INFO:root:Since_id: 1342897400902508546
INFO:root:Waiting...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it should show also in your timeline&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xY5FDRnV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zzvc4q7qvbhgzsin94wi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xY5FDRnV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zzvc4q7qvbhgzsin94wi.png" alt="Alt Text" width="609" height="125"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I suggest to save the &lt;code&gt;Since_id&lt;/code&gt; and to substitute to the script's own one, so that each time it starts again the script will not attempt to answer to old mentions-&lt;/p&gt;

&lt;p&gt;I suggest also to cancel some of the &lt;code&gt;logger.info()&lt;/code&gt;, since in production we will not need them. Moreover, we need to log on a file with:&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="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'tweet.bot.log'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That should be enough for the following.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy it
&lt;/h2&gt;

&lt;p&gt;When we are satisfied that everything works correctly, we can deploy it to DO App Platform&lt;/p&gt;

&lt;p&gt;First let's commit&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;-A&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s1"&gt;'First Commit'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to deploy, we need to go to the main page of our app and select the &lt;em&gt;Components&lt;/em&gt; tab:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c-2cR2WM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wm4mdxpaqx8e6b6o6eer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c-2cR2WM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wm4mdxpaqx8e6b6o6eer.png" alt="Alt Text" width="880" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to &lt;code&gt;Create a New Component&lt;/code&gt;, and we select &lt;strong&gt;Worker&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You need again to select the repository (if it does not show, just refresh the permissions, clicking on the link below the repository selection dropdown: change it, change it back and save)&lt;/p&gt;

&lt;p&gt;Then you'll pick again the branch and the region of deploy.&lt;/p&gt;

&lt;p&gt;After this, it will have detected a python service, but will be unable to detect the running command: just &lt;em&gt;edit&lt;/em&gt; the run command as before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 tweet.bot.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--icd2Jf4---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f53c8p1xv3gndam0ljtq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--icd2Jf4---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f53c8p1xv3gndam0ljtq.png" alt="Alt Text" width="880" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moreover, we will need to insert the ENVIRONMENT variables!&lt;/p&gt;

&lt;p&gt;As there is not a way to load a file, we have to add them manually&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9gfJj9Dw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aq3dr7e5faqalqvib4q5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9gfJj9Dw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aq3dr7e5faqalqvib4q5.png" alt="Alt Text" width="880" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure to select &lt;code&gt;[x] Encrypt&lt;/code&gt; where appropriate, so that it will add a security layer.&lt;/p&gt;

&lt;p&gt;It is time to select a plan, and again we can select the smallest size.&lt;/p&gt;

&lt;p&gt;Then we have to wait for the deploy&lt;/p&gt;

&lt;p&gt;Now, we can try it online and see everything running smooth&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ODCfsvCb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b24zmncflglz6ms49yzu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ODCfsvCb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b24zmncflglz6ms49yzu.png" alt="Alt Text" width="592" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also check the log file in the console&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DslON0Bq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m8ocr0ta45h14u4n5b1f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DslON0Bq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m8ocr0ta45h14u4n5b1f.png" alt="Alt Text" width="880" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;We have set up a worker to run as a bot&lt;/p&gt;

&lt;p&gt;The only problem we have with this configuration is that it will occupy two DigitalOcean Containers: one for the service, and one for the worker.&lt;/p&gt;

&lt;p&gt;However, this configuration is quite flexible. &lt;/p&gt;

&lt;p&gt;Stay tuned for the following episodes.&lt;/p&gt;

</description>
      <category>dohackathon</category>
      <category>python</category>
      <category>twitter</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Dev DigitalOcean Hackathon: Geobot, a Geography Python Twitter Bot - Tut 01</title>
      <dc:creator>Davide Del Papa</dc:creator>
      <pubDate>Sat, 02 Jan 2021 15:07:26 +0000</pubDate>
      <link>https://dev.to/davidedelpapa/dev-digitalocean-hackathon-geobot-a-geography-python-twitter-bot-tut-01-470o</link>
      <guid>https://dev.to/davidedelpapa/dev-digitalocean-hackathon-geobot-a-geography-python-twitter-bot-tut-01-470o</guid>
      <description>&lt;p&gt;[&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@vikceo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;vivek kumar&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/whale?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;, modified(cropped)]&lt;/p&gt;

&lt;p&gt;I started surveying the &lt;a href="https://dev.to/devteam/announcing-the-digitalocean-app-platform-hackathon-on-dev-2i1k"&gt;Dev DigitalOcean Hackathon&lt;/a&gt; with &lt;a href="https://dev.to/davidedelpapa/digital-ocean-app-platform-hackathon-using-not-natively-supported-platforms-rust-rocket-55og"&gt;an article on deploying a Rust application&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, since Rust is a much technical language, and it is not so far supported by DigitalOcean App Platform, I decided to go the Python way for this hackathon.&lt;/p&gt;

&lt;p&gt;Grab your laptop and a beer (or some spiked eggnog: it's still Christmas season after all!).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: read the &lt;a href="(https://dev.to/devteam/announcing-the-digitalocean-app-platform-hackathon-on-dev-2i1k)"&gt;official hackathon page&lt;/a&gt;. If you are following this tutorial to prepare for your own hackathon, there is a link to a form to fill in order to get 50$ for 60 days, good to test the environment and to participate to the hackathon without weighing too much on the wallet. Merry Christmas and a happy new year to us!&lt;/p&gt;

&lt;h2&gt;
  
  
  First Build
&lt;/h2&gt;

&lt;p&gt;I will give for granted that you are using a POSIX like shell (mostly Bash, but I use ZSH). &lt;br&gt;
So the following is just routine:&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;geobot
&lt;span class="nb"&gt;cd &lt;/span&gt;geobot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above you can change &lt;em&gt;geobot&lt;/em&gt; to give your project a different name.&lt;/p&gt;

&lt;p&gt;Now we can create a virtual environment for our app:&lt;br&gt;
&lt;/p&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; venv venv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we need to push our app to GitHub in order to trigger the DigitalOcean builds, we need a &lt;code&gt;.gitignore&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We could create our own, but I advise to use a ready-made one, &lt;a href="https://github.com/github/gitignore" rel="noopener noreferrer"&gt;from the official GitHub repo&lt;/a&gt;:&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;-L&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; .gitignore https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can make our project's folder into a git repository:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Time to activate our virtual environment:&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;source &lt;/span&gt;venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Remember: when you have finished, in order to deactivate the environment, just give the command &lt;code&gt;deactivate&lt;/code&gt; straight to the shell).&lt;/p&gt;

&lt;p&gt;Now we need to install our first dependencies.&lt;/p&gt;

&lt;p&gt;We will use &lt;a href="https://flask.palletsprojects.com/en/1.1.x/" rel="noopener noreferrer"&gt;Flask&lt;/a&gt; as API Server Framework, and &lt;a href="https://gunicorn.org/" rel="noopener noreferrer"&gt;Gunicorn&lt;/a&gt; as WSGI HTTP server (think of it as an Apache for the Python frameworks).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;Flask gunicorn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also create a &lt;em&gt;requirements.txt&lt;/em&gt; now, and in case of need, update it later on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip freeze &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's create a minimalist Flask app, called &lt;em&gt;app.py&lt;/em&gt;:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&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="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello_world&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello world!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to create a configuration file for Gunicorn, called &lt;em&gt;gunicorn_config.py&lt;/em&gt;:&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="n"&gt;bind&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0:8080&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;workers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That will bind your server to the port &lt;code&gt;8080&lt;/code&gt; of the &lt;em&gt;localhost&lt;/em&gt;, from which DigitalOcean Apps will fetch it.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Deploy
&lt;/h2&gt;

&lt;p&gt;Now it's time to push to GitHub and deploy on DO App Platform.&lt;/p&gt;

&lt;p&gt;Let's prepare our local repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;-A&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s1"&gt;'First Commit'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can create a new empty repo on GitHub, that we can enable as remote on the local one, and push our first commit to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote add origin https://github.com/&amp;lt;yourname&amp;gt;/geobot.git
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: very soon GitHub will change the defaults, and replace &lt;code&gt;master&lt;/code&gt; with &lt;code&gt;main&lt;/code&gt;. There will be a transparent method provided by GitHub to do so, therefore we will patiently wait the tools are in place (the official guides say to wait still). Otherwise branch now to &lt;code&gt;main&lt;/code&gt; (&lt;code&gt;git branch -M main&lt;/code&gt;) and push to &lt;code&gt;main&lt;/code&gt; instead than to &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Time for the DigitalOcean part.&lt;/p&gt;

&lt;p&gt;Let's point our browser to the &lt;a href="https://cloud.digitalocean.com/apps" rel="noopener noreferrer"&gt;DO App Platform Homepage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;Launch Your App&lt;/code&gt;: if it's the first time it will ask you to connect your GitHub account. &lt;strong&gt;Just follow the procedure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At the end you will be prompted to choose a repository&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%2Fi%2F8h8hdu91yudg20kzrfia.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%2Fi%2F8h8hdu91yudg20kzrfia.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;code&gt;Next&lt;/code&gt; and in page 2 you will be prompted to pick a name and a region of deploy&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%2Fi%2Fz13m8rb8dp272s65hq8w.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%2Fi%2Fz13m8rb8dp272s65hq8w.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;code&gt;Next&lt;/code&gt; and in page 3 it should have detected everything for you (that is, Python and even Gunicorn!). In case it has not, please refer to the following image for the right settings:&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%2Fi%2Fp5156kc6nsmhdhvsxnep.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%2Fi%2Fp5156kc6nsmhdhvsxnep.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything is OK, but the &lt;code&gt;Run Command&lt;/code&gt;: click &lt;code&gt;Edit&lt;/code&gt; in there and add &lt;code&gt;app:app&lt;/code&gt; at the end.&lt;/p&gt;

&lt;p&gt;It should be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gunicorn &lt;span class="nt"&gt;--worker-tmp-dir&lt;/span&gt; /dev/shm app:app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can save and resume the wizard.&lt;/p&gt;

&lt;p&gt;Upon clicking &lt;code&gt;Next&lt;/code&gt; we will be given the opportunity to choose our Monthly plan and the size of our virtual server (available maximum resources).&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%2Fi%2Fkmrcd8dzlw99d3i673ml.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%2Fi%2Fkmrcd8dzlw99d3i673ml.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that the free plan is not available for web services, but only to host static resources.&lt;/p&gt;

&lt;p&gt;Notice too in the bottom left of the above picture: DO defaults to the small &lt;code&gt;S&lt;/code&gt; (10$ per month) server; however, there is an option for an &lt;code&gt;XS&lt;/code&gt; (extra small) server (5$/Mo.); you can opt for that, at least when you are not deploying a business app, but just testing the environment.&lt;/p&gt;

&lt;p&gt;Upon clicking on &lt;code&gt;Launch Basic App&lt;/code&gt; you will be redirected to the page of your app, and you should see it loading the deploy&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%2Fi%2F59otp42m5w37wfsfl2he.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%2Fi%2F59otp42m5w37wfsfl2he.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you click on &lt;code&gt;view Logs&lt;/code&gt; (on the top right), you can take a look to see if the deploy got stuck somewhere.&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%2Fi%2Fyazfv5kqovm5w8rg8g90.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%2Fi%2Fyazfv5kqovm5w8rg8g90.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once everything is done, you should see a &lt;code&gt;Deployed successfully!&lt;/code&gt; message, and a link to the app under the app name:&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%2Fi%2Fn2dhvpe8t1g8ubomgzfn.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%2Fi%2Fn2dhvpe8t1g8ubomgzfn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you follow the link, you should see our Flask app greeting us from the browser window:&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%2Fi%2F3n6ql0btv4ejhp6o395j.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%2Fi%2F3n6ql0btv4ejhp6o395j.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Always an emotion!&lt;/p&gt;

&lt;h2&gt;
  
  
  Playing with your First App
&lt;/h2&gt;

&lt;p&gt;You can go ahead and change the greeting message in &lt;em&gt;app.py&lt;/em&gt;, for example:&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="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello_world&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello from DO App Platform!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, if you commit to GitHub&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;-A&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s1"&gt;'Showing Personalized Greeting Message'&lt;/span&gt;
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you will see App Platform "instantly" rebuild the app for us:&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%2Fi%2F3no8s17l926u4sl0vovr.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%2Fi%2F3no8s17l926u4sl0vovr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the end you will see the updated message:&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%2Fi%2Fifp6h2qon3rks13ufl39.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%2Fi%2Fifp6h2qon3rks13ufl39.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that while it is still building, DigitalOcean will keep the old version running, and when the deploy is completed it will substitute the new version for the old.&lt;/p&gt;

&lt;p&gt;Quite neat!&lt;/p&gt;

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

&lt;p&gt;For today it's all folks!&lt;br&gt;
If you are completely new to this world, I hope you could follow the tutorial without problems.&lt;/p&gt;

&lt;p&gt;Do not hesitate to write in the comments section.&lt;/p&gt;

&lt;p&gt;As usual: stay excited, because something good's coming at the horizon!&lt;br&gt;
Till next time!&lt;/p&gt;

</description>
      <category>dohackathon</category>
      <category>python</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Rocket Tutorial 05: Enforcing uniqueness of emails.</title>
      <dc:creator>Davide Del Papa</dc:creator>
      <pubDate>Mon, 21 Dec 2020 18:18:01 +0000</pubDate>
      <link>https://dev.to/davidedelpapa/rocket-tutorial-05-enforcing-uniqueness-of-emails-136j</link>
      <guid>https://dev.to/davidedelpapa/rocket-tutorial-05-enforcing-uniqueness-of-emails-136j</guid>
      <description>&lt;p&gt;[&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@ancientwanderer?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Terence Burke&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/rocket-space?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;, modified (cropped)]&lt;/p&gt;

&lt;p&gt;In the alternative tutorial 04 we discovered that our tests were not enough, and we left with the promise to take care of that. Here we are, honoring that promise.&lt;/p&gt;

&lt;p&gt;Of course, we will not talk about just testing and testing forever... In fact we'll be strengthening security on our system by enforcing uniqueness of emails.&lt;/p&gt;

&lt;p&gt;The code for this tutorial can be found in this repository: &lt;a href="https://github.com/davidedelpapa/rocket-tut"&gt;github.com/davidedelpapa/rocket-tut&lt;/a&gt;, and has been tagged for your convenience:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/davidedelpapa/rocket-tut.git
&lt;span class="nb"&gt;cd &lt;/span&gt;rocket-tut
git checkout tags/tut5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A promise is a promise: more on tests
&lt;/h2&gt;

&lt;p&gt;Hold your horses, cowboy! First we need to honor the promise we made last time.&lt;/p&gt;

&lt;p&gt;I'm still in the "Redis branch" of the repo: we'll change things here, test properly, and then I'll show a nice &lt;em&gt;git trick&lt;/em&gt;, if you don't already know it, to merge back just the tests to master (where there's the MongoDB version).&lt;/p&gt;

&lt;p&gt;We have to do two things: delete each user we insert in testing, and make sure that each email is unique.&lt;/p&gt;

&lt;p&gt;As for the first thing we have to make sure that EACH user we insert is unique (i.e., no copy-pasta, even though I'm Italian and I love pasta)&lt;/p&gt;

&lt;p&gt;The following is useful in almost any case we insert a user first:&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;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="nf"&gt;.status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Ok&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="nf"&gt;.delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/users/{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r##"{
            "password": "123456"
        }"##&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.dispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="nf"&gt;.status&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&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;p&gt;Of course we have to fill in the right password.&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;tests/basic_test.rs&lt;/em&gt;, in &lt;code&gt;new_user_rt_test()&lt;/code&gt; we do not extract the user id at all, so we have to pass it on the fly, like so:&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;client&lt;/span&gt;&lt;span class="nf"&gt;.delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/users/{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;em&gt;tests/failures_test.rs&lt;/em&gt; instead, in &lt;code&gt;id_user_rt_fail()&lt;/code&gt; we have to extract the info of the id from the user.&lt;/p&gt;

&lt;p&gt;However, remember that in &lt;em&gt;tests/failures_test.rs&lt;/em&gt; we make the responses fail on purpose (it's our fails test); however we check always that the insertion was correct.&lt;br&gt;
So, there's no need to check again if the insertion was correct, and we can take away the &lt;code&gt;if&lt;/code&gt; altogether.&lt;/p&gt;

&lt;p&gt;Instead in &lt;code&gt;info_user_rt_fail()&lt;/code&gt;, before we forge a fake id, we need to &lt;code&gt;clone()&lt;/code&gt; it:&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;let&lt;/span&gt; &lt;span class="k"&gt;mut&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;user_new&lt;/span&gt;&lt;span class="py"&gt;.id&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;so that later on we can reuse &lt;code&gt;user_new.id&lt;/code&gt;:&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;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="nf"&gt;.status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Ok&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="nf"&gt;.delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/users/{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_new&lt;/span&gt;&lt;span class="py"&gt;.id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r##"{
            "password": "123456"
        }"##&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.dispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="nf"&gt;.status&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&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;p&gt;In &lt;em&gt;tests/persistency_test.rs&lt;/em&gt; too we do not extract the id info from the response; we have also to remember that we cannot access anymore the first client,so we have to just call &lt;code&gt;client2&lt;/code&gt;:&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;let&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client2&lt;/span&gt;&lt;span class="nf"&gt;.delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/users/{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="py"&gt;.id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that is it: if we adapt a little the code and the passwords.&lt;/p&gt;

&lt;p&gt;Now we can test everything and cleanup after our mess. Well done.&lt;/p&gt;

&lt;p&gt;Even checking in the Redis part all the keys present in the DB 1 we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;127.0.0.1:6379[1]&amp;gt; keys *
(empty list or set)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In fact, the lookup key gets also destroyed once its values are depleted.&lt;/p&gt;

&lt;p&gt;Now that everything is fixed we'd like to commit those changes to the Redis branch, but also bring them to the MongoDB branch (assuming it's &lt;em&gt;master&lt;/em&gt;; if it's &lt;em&gt;main&lt;/em&gt; correct the following as needed). No worries we can do that easily&lt;/p&gt;

&lt;p&gt;First commit all changes to the Redis branch; then we move back to master&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="nv"&gt;$ &lt;/span&gt;git checkout master
Switched to branch &lt;span class="s1"&gt;'master'&lt;/span&gt;
~&lt;span class="nv"&gt;$ &lt;/span&gt; git checkout tut04alt tests/basic_test.rs tests/failures_test.rs tests/persistency_test.rs
Updated 3 paths from 69b3ab7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is, on &lt;em&gt;master&lt;/em&gt; we give the &lt;code&gt;git branch &amp;lt;name_of_branch_to_copy_from&amp;gt; &amp;lt;path/to/file&amp;gt; &amp;lt;path/to/file&amp;gt; ...&lt;/code&gt; and git will stage for us in master the modifications to the files from the other branch we want copy also on the current branch.&lt;/p&gt;

&lt;p&gt;Let's check now:&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="nv"&gt;$ &lt;/span&gt;git status
On branch master
Changes to be committed:
  &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git restore --staged &amp;lt;file&amp;gt;..."&lt;/span&gt; to unstage&lt;span class="o"&gt;)&lt;/span&gt;
    modified:   tests/basic_test.rs
    modified:   tests/failures_test.rs
    modified:   tests/persistency_test.rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sorry for this interlude about git-foo, but it is convenient to know while working on many branches at the same time. Now we can commit on master as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Second promise: Unique emails
&lt;/h2&gt;

&lt;p&gt;Now we need a new test to check whether our system accepts only one unique email or not.&lt;/p&gt;

&lt;p&gt;It's a case fit for &lt;em&gt;failure&lt;/em&gt; so, we modify our &lt;em&gt;tests/failures_test.rs&lt;/em&gt;&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;#[test]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;unique_emails_insertion_fail&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;common&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// First user with its email&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;response_new_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="nf"&gt;.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/users"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r##"{
            "name": "Jared Doe",
            "email": "jthebest@m.com",
            "password": "123456"
        }"##&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.dispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// We have to make sure this does not fail because of wrong new user insertion&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response_new_user&lt;/span&gt;&lt;span class="nf"&gt;.status&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response_new_user&lt;/span&gt;&lt;span class="nf"&gt;.content_type&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JSON&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;response_body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response_new_user&lt;/span&gt;&lt;span class="nf"&gt;.body_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Response Body"&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;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResponseUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;serde_json&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_str&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;response_body&lt;/span&gt;&lt;span class="nf"&gt;.as_str&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Valid User Response"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Second user with the same email&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;response_second_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="nf"&gt;.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/users"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r##"{
            "name": "Joy Doe",
            "email": "jthebest@m.com",
            "password": "qwertyuiop"
        }"##&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.dispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;assert_ne!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response_second_user&lt;/span&gt;&lt;span class="nf"&gt;.status&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response_second_user&lt;/span&gt;&lt;span class="nf"&gt;.content_type&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response_second_user&lt;/span&gt;&lt;span class="nf"&gt;.body_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;email already in use&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

    &lt;span class="c1"&gt;// Cleanup&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="nf"&gt;.delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/users/{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="py"&gt;.id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r##"{
            "password": "123456"
        }"##&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.dispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="nf"&gt;.status&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&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;p&gt;In the above we insert a user and then attempt to insert another one with the same email as the first.&lt;/p&gt;

&lt;p&gt;In the code we've added also another test, &lt;code&gt;unique_emails_update_fail()&lt;/code&gt;, for the &lt;code&gt;PUT&lt;/code&gt; route, to update the user. This test inserts two different users and is set to fail when updating the first user we use the same email as the second user.&lt;/p&gt;

&lt;p&gt;If we run &lt;code&gt;cargo test&lt;/code&gt; of course it will fail.&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;test &lt;/span&gt;unique_emails_insertion_fail ... FAILED
&lt;span class="nb"&gt;test &lt;/span&gt;unique_emails_update_fail ... FAILED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moreover, now we will have to clean the DB by hand as well.&lt;/p&gt;

&lt;p&gt;Just for your info, I'm not fan of any software specifically, but if you do not really know how to use MongoDB and want a GUI to manage it, I'm using &lt;a href="https://robomongo.org/download"&gt;Robo 3t&lt;/a&gt; by &lt;a href="https://robomongo.org/"&gt;robomongo&lt;/a&gt;. I'm not affiliated to nobody, just saying that which I happen to use, but there are other software out there, as well, just search for them.&lt;/p&gt;

&lt;p&gt;Back to business, we have some emails to render unique.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unique fields in MongoDB
&lt;/h3&gt;

&lt;p&gt;We need to enforce an index out of a field, so that MongoDB will index by id, as well as by that index (in this case email).&lt;/p&gt;

&lt;p&gt;There's not as yet this function on the &lt;code&gt;mongodb&lt;/code&gt; crate. Besides, which part of the code should create it?&lt;/p&gt;

&lt;p&gt;The only thing to do is to run the command on a MongoDB shell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.getCollection('users').createIndex( { "email": 1 }, { unique: true } )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I run it on Robo3t for example.&lt;/p&gt;

&lt;p&gt;OK, there's technically another way to do it, in a more elegant way, and in a way that it is all done in Rust (think of deploying this quickly by an inexperienced user, without having to setup just about &lt;em&gt;everything&lt;/em&gt;). We could create a lookup collection, in the same way we did with Redis, and use the email as ID, while setting as only field the User ID. &lt;/p&gt;

&lt;p&gt;The data structure will look like this:&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;#[derive(Serialize,&lt;/span&gt; &lt;span class="nd"&gt;Deserialize,&lt;/span&gt; &lt;span class="nd"&gt;Debug,&lt;/span&gt; &lt;span class="nd"&gt;Clone)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;EmailLookup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;#[serde(rename&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"_id"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Uuid&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;Serde will rename &lt;code&gt;emailk&lt;/code&gt; to &lt;code&gt;_id&lt;/code&gt;, and MongoDB will use this field as its id, instead of creating an id automatically. I mean, its the same technique we used for &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You just put it in &lt;em&gt;src/data/db.rs&lt;/em&gt; and you are set to go.&lt;/p&gt;

&lt;p&gt;The procedure for insertion will be thus:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check the lookup table: if the field already exists, let the insertion fail.&lt;/li&gt;
&lt;li&gt;Insert the new user regularly, and extrapolate the ID&lt;/li&gt;
&lt;li&gt;Insert the user by email in the lookup collection.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point we could change the retrieval of the get by email, but I do not advise doing so, because it would mean to first extract the ID, then use it to get the user by ID... oh my.&lt;/p&gt;

&lt;p&gt;BIG WARNING: in MongoDB the &lt;code&gt;_id&lt;/code&gt; (whatever its content) is &lt;em&gt;immutable&lt;/em&gt;: when the user updates the email, you have first to delete the field, then create another one. Not that difficult, but keep an eye on it.&lt;/p&gt;

&lt;p&gt;Anyway let's discard the idea of a separate lookup collection in this project (it's always up to you to implement it, if you want, I think we covered enough together for you at least to try).&lt;/p&gt;

&lt;p&gt;We go for the quick-fix command described above. This leave us with the only task of getting the right error when inserting a new user.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://docs.mongodb.com/manual/reference/method/db.collection.insert/index.html"&gt;MongoDB's docs&lt;/a&gt; it is written that a non unique index key would result in an error of kind &lt;code&gt;writeError&lt;/code&gt; with code &lt;code&gt;11000&lt;/code&gt;. We have to get this same Error definition in &lt;em&gt;mongodb&lt;/em&gt; crate.&lt;/p&gt;

&lt;p&gt;It is in &lt;code&gt;mongodb::coll::error::WriteError&lt;/code&gt;:&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;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;WriteError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&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;Now we know we have to match that same error code. Let's find in &lt;em&gt;src/routes/user.rs&lt;/em&gt; when we insert a new user:&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;match&lt;/span&gt; &lt;span class="n"&gt;user_coll&lt;/span&gt;&lt;span class="nf"&gt;.insert_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="nf"&gt;.to_owned&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&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;inserted&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="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;inserted&lt;/span&gt;&lt;span class="py"&gt;.inserted_id&lt;/span&gt; &lt;span class="p"&gt;{&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;id&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="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;ApiResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;internal_err&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// here!&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;_&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;ApiResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;internal_err&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// not here!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why there and not on the error? Because the error is when there's not an answer from the MongoDB server, but an answer WITH an error is covered somewhere else. Actually, the response is a &lt;code&gt;&lt;/code&gt;&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;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;InsertOneResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;acknowledged&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="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;inserted_id&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="n"&gt;Bson&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;pub&lt;/span&gt; &lt;span class="n"&gt;write_exception&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="n"&gt;WriteException&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;You can see that there's the option with the id inserted, but if that is &lt;code&gt;None&lt;/code&gt; then the &lt;code&gt;write_exception&lt;/code&gt; contains the error. PS: acknowledged contains how many records have been written, so in this case that is &lt;code&gt;0&lt;/code&gt; since it is an &lt;code&gt;insert_one&lt;/code&gt;; if it were a bulk insertion it could have had info of fields written and fields with exceptions...&lt;/p&gt;

&lt;p&gt;Let's get back on track:&lt;/p&gt;

&lt;p&gt;We have to change the &lt;code&gt;None&lt;/code&gt; where it says &lt;code&gt;// here!&lt;/code&gt; to:&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="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;inserted&lt;/span&gt;&lt;span class="py"&gt;.write_exception&lt;/span&gt; &lt;span class="p"&gt;{&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;wite_error&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="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;wite_error&lt;/span&gt;&lt;span class="py"&gt;.write_error&lt;/span&gt; &lt;span class="p"&gt;{&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;err&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="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="py"&gt;.code&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="mi"&gt;11000i32&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;ApiResponse&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="nd"&gt;json!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"email already in use"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
                    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;ApiResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;internal_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="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;ApiResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;internal_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="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;ApiResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;internal_err&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 for the other route we have to check, &lt;code&gt;update_user_rt()&lt;/code&gt;, we just need to briefly check that the email does not yet exist, right after we authenticate the password.&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="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;if&lt;/span&gt; &lt;span class="n"&gt;found_user&lt;/span&gt;&lt;span class="nf"&gt;.match_password&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;user&lt;/span&gt;&lt;span class="py"&gt;.password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// After this&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;insertable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;found_user&lt;/span&gt;&lt;span class="nf"&gt;.update_user&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;user&lt;/span&gt;&lt;span class="py"&gt;.name&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;user&lt;/span&gt;&lt;span class="py"&gt;.email&lt;/span&gt;&lt;span class="p"&gt;);&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll borrow the &lt;code&gt;find_one()&lt;/code&gt; scheme from &lt;code&gt;id_user_rt()&lt;/code&gt; (that finds users through the email): if we find one we'll sen the error about the email already in use, otherwise we'll let everything work normally.&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;if&lt;/span&gt; &lt;span class="n"&gt;found_user&lt;/span&gt;&lt;span class="nf"&gt;.match_password&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;user&lt;/span&gt;&lt;span class="py"&gt;.password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Check the email does not yet exist&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;user_coll&lt;/span&gt;&lt;span class="nf"&gt;.find_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"email"&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;user&lt;/span&gt;&lt;span class="py"&gt;.email&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&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;mail_query_result&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="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;mail_query_result&lt;/span&gt; &lt;span class="p"&gt;{&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;_&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="k"&gt;return&lt;/span&gt; &lt;span class="nn"&gt;ApiResponse&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="nd"&gt;json!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"email already in use"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="k"&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="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;_&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="k"&gt;return&lt;/span&gt; &lt;span class="nn"&gt;ApiResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;internal_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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;insertable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;found_user&lt;/span&gt;&lt;span class="nf"&gt;.update_user&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;user&lt;/span&gt;&lt;span class="py"&gt;.name&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;user&lt;/span&gt;&lt;span class="py"&gt;.email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have implemented in both routes the &lt;code&gt;"email already in use"&lt;/code&gt; error. We should build and test (fingers crossed).&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;test &lt;/span&gt;unique_emails_insertion_fail ... ok
&lt;span class="nb"&gt;test &lt;/span&gt;unique_emails_update_fail ... ok
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can consider that a personal win.&lt;/p&gt;

&lt;h3&gt;
  
  
  Uniqueness in Redis
&lt;/h3&gt;

&lt;p&gt;Let's commit, switch over to Redis and bring the new test in there... And let's hope the fix will be quick.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push origin master
git checkout tut04alt
git checkout master tests/failures_test.rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As for Redis the only way of enforcing uniqueness is through a &lt;code&gt;set&lt;/code&gt;, that is a container of unique objects.&lt;/p&gt;

&lt;p&gt;Example:&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="nv"&gt;$ &lt;/span&gt;redis-cli
127.0.0.1:6379&amp;gt; sadd mykey &lt;span class="s2"&gt;"one"&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;integer&lt;span class="o"&gt;)&lt;/span&gt; 1
127.0.0.1:6379&amp;gt; sadd mykey &lt;span class="s2"&gt;"two"&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;integer&lt;span class="o"&gt;)&lt;/span&gt; 1
127.0.0.1:6379&amp;gt; sadd mykey &lt;span class="s2"&gt;"one"&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;integer&lt;span class="o"&gt;)&lt;/span&gt; 0
127.0.0.1:6379&amp;gt; smembers mykey
1&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="s2"&gt;"two"&lt;/span&gt;
2&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="s2"&gt;"one"&lt;/span&gt;
127.0.0.1:6379&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The integer answer is the number of members added (can be more than one at a time). When re-adding the same member we see that it returns &lt;code&gt;0&lt;/code&gt;, and checking the list of members we see that there are no duplicates.&lt;/p&gt;

&lt;p&gt;Let's implement it in code. Briefly we have to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a email to a set each time it is serialized a user. We do not need &lt;em&gt;per se&lt;/em&gt; to check for failures there, in fact, we should check for failures beforehand. But anyhow, it is better to check.&lt;/li&gt;
&lt;li&gt;Before each insert, we need to make sure that the email does not already exist.&lt;/li&gt;
&lt;li&gt;Before updating with a new email we need to check that it is not already in use.&lt;/li&gt;
&lt;li&gt;We have to cleanup the email before updating it, and also change password (because the user gets re-inserted). Also we have to cleanup he email once we remove the user.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As to the point 1, we change the &lt;code&gt;to_redis()&lt;/code&gt; method to look like:&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;to_redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;connection&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;Conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AnyResult&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.id&lt;/span&gt;&lt;span class="nf"&gt;.to_string&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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.email&lt;/span&gt;&lt;span class="nf"&gt;.clone&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;r_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.email&lt;/span&gt;&lt;span class="nf"&gt;.to_lowercase&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hashed_password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.hashed_password&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"salt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.salt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"created"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.created&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"updated"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.updated&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="nf"&gt;.hset_multiple&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;id&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;r_user&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="c1"&gt;// Enforce email uniqueness&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;res_enforce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="nf"&gt;.sadd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UNIQUE_EMAIL_SET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="nf"&gt;.clone&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="c1"&gt;// Add email lookup index&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;res_enforce&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&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;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="nf"&gt;.zadd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOOKUP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;format!&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;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&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="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;bail!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"email already in use"&lt;/span&gt;&lt;span class="p"&gt;);&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;p&gt;We have to render all email lowercase, because &lt;code&gt;sadd&lt;/code&gt; is case sensitive.&lt;/p&gt;

&lt;p&gt;We create a new &lt;code&gt;User&lt;/code&gt; method to check uniqueness as well:&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;is_unique_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;connection&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;Conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AnyResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;bool&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;res_enforce&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="nb"&gt;i8&lt;/span&gt;&lt;span class="p"&gt;,&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;connection&lt;/span&gt;&lt;span class="nf"&gt;.sismember&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UNIQUE_EMAIL_SET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.email&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;res_enforce&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;res&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&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="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&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="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;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;anyhow!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connection error"&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;I'm not going to discuss all the other routes, I think it is easy to check them, but this is the &lt;code&gt;POST&lt;/code&gt; route:&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;#[post(&lt;/span&gt;&lt;span class="s"&gt;"/users"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;format&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"json"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;data&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;user&amp;gt;"&lt;/span&gt;&lt;span class="nd"&gt;)]&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;new_user_rt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;InsertableUser&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;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ApiResponse&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;ins_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;User&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_insertable&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.clone&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;ins_user&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.is_unique_email&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;connection&lt;/span&gt;&lt;span class="p"&gt;)&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;res&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="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;true&lt;/span&gt; &lt;span class="k"&gt;=&amp;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;ins_user&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.to_redis&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;connection&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;_&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;ApiResponse&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="nd"&gt;json!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ResponseUser&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_user&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;ins_user&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;_&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;ApiResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;internal_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="k"&gt;false&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;ApiResponse&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="nd"&gt;json!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"email already in use"&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="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&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;ApiResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;internal_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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Easy, isn't it?&lt;br&gt;
A quick build&amp;amp;run confirms that everything is as it is supposed to be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;I think we can call it a day, although we didn't lean anything new about Rocket or about integrating it with other software, as we did in the last tutorials.&lt;/p&gt;

&lt;p&gt;Besides, learning how to strengthen security on our systems by enforcing uniqueness of a field is a skill useful not just to this specific case: there are many cases in which fields have to be unique and index-like, &lt;em&gt;independently&lt;/em&gt; of the real index.&lt;/p&gt;

&lt;p&gt;Next time I will introduce a new concept to work with Rocket, and we will use it to authenticate our Users to the platform (finally).&lt;br&gt;
So, stay tuned!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
