<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>Cetra&#x27;s Thoughts</title>
      <link>https://cetra3.github.io</link>
      <description>Blogs and Investigations mostly about Rust</description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://cetra3.github.io/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Wed, 11 Mar 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>The State of Allocators in 2026</title>
          <pubDate>Wed, 11 Mar 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/state-of-allocators-2026/</link>
          <guid>https://cetra3.github.io/blog/state-of-allocators-2026/</guid>
          <description xml:base="https://cetra3.github.io/blog/state-of-allocators-2026/">&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;1398-kinds-of-allocators.html&quot;&gt;Allocators RFC&lt;&#x2F;a&gt; is about to reach a &lt;strong&gt;decade&lt;&#x2F;strong&gt; milestone of it &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;1398#issuecomment-207603823&quot;&gt;being accepted&lt;&#x2F;a&gt;, but with no stabilisation.&lt;&#x2F;p&gt;
&lt;p&gt;With the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2026&#x2F;03&#x2F;02&#x2F;2025-State-Of-Rust-Survey-results&#x2F;#challenges-and-wishes-about-rust&quot;&gt;2025 State of Rust Survey&lt;&#x2F;a&gt; indicating &lt;strong&gt;~12%&lt;&#x2F;strong&gt; would be unblocked by stabilisation and another &lt;strong&gt;~27%&lt;&#x2F;strong&gt; would have improved code, it still seems to be something that a significant portion of rust users want.&lt;&#x2F;p&gt;
&lt;p&gt;I figured it was time to take a lay of the land and work out what the current state of allocators is, where the blockers are, and any outstanding but critical issues remain. I&#x27;m hoping this will spur some activity and breathe new life into one of the older RFCs&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-current-state&quot;&gt;The Current State&lt;&#x2F;h2&gt;
&lt;p&gt;The allocator trait, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;blob&#x2F;b41f22de2a13a0babd28771e96feef4c309f54aa&#x2F;library&#x2F;core&#x2F;src&#x2F;alloc&#x2F;mod.rs#L106-L369&quot;&gt;while implemented for nightly&lt;&#x2F;a&gt;, is still unstable. It has been defined as a trait for a good 6 years or more, without many changes to the core methods of the trait.&lt;&#x2F;p&gt;
&lt;p&gt;Currently, the trait implementation contains two simple required methods:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub unsafe trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Allocator&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; allocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; AllocError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; deallocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; ...other provided methods...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Implementing this trait, you can then use this with std container types such as &lt;code&gt;Box&lt;&#x2F;code&gt; or &lt;code&gt;Vec&lt;&#x2F;code&gt; to return values allocated by your custom allocator:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; MyAllocator&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new_in&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;MyAllocator&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;Vec&lt;&#x2F;code&gt; container now has two generic types, &lt;code&gt;Vec&amp;lt;T, A&amp;gt;&lt;&#x2F;code&gt;, the type &lt;code&gt;T&lt;&#x2F;code&gt; it&#x27;s a container for, and the &lt;code&gt;A&lt;&#x2F;code&gt; allocator itself (In fact, if you dig deep enough, you can see that &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; is just a special cased version with a global allocator, i.e, &lt;code&gt;Vec&amp;lt;T, A = Global&amp;gt;&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;You need to keep around the allocator in the &lt;code&gt;Vec&lt;&#x2F;code&gt; because whenever you want to resize, truncate or drop the memory, you need to use the same allocator to do so, otherwise it&#x27;s almost impossible not to hit Undefined Behaviour, if you are fiddling around with another allocator&#x27;s memory.&lt;&#x2F;p&gt;
&lt;p&gt;In practice this field with a Zero Sized Type (ZST) like &lt;code&gt;Global&lt;&#x2F;code&gt; this does get inline compiled away, and vec is the standard &lt;code&gt;ptr&lt;&#x2F;code&gt;, &lt;code&gt;len&lt;&#x2F;code&gt;, &lt;code&gt;capacity&lt;&#x2F;code&gt;, but for other allocators that need state, this means increasing the size of &lt;code&gt;Vec&lt;&#x2F;code&gt; to include an allocator field.&lt;&#x2F;p&gt;
&lt;p&gt;The same with &lt;code&gt;Box&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; as well, this is a &lt;code&gt;Box&amp;lt;T, A&amp;gt;&lt;&#x2F;code&gt; with &lt;code&gt;Box&amp;lt;T, A = Global&amp;gt;&lt;&#x2F;code&gt; by default. Although &lt;code&gt;Box&lt;&#x2F;code&gt; is much simpler in terms of memory allocations&#x2F;chagnes, it&#x27;s only really ever allocated when created, no resizes, truncations etc... but you still need to keep the allocator around to deallocate.&lt;&#x2F;p&gt;
&lt;p&gt;So, for such a simple trait definition, it seems like consensus should be easy right? Just two methods and there is already most of the grunt work done on nightly to support it.&lt;&#x2F;p&gt;
&lt;p&gt;However: even &lt;em&gt;this&lt;&#x2F;em&gt; simple of a definition still has some outstanding questions unanswered.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;current-blockers&quot;&gt;Current Blockers&lt;&#x2F;h2&gt;
&lt;p&gt;As of writing this article, the rust allocator working group repo has &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;wg-allocators&#x2F;issues&quot;&gt;75 issues open&lt;&#x2F;a&gt;, with the roadmap not touched in a long time, and probably due for &lt;em&gt;some&lt;&#x2F;em&gt; cleanup.&lt;&#x2F;p&gt;
&lt;p&gt;Thom Chiovoloni &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;shift.click&#x2F;blog&#x2F;allocator-trait-talk&#x2F;&quot;&gt;wrote a few years ago&lt;&#x2F;a&gt; about the allocator trait and some of the blockers that exist, and even now a lot of the original referred issues have not been closed. There has been &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;old.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;1prgyc8&#x2F;stackallocator_a_project_for_a_bright_future_with&#x2F;&quot;&gt;many&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;old.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;1op6g64&#x2F;whats_the_statusblocker_for_allocator_api_to_be&#x2F;&quot;&gt;discussions&lt;&#x2F;a&gt; on reddit and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rust-lang.zulipchat.com&#x2F;#narrow&#x2F;channel&#x2F;197181-t-libs.2Fwg-allocators&#x2F;topic&#x2F;State.20of.20Allocators&#x2F;with&#x2F;577423708&quot;&gt;other places&lt;&#x2F;a&gt; since.&lt;&#x2F;p&gt;
&lt;p&gt;Now in early 2026, it seems like consensus still hasn&#x27;t been reached. While a number of those existing issues stand, here&#x27;s my opinion on what some of the main ones are. The list isn&#x27;t exhaustive, but I think covers some of the &quot;bigger&quot; style problems of the trait so far.&lt;&#x2F;p&gt;
&lt;p&gt;To be clear: I&#x27;m not strongly advocating the inclusion of any of these changes, my hope is to stimulate a bit of discussion.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zero-sized-allocations&quot;&gt;Zero Sized Allocations&lt;&#x2F;h3&gt;
&lt;p&gt;Currently, the trait allows the &lt;code&gt;Layout&lt;&#x2F;code&gt; to be defined as zero sized, which back in 2020 was known to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;wg-allocators&#x2F;issues&#x2F;82&quot;&gt;cause issues with zero sized types&lt;&#x2F;a&gt;. What happens is that the allocator contract, allows the same pointer for zero sized allocations, since we aren&#x27;t actually &quot;allocating&quot; anything. Then this might mean that returning the same pointer for different things could be considered Undefined Behaviour (although I&#x27;m not sure it strictly is). Not only that: this breaks pointer equality as well.&lt;&#x2F;p&gt;
&lt;p&gt;This means you need to special case this in all of your allocator implementations, i.e,&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Allocator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; MyAllocator&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; allocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; AllocError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;NonNull&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;dangling&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F; do actual allocations here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; deallocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F; do actual deallocations here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And so &lt;em&gt;every&lt;&#x2F;em&gt; implementation of allocator will need code similar to this example, or at least consider zero sized allocations, or wastefully allocate space just to uphold the contract. So does it make sense to keep &lt;code&gt;Layout&lt;&#x2F;code&gt; as is?&lt;&#x2F;p&gt;
&lt;p&gt;One possible fix is to introduce a &lt;code&gt;NonZeroLayout&lt;&#x2F;code&gt; type which enforces that allocations must actually have a size. This foregoes some of the footguns around zero sized allocations, but it would introduce complexity for any trait consumers.&lt;&#x2F;p&gt;
&lt;p&gt;This is a small change to the trait interface:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Our new non zero layout (other constraints left out for brevity)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonZeroLayout&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    size&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonZeroUsize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    align&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonZeroUsize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub unsafe trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Allocator&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; allocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonZeroLayout&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; AllocError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; deallocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonZeroLayout&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Sidenote:&lt;&#x2F;strong&gt; If we look at &lt;code&gt;malloc&lt;&#x2F;code&gt; in &lt;code&gt;C&lt;&#x2F;code&gt; how it behaves, it&#x27;s allowed to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.cppreference.com&#x2F;w&#x2F;c&#x2F;memory&#x2F;malloc&quot;&gt;return a null pointer&lt;&#x2F;a&gt; (among other things). However, rust&#x27;s &lt;code&gt;allocate&lt;&#x2F;code&gt; return is always &lt;code&gt;NonNull&lt;&#x2F;code&gt; and so I think that enforcing the &lt;code&gt;NonZeroLayout&lt;&#x2F;code&gt; balances out these argument types nicely.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;context-and-rust-for-linux&quot;&gt;Context and Rust for Linux&lt;&#x2F;h3&gt;
&lt;p&gt;In order to unblock things, and probably because it&#x27;s a &lt;em&gt;different&lt;&#x2F;em&gt; use case (panics are more severe in the kernel), the rust for linux team has pressed on ahead without requiring allocators to be stable. It&#x27;s worth studying the shape they came up with, because I feel as if the trait &lt;em&gt;was&lt;&#x2F;em&gt; stabilised as is, it still wouldn&#x27;t be sufficient for their use case.&lt;&#x2F;p&gt;
&lt;p&gt;Their &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rust.docs.kernel.org&#x2F;kernel&#x2F;alloc&#x2F;trait.Allocator.html&quot;&gt;allocator trait&lt;&#x2F;a&gt;, as it stands is slightly similar to the existing trait, but introduces a few extra args:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub unsafe trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Allocator&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; MIN_ALIGN&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Required method&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; realloc&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        old_layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        flags&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        nid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NumaNode&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; AllocError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Provided methods&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; alloc&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        flags&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Flags&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        nid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NumaNode&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; AllocError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; free&lt;&#x2F;span&gt;&lt;span&gt;(ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Essentially the &lt;code&gt;realloc&lt;&#x2F;code&gt; does the heavy lifting of &lt;code&gt;alloc&lt;&#x2F;code&gt; and &lt;code&gt;free&lt;&#x2F;code&gt; as well since they are provided, but it&#x27;s otherwise similar to the existing trait.&lt;&#x2F;p&gt;
&lt;p&gt;The interesting takeaway here is the &lt;code&gt;Flags&lt;&#x2F;code&gt; struct and &lt;code&gt;NumaNode&lt;&#x2F;code&gt;: both imply that not all allocation requests are equal. In fact in the kernel there are different scenarios for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rust.docs.kernel.org&#x2F;kernel&#x2F;alloc&#x2F;flags&#x2F;index.html&quot;&gt;what should happen with memory allocations&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This means that, there should be some way to provide &lt;em&gt;context&lt;&#x2F;em&gt; for a given allocation. This is discussed in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;wg-allocators&#x2F;issues&#x2F;138&quot;&gt;wg #138&lt;&#x2F;a&gt; and a bit of a sketch of a trait is included:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub unsafe trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Allocator&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Ctx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Copy&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; allocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, ctx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ctx&lt;&#x2F;span&gt;&lt;span&gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; AllocError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; deallocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While I think the ship has already sailed on rust kernel allocators, it does feel context is a strong consideration for inclusion in the base trait.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;splitting-the-traits&quot;&gt;Splitting the Traits&lt;&#x2F;h3&gt;
&lt;p&gt;One of the goals of the allocator trait is to handle more &quot;esoteric&quot; style allocations. While we want to handle standard system style alloctors like &lt;code&gt;glibc&lt;&#x2F;code&gt;, &lt;code&gt;jemalloc&lt;&#x2F;code&gt; and &lt;code&gt;mimalloc&lt;&#x2F;code&gt;, we &lt;em&gt;also&lt;&#x2F;em&gt; want to support other styles like garbage collected allocators and bump allocators.&lt;&#x2F;p&gt;
&lt;p&gt;Taking the bump allocator as an example, they deallocate all memory at once, rather than individually. So essentially a deallocation for an individual value is a no-op.&lt;&#x2F;p&gt;
&lt;p&gt;But as mentioned earlier, a &lt;code&gt;Box&lt;&#x2F;code&gt; keeps around two generic arguments, &lt;code&gt;Box&amp;lt;T, A&amp;gt;&lt;&#x2F;code&gt;. While this is fine for ZST allocators like &lt;code&gt;Global&lt;&#x2F;code&gt;, compiling down to a single pointer, if you keep around a field for the allocator, which is never actually going to be used to deallocate, then you are increasing the size of &lt;code&gt;Box&lt;&#x2F;code&gt; for no reason.&lt;&#x2F;p&gt;
&lt;p&gt;One solution discussed in the working group is to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;wg-allocators&#x2F;issues&#x2F;112&quot;&gt;split the traits into two&lt;&#x2F;a&gt;: for allocation and deallocation.&lt;&#x2F;p&gt;
&lt;p&gt;This looks something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub unsafe trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deallocator&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; deallocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonZeroLayout&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub unsafe trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Allocator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deallocator&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; allocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; AllocError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And assuming that you have a way of converting allocators to other deallocators, then, using the example from zakarumych in the issue, you can do something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; used to keep the lifetime around&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BumpDealloc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  _marker&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; PhantomData&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a Bump&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;unsafe impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deallocator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BumpDealloc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; deallocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, _ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, _layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;) {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; From&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a Bump&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BumpDealloc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; from&lt;&#x2F;span&gt;&lt;span&gt;(_bump&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a Bump&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    BumpDealloc&lt;&#x2F;span&gt;&lt;span&gt; { _marker&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; PhantomData&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(bump&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a Bump&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;  &#x2F;&#x2F; currently includes `&amp;amp;&amp;#39;a Bump` in the `Box`, making it bigger than a pointer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  let box&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a Bump&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new_in&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;, bump);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;  &#x2F;&#x2F; now it&amp;#39;s pointer sized&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  let box&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Bumped&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; box&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;size_of_val&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;box&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; size_of&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are suggestions that this could work without the split of the trait. For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BumpDealloc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;PhantomData&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a Bump&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;unsafe impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Allocator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BumpDealloc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; allocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, _&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; AllocError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;        panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;cannot allocate through BumpDealloc&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; deallocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, _&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, _&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;) {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, having this as a &lt;em&gt;runtime&lt;&#x2F;em&gt; panic feels like it goes against the spirit of rust. So it&#x27;s a trade off of keeping the trait simple, or allowing this sort of expressivity.&lt;&#x2F;p&gt;
&lt;p&gt;I have flipped back and forth on this one whether it&#x27;s worthwhile to split the traits. The only strong case in the issue is the no-op deallocator, or an deallocator that takes up &lt;em&gt;less&lt;&#x2F;em&gt; space than the allocator. So essentially you need an allocator always anyway, and the deallocator is a special pairing.&lt;&#x2F;p&gt;
&lt;p&gt;If there were &lt;em&gt;other&lt;&#x2F;em&gt; use cases that would benefit, then maybe it is worth considering. I think that as long as people are not &lt;em&gt;prevented&lt;&#x2F;em&gt; from doing what they want, then we should keep the trait simple.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;associated-error-type&quot;&gt;Associated Error Type&lt;&#x2F;h3&gt;
&lt;p&gt;Allocations can fail, and the existing trait returns a &lt;code&gt;Result&lt;&#x2F;code&gt; with &lt;code&gt;AllocError&lt;&#x2F;code&gt; as the error type. This is a ZST error which doesn&#x27;t include a whole lot of information about why the allocation failed, just that it did. It would be nice if an allocation fails, some more contextual information is included, so that the callee can recover from any issues.&lt;&#x2F;p&gt;
&lt;p&gt;This is discussed in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;wg-allocators&#x2F;issues&#x2F;23&quot;&gt;wg #23&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;wg-allocators&#x2F;issues&#x2F;106&quot;&gt;wg #106&lt;&#x2F;a&gt; with some use cases around why it would be useful to provide custom error types.&lt;&#x2F;p&gt;
&lt;p&gt;With associated errors, the trait would look like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub unsafe trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Allocator&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; core&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; allocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; deallocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Layout&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; ...other provided methods...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is obviously alternatives to this. For instance, if context was a thing, you could provide an allocation number on allocations, so you could get back the error out of band. Or you could lookup a last error in thread&lt;em&gt;local etc.. but obviously this is prone to errors if another allocation happens in between. But all of these feel a little less _nice&lt;&#x2F;em&gt; than using the existing &lt;code&gt;Result&lt;&#x2F;code&gt; type for what it&#x27;s designed for.&lt;&#x2F;p&gt;
&lt;p&gt;However, one issue around associated types is around making it easily dyn compatible. If you had an associated error type, you would need to ensure you are using &lt;code&gt;dyn Allocator&amp;lt;Error = AllocError&amp;gt;&lt;&#x2F;code&gt; everywhere rather than &lt;code&gt;dyn Allocator&lt;&#x2F;code&gt;. I don&#x27;t &lt;em&gt;think&lt;&#x2F;em&gt; this is a big deal, and the std lib could provide some helper plumbing to make it seamless, but nothing that would prevent dyn compatible allocators.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-store-api-alternative&quot;&gt;The Store API Alternative&lt;&#x2F;h3&gt;
&lt;p&gt;There exists an alternative to the allocator trait, called the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;3446&quot;&gt;Store API&lt;&#x2F;a&gt; which has seen some momentum behind it. This would unlock a few more use cases above &amp;amp; beyond the existing trait, especially around putting things on the stack.&lt;&#x2F;p&gt;
&lt;p&gt;But (and this is just my personal hot take which is not worth much!) I think it&#x27;s over-engineered and suffers from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Second-system_effect&quot;&gt;second system effect&lt;&#x2F;a&gt;, when we haven&#x27;t even got the first system out yet. It has a higher &amp;amp; more complex API surface area, introducing &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;matthieu-m&#x2F;rfcs&#x2F;blob&#x2F;store&#x2F;text&#x2F;3446-store.md#overview-1&quot;&gt;5 traits&lt;&#x2F;a&gt;, and abstracting away &lt;em&gt;pointers&lt;&#x2F;em&gt; to &lt;em&gt;handles&lt;&#x2F;em&gt; feels like unnecessary indirection. I found it a bit more difficult to follow, trying to imagine porting a simple allocator to use it, compared to the existing trait.&lt;&#x2F;p&gt;
&lt;p&gt;I feel like there is a world where we can extend beyond the base trait to support some of the better bits of the Storage API, but it feels like an even bigger uphill battle to stabilise in lieu of the existing trait. i.e, let&#x27;s take the best bits and stabilise them separately, if we can.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-stable-alternative&quot;&gt;A Stable Alternative&lt;&#x2F;h3&gt;
&lt;p&gt;With the age of this feature, it&#x27;s inevitable that there will be some experimentation of a bridge solution, while waiting for stabilisation. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zakarumych&#x2F;allocator-api2&quot;&gt;&lt;code&gt;allocator_api2&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate exists to fill this gap.&lt;&#x2F;p&gt;
&lt;p&gt;This crate mirrors the current trait definition in nightly, allowing use of the allocator trait, as it stands, on stable.&lt;&#x2F;p&gt;
&lt;p&gt;It is surprisingly a popular crate with over 250 million downloads on crates.io, and an optional dependency of crates like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;hashbrown&quot;&gt;&lt;code&gt;hashbrown&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fitzgen&#x2F;bumpalo&quot;&gt;&lt;code&gt;bumpalo&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-cost-of-monomorphisation&quot;&gt;The Cost of Monomorphisation&lt;&#x2F;h2&gt;
&lt;p&gt;This isn&#x27;t actually an existing issue, but more a discussion around some of the ramifications of the existing design. What I mean by the &lt;em&gt;cost&lt;&#x2F;em&gt; of monomorphisation, apart from the code generation angle, is the developer experience. Having a new generic argument on all containers will cause a &lt;em&gt;lot&lt;&#x2F;em&gt; of churn at call sites.&lt;&#x2F;p&gt;
&lt;p&gt;For example, right now, &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; is generic against the value itself, and nothing else. I&#x27;m sure there are millions of functions out there that have a signature like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; do_something&lt;&#x2F;span&gt;&lt;span&gt;(input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; something with the vec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, if we want out function to support custom allocated vecs, we now need to add trait bounds on the function signature:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; do_something&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Allocator&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;   &#x2F;&#x2F; something with the vec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Not only that, mixing and matching vecs with different allocators also becomes a little painful, as &lt;code&gt;Vec&amp;lt;T, A&amp;gt; != Vec&amp;lt;T, B&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can imagine this would be a nightmare to adjust everywhere. And so we need some guidance, or a solution for it. I did a small investigation around how other languages handled this, focusing on Zig and C++, since both support custom allocators.&lt;&#x2F;p&gt;
&lt;p&gt;Now, I am not an expert of either language, so there is a good chance I am wrong in some of this understanding. But the gist is that, it &lt;em&gt;feels&lt;&#x2F;em&gt; like dynamic dispatch is not as bad as it seems here.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zig-s-allocator&quot;&gt;Zig&#x27;s Allocator&lt;&#x2F;h3&gt;
&lt;p&gt;I wanted to look at how allocators worked in Zig, as the sentiment of using Zig is that it provides greater flexibility around memory allocations. So what does it do that rust doesn&#x27;t, and how does it do it?&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;blob&#x2F;master&#x2F;lib&#x2F;std&#x2F;mem&#x2F;Allocator.zig&quot;&gt;Allocator&lt;&#x2F;a&gt; is a struct with two pointers: one for the state, and the other to a VTable of const fns:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;zig&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; not really defined like this (but for illustrations only)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub const&lt;&#x2F;span&gt;&lt;span&gt; Allocator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;anyopaque&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F; opaque pointer to allocator state&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    vtable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; VTable,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;  &#x2F;&#x2F; pointer to constant function table&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub const&lt;&#x2F;span&gt;&lt;span&gt; VTable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    alloc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;const fn&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;anyopaque&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;, Alignment,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    resize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;const fn&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;anyopaque&lt;&#x2F;span&gt;&lt;span&gt;, []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;, Alignment,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    remap&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;const fn&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;anyopaque&lt;&#x2F;span&gt;&lt;span&gt;, []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;, Alignment,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    free&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;   *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;const fn&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;anyopaque&lt;&#x2F;span&gt;&lt;span&gt;, []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;, Alignment,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a type erased, dynamic dispatch style allocator. You would think that this would be slower than static dispatch, but in fact Nical &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nical.github.io&#x2F;posts&#x2F;rust-custom-allocators.html&quot;&gt;wrote a blog&lt;&#x2F;a&gt; that suggests that this isn&#x27;t always the case: sometimes the code bloat from monomorphisation outweighs the performance benefits of static dispatch.&lt;&#x2F;p&gt;
&lt;p&gt;And besides, it does look like LLVM can, in most cases, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pithlessly.github.io&#x2F;allocgate.html&quot;&gt;rewrite them as static calls anyway&lt;&#x2F;a&gt;, so you get to have your cake &amp;amp; eat it too.&lt;&#x2F;p&gt;
&lt;p&gt;How could we get something similar in rust? Well, with the trait as it exists now, we could just use &lt;code&gt;dyn Allocator&lt;&#x2F;code&gt; that essentially provides the same style dynamic dispatch, and use that as the &lt;code&gt;Allocator&lt;&#x2F;code&gt; bound in function calls:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; do_something&lt;&#x2F;span&gt;&lt;span&gt;(input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Allocator&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;   &#x2F;&#x2F; something with the vec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So with rust, we do have options to go down the dynamic dispatch path already, given the trait definition. Obviously object-safety, etc.. comes into it, but it&#x27;s not completely out of the realm of possibility&lt;&#x2F;p&gt;
&lt;h3 id=&quot;c-allocator-story&quot;&gt;C++ Allocator story&lt;&#x2F;h3&gt;
&lt;p&gt;C++ is an older language, and so you expect it to have some warts, moreso than rust.&lt;&#x2F;p&gt;
&lt;p&gt;C++ does have some of the same monomorphisation issues that rust will potentially have: different allocators means that the container type is different, but besides &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.cppreference.com&#x2F;w&#x2F;cpp&#x2F;language&#x2F;templates.html&quot;&gt;templates&lt;&#x2F;a&gt; being a solution, C++17 introduced &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.modernescpp.com&#x2F;index.php&#x2F;polymorphic-allocators-in-c17&#x2F;&quot;&gt;polymorphic memory resources&lt;&#x2F;a&gt;, or pmr to address this.&lt;&#x2F;p&gt;
&lt;p&gt;I.e, the following C++ code would error&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span&gt; vec1 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;vector&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;allocator1&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span&gt; vec2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;vector&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;allocator2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span&gt; vec &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; vec1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;vec &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; vec2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;pmr solves this with type erasure, in similar fashion to zig and &lt;code&gt;dyn&lt;&#x2F;code&gt; in rust (albeit probably not identical under the hood):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span&gt; vec1 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;pmr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;vector&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;resource1)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span&gt; vec2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;pmr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;vector&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;resource2)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span&gt; vec &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; vec1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;vec &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; vec2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So C++ started off down the static route, and moved towards dynamic dispatch. Obviously you can still use the older container types, but it might be fitting that we pay a bit more attention to dynamic dispatch with allocators, since other languages are tending towards them.&lt;&#x2F;p&gt;
&lt;p&gt;If we had some LLVM trickery to be able to statically inline in the dynamic case (if it doesn&#x27;t already exist in rust), as in Zig, we might not end up paying as much for it, or it &lt;em&gt;could&lt;&#x2F;em&gt; be free.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;three-steps-forward&quot;&gt;Three Steps Forward&lt;&#x2F;h2&gt;
&lt;p&gt;So as you can see, almost 10 years on, there is still some outstanding decisions to be made. The inertia of getting this stabilised has definitely slowed down in recent years, but there is definitely still a need to think about this.&lt;&#x2F;p&gt;
&lt;p&gt;I like to frame it as boiling down to a few possible outcomes:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Wait for a better alternative to emerge or some language features&lt;&#x2F;li&gt;
&lt;li&gt;Stabilise the trait as-is: no further changes to the API and let&#x27;s go for it&lt;&#x2F;li&gt;
&lt;li&gt;Work a little bit more on the trait and then stabilise&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;wait-for-a-better-alternative&quot;&gt;Wait for a better alternative&lt;&#x2F;h3&gt;
&lt;p&gt;This is essentially the current state of play and, unless there is something to help with the current level of inertia, in all likelihood we could still be here in another decade! I am not that pessimistic, however, and think that we can definitely solve it if there is some attention placed on it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;stabilise-as-is&quot;&gt;Stabilise as-is&lt;&#x2F;h3&gt;
&lt;p&gt;The trait, as it stands, is actually already useful and, in fact with the &lt;code&gt;allocator_api2&lt;&#x2F;code&gt; crate is already useable. And considering that the trait hasn&#x27;t changed all that much recently, it might be an indication that it&#x27;s ready for stabilisation. However, this could be because it&#x27;s on nightly, meaning not many consumers of the API exist currently. So the risk of stabilising it means that there is a missed use case.&lt;&#x2F;p&gt;
&lt;p&gt;I am partially in favour of this direction. This would eliminate the rust for linux use case and other esoteric cases, but they have pressed on without it anyway.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;work-a-little-bit-more-on-the-trait&quot;&gt;Work a little bit more on the trait&lt;&#x2F;h3&gt;
&lt;p&gt;Coming back to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;wg-allocators&#x2F;issues&quot;&gt;75 open issues&lt;&#x2F;a&gt; and some of the main blockers mentioned, we could adjust the trait slightly so that it supports some extra needed features.&lt;&#x2F;p&gt;
&lt;p&gt;I was a little strategic in selecting the blockers to focus on, as they are &lt;em&gt;all&lt;&#x2F;em&gt; composable together.&lt;&#x2F;p&gt;
&lt;p&gt;Omitting the trait split, but including: the context, non-zero layout and error associated type, you could envisage a trait looking like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub unsafe trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Allocator&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Ctx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Copy&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; core&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; allocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ctx&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonZeroLayout&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; deallocate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonNull&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, layout&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NonZeroLayout&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; ...other provided methods...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;m &lt;em&gt;not&lt;&#x2F;em&gt; implying this should be the final shape, but I think something along these lines is within the realms of possibility.&lt;&#x2F;p&gt;
&lt;p&gt;Besides blockers mentioned above, there are some unsoundness issues like the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;wg-allocators&#x2F;issues&#x2F;122&quot;&gt;Box &lt;code&gt;noalias&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; that might be resolved already, and a few other issues that might need some triage.&lt;&#x2F;p&gt;
&lt;p&gt;I think my approach would be:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Divide issues into stabilisation blockers, design trade-offs, and miscellaneous&#x2F;post stabilisation&lt;&#x2F;li&gt;
&lt;li&gt;For the stabilisation blockers that don&#x27;t &lt;em&gt;really&lt;&#x2F;em&gt; require much change of the design, if at all, these should be worked through&lt;&#x2F;li&gt;
&lt;li&gt;For the design trade-offs, a decision one way or another should be made, and incorporated in or not&lt;&#x2F;li&gt;
&lt;li&gt;For the miscellaneous&#x2F;post stabilisation issues, they can remain open if they are not critical.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I feel like working through the issues in the repo is the best path forward.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;&#x2F;h2&gt;
&lt;p&gt;As it stands, custom allocators are still not in a state to stabilise, and it would be good to stabilise them soon.&lt;&#x2F;p&gt;
&lt;p&gt;I haven&#x27;t really touched on &lt;em&gt;why&lt;&#x2F;em&gt; they are useful, since I feel that the benefits are pretty clear. My own interest in it comes from working on the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pydantic.dev&#x2F;logfire&quot;&gt;rust logfire team&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;datafusion.apache.org&#x2F;&quot;&gt;contributing to datafusion&lt;&#x2F;a&gt;, building, and &lt;a href=&quot;&#x2F;blog&#x2F;a-tale-of-two-lengths&#x2F;&quot;&gt;dealing with memory in production systems&lt;&#x2F;a&gt; that love to crash when they don&#x27;t have memory. All of these things I am working on will benefit from custom allocators, and unblock me in some cases. I want to have the tools available to wrangle allocations where it counts.&lt;&#x2F;p&gt;
&lt;p&gt;I am hoping with this article that it at least spurs some discussion and breathes new life into custom allocators.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Creating MCP Servers in Rust</title>
          <pubDate>Sun, 01 Feb 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/creating-mcp-servers-in-rust/</link>
          <guid>https://cetra3.github.io/blog/creating-mcp-servers-in-rust/</guid>
          <description xml:base="https://cetra3.github.io/blog/creating-mcp-servers-in-rust/">&lt;p&gt;MCP servers are useful tools that allow AI agents the ability to interact with applications in a prescribed fashion.  I wanted to understand how they put together so I could work out where&#x2F;how they are useful.&lt;&#x2F;p&gt;
&lt;p&gt;One of the things I found when first investigating them, is that there aren&#x27;t &lt;em&gt;that&lt;&#x2F;em&gt; many MCP servers that are written in rust, most are either NodeJS or Python.  So this is my journey of how I went about creating &lt;code&gt;todo-mcp&lt;&#x2F;code&gt;: a rust based todo list MCP server, with local state synchronisation and desktop&#x2F;android app.&lt;&#x2F;p&gt;
&lt;p&gt;Todo MCP is open source, and available at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;todo-mcp&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;todo-mcp&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;photos&#x2F;dioxus-todo-mcp.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mcp-servers-and-requirements&quot;&gt;MCP Servers and Requirements&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;em&gt;very&lt;&#x2F;em&gt; first challenge I ran into was that, if you have a number of agent windows open, they will all spawn &lt;em&gt;separate&lt;&#x2F;em&gt; MCP processes. If you are integrating with a remote web server, this isn&#x27;t much of an issue, as they will be essentially wrappers over API calls to a service that can handle multiple clients.&lt;&#x2F;p&gt;
&lt;p&gt;However, if you wanted a more &quot;local-first&quot; approach, this becomes a little hard without some state synchronisation between processes. There isn&#x27;t any central server to ask state for, and more often than not, when I think of a todo to write, I don&#x27;t want to have to be at home, or even connected to any network.&lt;&#x2F;p&gt;
&lt;p&gt;I also wanted to have a &quot;companion app&quot; open so that I could see my todo lists without having to use an MCP server at all, and mobile support, so I could use it when I am out of the house.&lt;&#x2F;p&gt;
&lt;p&gt;I had experimented already with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;automerge.org&#x2F;&quot;&gt;&lt;code&gt;automerge&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and its associated API in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;mpad&#x2F;&quot;&gt;&lt;code&gt;mpad&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to make a multiplayer text pad, and thought it would be a good fit for this project. We could use the same strategy here: use automerge CRDTs and persist to disk periodically and then when another connection to another process is made (either on the same device or on another device), then it could reconcile changes made, and update the state accordingly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;automerge-and-crdts&quot;&gt;Automerge and CRDTs&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;automerge.org&#x2F;&quot;&gt;Automerge&lt;&#x2F;a&gt; uses &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Conflict-free_replicated_data_type&quot;&gt;Conflict-free Replicated Data Types (CRDTs)&lt;&#x2F;a&gt; to ensure data synchronisation without a central authority. A CRDT is a data structure that will ensure &quot;eventual consistency&quot; to state, with some smarts around merging multiple disparate sources.&lt;&#x2F;p&gt;
&lt;p&gt;An example of a CRDT (one of the more simpler ones) is a Grow Only set. Say you have two separate processes that have a set of values that are shared:&lt;&#x2F;p&gt;
&lt;p&gt;Process A has:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Value A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Process B has:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Value B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Value C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To merge&#x2F;reconcile this, you can see the obvious choice is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Value A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Value B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Value C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The most important thing is that the output state converges. If Process A sends an update before Process B, or vice versa, the result is the same. This type of CRDT, however, is quite simplistic, and doesn&#x27;t allow you to do more complex state changes. You can imagine an extension to this would be to add another set for &quot;removed&quot; values, so you could remove the values from the set.&lt;&#x2F;p&gt;
&lt;p&gt;I.e, if starting from the last merge an update is sent like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Remove:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Value B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then the state is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Added:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Value A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Value B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Value C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Removed:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Value B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&amp;amp; the merged state is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Value A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- Value C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is sometimes called a Two Phase Set. It allows you to add &amp;amp; remove values from a set, but once a value is removed, it can&#x27;t be re-added back.&lt;&#x2F;p&gt;
&lt;p&gt;To extend this again to allow items to be added&#x2F;removed multiple times, you could add a timestamp to each of the values, when they were added or removed, and they are added&#x2F;removed based upon which set the value is in, and the newest timestamp (AKA Last Write Wins).&lt;&#x2F;p&gt;
&lt;p&gt;You can see as this gets more complex, a lot of bookkeeping is required.&lt;&#x2F;p&gt;
&lt;p&gt;For different types of data, like text, lists, objects, there are a &lt;em&gt;number&lt;&#x2F;em&gt; of different types of CRDTs available, that can sometimes be composed together to create complex state shapes. That&#x27;s where &lt;code&gt;automerge&lt;&#x2F;code&gt; comes in.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;automerge&lt;&#x2F;code&gt; provides a number of CRDTs you can use to build out your state:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Composite nested CRDTs such as lists, objects and text&lt;&#x2F;li&gt;
&lt;li&gt;Primitive CRDTs such as counters, numbers, booleans&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;autosurgeon&quot;&gt;Autosurgeon&lt;&#x2F;h3&gt;
&lt;p&gt;CRDTs are a good tool to use, and &lt;code&gt;automerge&lt;&#x2F;code&gt; provides some great foundations for using them. However, like manually writing JSON structures is a pain, and we derive with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;serde.rs&#x2F;&quot;&gt;&lt;code&gt;serde&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; most of the time, we can use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;automerge&#x2F;autosurgeon&quot;&gt;&lt;code&gt;autosurgeon&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to automatically derive a rust structure, converting it into something that can be used with &lt;code&gt;automerge&lt;&#x2F;code&gt; CRDTs&lt;&#x2F;p&gt;
&lt;p&gt;So for a &lt;code&gt;todo&lt;&#x2F;code&gt; like structure, we can write:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; autosurgeon&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Reconcile&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Hydrate&lt;&#x2F;span&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Reconcile&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Hydrate&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoList&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  todos&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Todo&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Reconcile&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Hydrate&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Todo&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    title&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    completed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; bool&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And use the hydrate&#x2F;reconcile methods in &lt;code&gt;autosurgeon&lt;&#x2F;code&gt; to manage state changes for us.&lt;&#x2F;p&gt;
&lt;p&gt;This is &lt;em&gt;not&lt;&#x2F;em&gt; without challenges, however, and seeding new processes can be tricky. When writing &lt;code&gt;mpad&lt;&#x2F;code&gt; I encountered a bit of an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;automerge&#x2F;automerge&#x2F;issues&#x2F;528&quot;&gt;issue around this&lt;&#x2F;a&gt;, which has not been resolved as of this blog. However I have managed to work around it for now.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sending-state-via-multicast&quot;&gt;Sending State via Multicast&lt;&#x2F;h2&gt;
&lt;p&gt;I elected to use Multicast to send state changes to other instances.  Multicast is (normally) a LAN protocol, that allows 1 or more processes the ability to register for packets to the same IP address&#x2F;Port combo (Within the specific Multicast IP range of &lt;code&gt;224.0.0.0&#x2F;4&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;With a bit of setup when creating a UDP socket, you can retrieve packets destined to the ip&#x2F;port pairing.  The OS will send an IGMP group request, which hopefully your router&#x2F;switch will respect, and start sending packets to your socket.  Sending packets is pretty easy, you just send them to the same ip&#x2F;port as things are listening.&lt;&#x2F;p&gt;
&lt;p&gt;However, UDP does not have the same guarantees as TCP, and with multicast TCP can&#x27;t be used.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;simple-multicast-protocol&quot;&gt;Simple Multicast Protocol&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;ve elected to create a pretty bare-bones protocol for use with UDP for sending packets from &quot;sites&quot; (i.e, instances of a process).  Essentially, given any payload to send over the network it will:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Chunk it down to fit into the standard Ethernet MTU (which is normally 1500 bytes but I capped it 1400 for a bit of headroom)&lt;&#x2F;li&gt;
&lt;li&gt;Send the site id, which is randomly generated by each process on startup, I &lt;em&gt;could&lt;&#x2F;em&gt; use the sender ip&#x2F;port but that doesn&#x27;t deal with reconnections&#x2F;network changes.&lt;&#x2F;li&gt;
&lt;li&gt;Send a sequence number, the current payload number being sent&lt;&#x2F;li&gt;
&lt;li&gt;Send a total length of the sequence &lt;code&gt;num&lt;&#x2F;code&gt;, which is how many packets will be sent for this payload&lt;&#x2F;li&gt;
&lt;li&gt;Send an index number (what packet number this is for the given sequence)&lt;&#x2F;li&gt;
&lt;li&gt;Finally the payload&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;With this we have semi-reliable network communications.  It hasn&#x27;t been widely tested with packet loss etc.. but it&#x27;s enough to get started.  Some improvements in the future we could do &lt;code&gt;NACK&lt;&#x2F;code&gt; style handling, whereby if we missed a sequence, we can request the full state from that site etc.. but for now this was enough to work reliably well in testing.  Already when a &quot;site&quot; reconnects due to network changes, it resends its full state for reconciliation each time in the first message.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;choosing-a-gui-framework&quot;&gt;Choosing a GUI Framework&lt;&#x2F;h2&gt;
&lt;p&gt;One design decision I made was that I wanted a little companion app around seeing and interacting with Todos. I also wanted support for using it on my android phone, so a cross platform UI was necessary.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;slint-the-first-attempt&quot;&gt;Slint: The First Attempt&lt;&#x2F;h3&gt;
&lt;p&gt;Slint is a rust first cross platform GUI framework with some nice editor plugins and some good primitives to get you started.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;photos&#x2F;slint-todo-mcp.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I wrote an initial version using slint, and was happy with how lightweight it was and would still consider it for new projects. However I ran into two bugs when doing some lightweight QA:&lt;&#x2F;p&gt;
&lt;p&gt;Undo&#x2F;Redo functionality did not update the &lt;code&gt;TextInput&lt;&#x2F;code&gt;, so there was no real way to get the text from the GUI and feed it into my CRDT: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;slint-ui&#x2F;slint&#x2F;issues&#x2F;9205&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;slint-ui&#x2F;slint&#x2F;issues&#x2F;9205&lt;&#x2F;a&gt;. For this one I &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;slint-ui&#x2F;slint&#x2F;pull&#x2F;9272&quot;&gt;raised a PR and got it fixed&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Text Editing on Android was not working. With garbled text and other weirdness: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;slint-ui&#x2F;slint&#x2F;issues&#x2F;9240&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;slint-ui&#x2F;slint&#x2F;issues&#x2F;9240&lt;&#x2F;a&gt;. Turns out because I wasn&#x27;t using the standard android keyboard, this caused issues. I tried a good half a day to try and fix this, by looking at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;slint-ui&#x2F;slint&#x2F;blob&#x2F;master&#x2F;internal&#x2F;backends&#x2F;android-activity&#x2F;java&#x2F;SlintAndroidJavaHelper.java&quot;&gt;the companion Java helper&lt;&#x2F;a&gt; that is used to manage inputs, but gave up in the end.&lt;&#x2F;p&gt;
&lt;p&gt;While I still think Slint is perfect for this, these issues made it seem like a bit of an uphill battle to implement something pretty simple. Most of the guts of this application isn&#x27;t in UI, so I can swap it out for any frame work. So for now, I moved onto something I had been meaning to try for a while: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dioxuslabs.com&#x2F;&quot;&gt;Dioxus&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;dioxus-embracing-webview&quot;&gt;Dioxus: Embracing Webview&lt;&#x2F;h3&gt;
&lt;p&gt;Dioxus is cross platform, but it is not native, rather it uses a webview to display the UI. There are some great time savers like hot reloading, and support for Tailwind CSS is pretty easy. Plus, I have coded enough websites to understand the quirks of that ecosystem enough to know I could get myself out of trouble. It took me far less time to get things up and running, and initial testing showed that there weren&#x27;t any major flaws.&lt;&#x2F;p&gt;
&lt;p&gt;One feature I added immediately was the ability to have multiple todo lists in a collapsible fashion:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;photos&#x2F;dioxus-todo-mcp.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The one downside is memory usage: it is essentially embedding a full browser on Desktop and so uses a lot more RAM and resources. There are some potential avenues for addressing this, such as an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dioxuslabs.com&#x2F;learn&#x2F;0.7&#x2F;beyond&#x2F;project_structure#renderers&quot;&gt;experimental native renderer&lt;&#x2F;a&gt; in the works, so hopefully this will be a good solution in the future.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mcp-server-libraries&quot;&gt;MCP Server Libraries&lt;&#x2F;h2&gt;
&lt;p&gt;There is first class support for rust MCP servers via the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;modelcontextprotocol&#x2F;rust-sdk&quot;&gt;&lt;code&gt;rmcp&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate. However, this was &lt;em&gt;also&lt;&#x2F;em&gt; not without issues. When running an MCP process within &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zed.dev&#x2F;&quot;&gt;Zed&lt;&#x2F;a&gt;, it failed to run. Turns out that some of the schema definitions were wrong and didn&#x27;t match the spec. I raised a PR and got this fixed as well: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;modelcontextprotocol&#x2F;rust-sdk&#x2F;pull&#x2F;377&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;modelcontextprotocol&#x2F;rust-sdk&#x2F;pull&#x2F;377&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;With &lt;code&gt;rmcp&lt;&#x2F;code&gt; you can use derive macros to build your MCP server:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[tool_router]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoMcp&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[tool(description &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Get all todo lists&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_todos&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;        Parameters&lt;&#x2F;span&gt;&lt;span&gt;(params)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Parameters&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;GetListParams&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Json&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;TodoListsResponse&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; McpError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;todo_state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; response&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoListsResponse&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span&gt;state)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Json&lt;&#x2F;span&gt;&lt;span&gt;(response))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then serving it is pretty easy (I only use stdio mode for MCPs):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; run_mcp&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; todo_mcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoMcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;serve&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;stdio&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    todo_mcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;waiting&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;claude-code-hook-integration&quot;&gt;Claude Code Hook Integration&lt;&#x2F;h2&gt;
&lt;p&gt;With Claude Code, while you can instrument an MCP server and run it, I wanted it to feel a little more &quot;native&quot; in that whenever there was a todo list in any agent session, I wanted that to be published. That way I could open my companion app on my phone, or desktop, and watch the todo list updates in real time. I could go make a coffee and wait for the todos to be completed before checking back in.&lt;&#x2F;p&gt;
&lt;p&gt;To accomplish that, I made a small integration with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;code.claude.com&#x2F;docs&#x2F;en&#x2F;hooks&quot;&gt;Claude Code&#x27;s hook system&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;video width=&quot;100%&quot; autoplay muted loop src=&quot;&#x2F;videos&#x2F;claude-todo-mcp.mp4&quot; &gt;&lt;&#x2F;video&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Because hooks execute a command (like a bash command) and exit, I wanted this to be pretty dumb and simple:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Receive the hook JSON from stdin&lt;&#x2F;li&gt;
&lt;li&gt;Reconcile the todo list &amp;amp; work out a good name&lt;&#x2F;li&gt;
&lt;li&gt;Add&#x2F;Update the todo in the list when things happen in claude&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Then I can add this to &lt;code&gt;~&#x2F;.claude&#x2F;settings.json&lt;&#x2F;code&gt; to have it invoked:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  &amp;quot;hooks&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;    &amp;quot;PostToolUse&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;        &amp;quot;matcher&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;TaskCreate|TaskUpdate&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;        &amp;quot;hooks&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;            &amp;quot;type&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;command&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;            &amp;quot;command&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;todo-mcp hook&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This &lt;em&gt;mostly&lt;&#x2F;em&gt; works, but needs a bit more testing. The one thing is that it&#x27;s hard to get a nice name for a &quot;claude session&quot; without a bit of song and dance, and so I have elected just to include the current working dir as a title of the list.&lt;&#x2F;p&gt;
&lt;p&gt;The other problem was sometimes Claude skips creating todos and essentially adds them completed. So for this I revert back to reading it from the todo structure in &lt;code&gt;~&#x2F;.claude&#x2F;todos&#x2F;&lt;&#x2F;code&gt; which seems to work and allows me to reconcile changes.&lt;&#x2F;p&gt;
&lt;p&gt;Obviously a bit more testing is still needed, as I have sometimes seen it not act the way I want, and sometimes claude does not even create todo lists at all, so it&#x27;s currently an open question how to address that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dealing-with-network-changes&quot;&gt;Dealing with Network Changes&lt;&#x2F;h2&gt;
&lt;p&gt;When testing out this app with my phone, I went shopping and marked off my shopping on the list as I went around the store. When I got home, I noticed that the list was now out of sync, and I had to restart the app to get things going again. Not an ideal situation.&lt;&#x2F;p&gt;
&lt;p&gt;What I wanted to happen was that when a network changed, I wanted to restart the multicast protocol tasks in a way that allowed me to reconcile when I came back home.&lt;&#x2F;p&gt;
&lt;p&gt;So I found the great &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;thombles&#x2F;netwatcher&quot;&gt;&lt;code&gt;netwatcher&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate, that allows me to register a callback to fire whenever there are any network changes. This required a bit of re-architecting and decoupling of the multicast socket to the state of the app, so that we are able to continue off where we left.&lt;&#x2F;p&gt;
&lt;p&gt;While it is cross platform, I had to end up creating a custom &lt;code&gt;AndroidManifest.xml&lt;&#x2F;code&gt; for the extra &lt;code&gt;ACCESS_NETWORK_STATE&lt;&#x2F;code&gt; permission, which isn&#x27;t &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;DioxusLabs&#x2F;dioxus&#x2F;blob&#x2F;main&#x2F;packages&#x2F;cli&#x2F;assets&#x2F;android&#x2F;gen&#x2F;app&#x2F;src&#x2F;main&#x2F;AndroidManifest.xml.hbs&quot;&gt;included in dioxus by default&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Then it was a matter of testing it. For desktop I just turned on&#x2F;off the wifi with &lt;code&gt;iwctl&lt;&#x2F;code&gt; which would allow me to simulate network failures. And for android, I could just enable&#x2F;disable wifi from settings.&lt;&#x2F;p&gt;
&lt;p&gt;However, with android there is a state where your app is loaded, but it isn&#x27;t currently on screen. In this state, the app will continue to run, but can&#x27;t use any network sockets, returning a &quot;permission denied&quot; error. To work around this, I simply retry connecting every 10 seconds or so. However, there is probably a better solution, but requires a bit more investigation. I am hopeful that in newer versions of Dioxus, this will be made a lot easier, and so I&#x27;m waiting for &lt;code&gt;0.8&lt;&#x2F;code&gt; to see if there is an easy solution to solve it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;claude-code-and-frustration-driven-development&quot;&gt;Claude Code and Frustration Driven Development&lt;&#x2F;h2&gt;
&lt;p&gt;I wanted to give Claude Code a good rinse out when making this project.  A lot of the discourse around AI is extremely positive, or entirely negative, there doesn&#x27;t seem to be as much nuance.  So while I started with a base that I wrote, when adding new features and testing ideas I first prompted claude to help plan out and implement them.&lt;&#x2F;p&gt;
&lt;p&gt;9 times out of 10, unless it was a simple change, I found the code that it wrote was both alien and hard to follow.  If this was another colleague&#x27;s PR I would sit down and work with them together to get it to a good state. But with Claude you can&#x27;t do that, it never learns above the baseline, and when that context window blows out, or a new session is created, we&#x27;re back to square one.&lt;&#x2F;p&gt;
&lt;p&gt;It felt like, when reading Claude code changes, the entire thing was a giant code smell.  It&#x27;s hard to put my finger on why it was bad, it just didn&#x27;t seem like it was idiomatic, electing to take shortcuts and otherwise not understand the context of what was happening.  This gets compounded the more features and complexity your application has.  For small things, like writing tests, and doing small refactors, this was great, but for bigger things it fell down pretty quickly.&lt;&#x2F;p&gt;
&lt;p&gt;So what I ended up doing is something I am coining &lt;strong&gt;Frustration Driven Development&lt;&#x2F;strong&gt; or &lt;strong&gt;FDD&lt;&#x2F;strong&gt; for short.  This is when you have code that is written, that does what you want, just not in an ideal fashion, and so out of frustration, you rewrite it completely.&lt;&#x2F;p&gt;
&lt;p&gt;There are sections of code I haven&#x27;t adjusted much from Claude&#x27;s initial output, and reviewing some of the source code of the initial release I can already see changes&#x2F;cleanup I&#x27;d like to make.  Since this is a bit of a hobby project, I don&#x27;t have much time to dedicate to making this pristine and in a state that I would be proud of.&lt;&#x2F;p&gt;
&lt;p&gt;So I guess that&#x27;s a small win for AI: I don&#x27;t know if I would&#x27;ve finished it in this state without using Claude Code.  I hope that when I do get round to it, I can use some &lt;strong&gt;FDD&lt;&#x2F;strong&gt; to help work through some of it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;&#x2F;h2&gt;
&lt;p&gt;Todo MCP was a lot of fun to write and I have been using it as my daily driver currently, replacing google keep for my todo lists. I actually end up using it more for the todo functionality rather than MCP&#x2F;Claude integrations, so it&#x27;s sort of evolved into something more than just an MCP server in my eyes.&lt;&#x2F;p&gt;
&lt;p&gt;There were a few learnings around writing an application like this in rust, and I feel that the ecosystem around this is still very green (i.e, slint text issues &amp;amp; rmcp not working with zed &lt;em&gt;at all&lt;&#x2F;em&gt;). I had to raise a few PRs and a few issues to get to where I am at, and there is still lots of missing documentation&#x2F;ways to do things. I&#x27;m hopeful though that in the ensuing months&#x2F;years, this will not be as big of an issue.&lt;&#x2F;p&gt;
&lt;p&gt;One last thing is around the publishing of this app. There isn&#x27;t a great story currently around using rust-based MCPs, for other languages you have &lt;code&gt;uvx&lt;&#x2F;code&gt; and &lt;code&gt;npx&lt;&#x2F;code&gt;, so I might end up making a wrapper to support either, just so it&#x27;s a lot easier for people to try out. For now a simple &lt;code&gt;cargo install todo-mcp&lt;&#x2F;code&gt; will get you going.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>A tale of two lengths</title>
          <pubDate>Sun, 11 May 2025 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/a-tale-of-two-lengths/</link>
          <guid>https://cetra3.github.io/blog/a-tale-of-two-lengths/</guid>
          <description xml:base="https://cetra3.github.io/blog/a-tale-of-two-lengths/">&lt;p&gt;They say there are 2 hard problems in computer science, and I&#x27;ve hit all 3 of them....  This is a blog post about a memory problem we were hitting in production with a service written in rust, and the tools used to resolve it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;&#x2F;h2&gt;
&lt;p&gt;Object Storage, whether S3 or something else, does not have the best performance for latency in comparison to local disk.  There can be a lot of overhead to retrieving files.  Alongside this, repetitive calls to the same files means that you will have multiple requests to the same data.  One solution is to have a local cache of files sitting close to wherever you are using them.  That way, for regularly requested files, you can reduce latency and decrease the amount of requests to the backing object store.&lt;&#x2F;p&gt;
&lt;p&gt;For a possible solution, we recently moved to using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;foyer.rs&#x2F;&quot;&gt;&lt;code&gt;foyer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, touted as a &lt;em&gt;hybrid cache&lt;&#x2F;em&gt;, as it provides not only a memory cache, but can be used with local disk storage as well. For really hot files, they would be served in memory.  For colder files, they could be read from a local ephemeral ssd, so still providing some speedup even if evicted from memory.  This looked like a great fit for our use case.&lt;&#x2F;p&gt;
&lt;p&gt;Things looked like they were going OK, until the cache had been running for a day or so. We noticed that the memory limits we were setting were not honoured, and we were seeing pod restarts with the reason set to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;configure-pod-container&#x2F;assign-memory-resource&#x2F;#exceed-a-container-s-memory-limit&quot;&gt;&lt;code&gt;OOMKilled&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Something about how we configured the cache was not right.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cache-layout&quot;&gt;Cache Layout&lt;&#x2F;h3&gt;
&lt;p&gt;In our setup, we don&#x27;t want to actually cache entire files, just the ranges of bytes that have been requested.  Our request pattern means there is never any overlap between ranges, and the exact same ranges are going to be requested repeatedly.&lt;&#x2F;p&gt;
&lt;p&gt;So our Cache Key essentially looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; CacheKey&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    end&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And our Cache Value is standard &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;bytes&#x2F;latest&#x2F;bytes&#x2F;struct.Bytes.html&quot;&gt;&lt;code&gt;Bytes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, giving us a cache that looks a bit like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ByteCacheAppState&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    write_cache&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HybridCache&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;CacheKey&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Bytes&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Of course with a cache we can&#x27;t have &lt;em&gt;unbounded&lt;&#x2F;em&gt; memory usage.  So we configure a weighter that uses the length of bytes in memory (plus a &lt;code&gt;memory_size&lt;&#x2F;code&gt; method for the key to account for the path string + two usizes, even if it&#x27;s insignificant: we want to be as accurate as possible!):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_weighter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;key, value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;memory_size&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;Bytes&lt;&#x2F;code&gt; struct is a bit of a special struct that is used in a lot of crates.  It&#x27;s essentially an &lt;code&gt;Arc&amp;lt;[u8]&amp;gt;&lt;&#x2F;code&gt; but has some magic to deal with other backing implementations.  It&#x27;s cheaply cloneable: the underlying memory isn&#x27;t cloned, just a reference count is updated.  You can also take a subslice into it as well, so that you can have a view into a portion of the backing bytes, without reallocating.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;byte-request&quot;&gt;Byte Request&lt;&#x2F;h3&gt;
&lt;p&gt;When we get a request for a range of bytes, we want to either return that ranges bytes if it&#x27;s in the cache (either memory or disk), or read from object storage, storing that in the cache, and returning the bytes.&lt;&#x2F;p&gt;
&lt;p&gt;With &lt;code&gt;foyer&lt;&#x2F;code&gt; you can use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;foyer&#x2F;latest&#x2F;foyer&#x2F;struct.HybridCache.html#method.fetch&quot;&gt;&lt;code&gt;fetch&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; method to do just that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cache_entry&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; write_cache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;fetch&lt;&#x2F;span&gt;&lt;span&gt;(cache_key,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; async move&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let mut&lt;&#x2F;span&gt;&lt;span&gt; req&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; read_from_store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;path, range,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;store)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let mut&lt;&#x2F;span&gt;&lt;span&gt; buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BytesMut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_capacity&lt;&#x2F;span&gt;&lt;span&gt;(byte_len);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        while let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(bytes)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; req&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_next&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bytes);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;freeze&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And so our cache is pretty simple.  We keep around slices of files that have been requested on the predicted chance that they will be requested again.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;troubleshooting&quot;&gt;Troubleshooting&lt;&#x2F;h2&gt;
&lt;p&gt;Since we were running into memory limit situations, we started troubleshooting what could possibly be wrong.&lt;&#x2F;p&gt;
&lt;p&gt;The first thing that we tried, was to reduce the limits that we gave to the cache to be much less than the memory limits of the pod, to see if it would plateau albeit at a higher limit.  This &lt;em&gt;seemed&lt;&#x2F;em&gt; to have worked but was still a bit variable in our memory usage.  And we still didn&#x27;t know where the extra memory usage was coming from.  We really needed to see what was going on with the heap.&lt;&#x2F;p&gt;
&lt;p&gt;One of the &lt;em&gt;advantages&lt;&#x2F;em&gt; of garbage collected languages is that you can really easily introspect the heap. For rust this was traditionally a bit harder. However, there are now some awesome tools we can use to investigate memory allocations.  One we ended up using to troubleshoot was the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;polarsignals&#x2F;rust-jemalloc-pprof&quot;&gt;&lt;code&gt;jemalloc_pprof&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;profiling-with-jemalloc-pprof&quot;&gt;Profiling with &lt;code&gt;jemalloc_pprof&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;One way to profile memory usage is to have jemalloc as the global allocator, set some settings to turn on profiling, and then use &lt;code&gt;jemalloc_pprof&lt;&#x2F;code&gt; to dump out the heap profile.&lt;&#x2F;p&gt;
&lt;p&gt;The cache is a simple &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;axum&quot;&gt;&lt;code&gt;axum&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; webserver, so we ended up creating a request endpoint we could use to read the allocation profile when the cache was warmed up.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s how you can add this to your own project, if you wanted to follow along:&lt;&#x2F;p&gt;
&lt;p&gt;Firstly, add &lt;code&gt;tikv-jemallocator&lt;&#x2F;code&gt; and the &lt;code&gt;jemalloc_pprof&lt;&#x2F;code&gt; crate to &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; with a couple of enabled features:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tikv-jemallocator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { version&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;0.6.0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; features&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;profiling&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;unprefixed_malloc_on_supported_platforms&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;jemalloc_pprof&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {version&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;0.7.0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; features&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;symbolize&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Secondly, enable this as the global allocator in &lt;code&gt;main.rs&lt;&#x2F;code&gt;, with some exported settings (see the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;polarsignals&#x2F;rust-jemalloc-pprof&quot;&gt;&lt;code&gt;jemalloc_pprof&lt;&#x2F;code&gt; readme&lt;&#x2F;a&gt; for an explanation):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[global_allocator]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;static&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; GLOBAL&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tikv_jemallocator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Jemalloc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tikv_jemallocator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Jemalloc&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[allow(non_upper_case_globals)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[export_name &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;malloc_conf&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub static&lt;&#x2F;span&gt;&lt;span&gt; malloc_conf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; b&amp;quot;prof:true,prof_active:true,lg_prof_sample:19&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;\0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Thirdly, make a simple axum request handler to return the heap:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_heap&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Response&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Body&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span&gt; prof_ctl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; jemalloc_pprof&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;PROF_CTL&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; pprof&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; prof_ctl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;dump_pprof&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Response&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;builder&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;status&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;body&lt;&#x2F;span&gt;&lt;span&gt;(pprof&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Lastly, &lt;strong&gt;Run the program&lt;&#x2F;strong&gt; and get some allocations happening.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;getting-results&quot;&gt;Getting Results&lt;&#x2F;h3&gt;
&lt;p&gt;You can use curl to save the heap locally:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;path_to_get_heap&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; heap.pprof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then you can use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;google&#x2F;pprof&quot;&gt;&lt;code&gt;pprof&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to serve the results as a webpage:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;pprof&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; -http=:8080&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; heap.pprof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;heap-results&quot;&gt;Heap Results&lt;&#x2F;h2&gt;
&lt;p&gt;With the cache service instrumented, we ran up an instance with a limit of &lt;code&gt;10GB&lt;&#x2F;code&gt; RAM for the cache.  We then warmed the cache up to the point we were seeing it go above that limit. Then we downloaded the heap, and investigated it.&lt;&#x2F;p&gt;
&lt;p&gt;Tell me if you can spot the issue in the flame graph:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;photos&#x2F;heap_profile.png&quot;&gt;&lt;img src=&quot;&#x2F;photos&#x2F;heap_profile.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;What this profile is showing us is a couple of things: about 2&#x2F;3 come from our cache &lt;code&gt;fetch&lt;&#x2F;code&gt; implementation using &lt;code&gt;BytesMut&lt;&#x2F;code&gt;, and the other comes from re-hydrated values from the foyer disk cache.&lt;&#x2F;p&gt;
&lt;p&gt;No memory leaks it seems.  However: the amount of bytes that our heap has in total is &lt;code&gt;17GB&lt;&#x2F;code&gt; which is almost &lt;em&gt;twice&lt;&#x2F;em&gt; the amount of memory we have configured in the cache.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bytesmut-and-vec&quot;&gt;&lt;code&gt;BytesMut&lt;&#x2F;code&gt; and &lt;code&gt;Vec&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;When you use &lt;code&gt;BytesMut::with_capacity&lt;&#x2F;code&gt;, this uses &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;bytes&#x2F;latest&#x2F;src&#x2F;bytes&#x2F;bytes_mut.rs.html#148-150&quot;&gt;&lt;code&gt;Vec&lt;&#x2F;code&gt; as a backing store&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; with_capacity&lt;&#x2F;span&gt;&lt;span&gt;(capacity&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BytesMut&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    BytesMut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_vec&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_capacity&lt;&#x2F;span&gt;&lt;span&gt;(capacity))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Within &lt;code&gt;Vec&lt;&#x2F;code&gt;, there are two lengths.  There is the &lt;code&gt;len()&lt;&#x2F;code&gt; which is how many initialised values it has.  Then there is &lt;code&gt;capacity()&lt;&#x2F;code&gt;, which is how much it&#x27;s asked the allocator for.  Normally this &lt;code&gt;capacity()&lt;&#x2F;code&gt; is expanded as a power of two when adding values and is always greater than or equal to the length of entries. This can mean the in-memory size is not always what you&#x27;d expect.&lt;&#x2F;p&gt;
&lt;p&gt;So we have &lt;em&gt;two&lt;&#x2F;em&gt; lengths to consider: &lt;code&gt;len()&lt;&#x2F;code&gt; and &lt;code&gt;capacity()&lt;&#x2F;code&gt;, but only &lt;code&gt;capacity()&lt;&#x2F;code&gt; gives a more accurate account of memory usage.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bytes-and-capacity&quot;&gt;&lt;code&gt;Bytes&lt;&#x2F;code&gt; and &lt;code&gt;capacity()&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;There is no &lt;code&gt;capacity()&lt;&#x2F;code&gt; method on &lt;code&gt;Bytes&lt;&#x2F;code&gt;, given that its backing could be a number of different implementations.  This isn&#x27;t &lt;em&gt;great&lt;&#x2F;em&gt; for our use case here, where we want to account for the memory usage more accurately.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;changing-to-vec-u8&quot;&gt;Changing To &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Since we can&#x27;t use &lt;code&gt;capacity()&lt;&#x2F;code&gt; on &lt;code&gt;Bytes&lt;&#x2F;code&gt;, one troubleshooting step was that we tried using &lt;code&gt;Vec&lt;&#x2F;code&gt; directly.  This won&#x27;t give us cheaply cloneable bytes, but it will at least allow us to verify that this is where the extra memory usage comes from.&lt;&#x2F;p&gt;
&lt;p&gt;So we have a cache implementation like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ByteCacheAppState&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    write_cache&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HybridCache&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;CacheKey&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With a weighter like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_weighter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;key, value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;memory_size&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;the-new-profile&quot;&gt;The New Profile&lt;&#x2F;h3&gt;
&lt;p&gt;OK, running again with a &lt;code&gt;10GB&lt;&#x2F;code&gt; limit, let&#x27;s have a look at the new flame graph profile:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;photos&#x2F;heap_profile_vec.png&quot;&gt;&lt;img src=&quot;&#x2F;photos&#x2F;heap_profile_vec.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;OK, that looks &lt;em&gt;a lot&lt;&#x2F;em&gt; better!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-actual-bug&quot;&gt;The Actual Bug&lt;&#x2F;h2&gt;
&lt;p&gt;So it looks like the difference between &lt;code&gt;len()&lt;&#x2F;code&gt; and &lt;code&gt;capacity()&lt;&#x2F;code&gt; is our culprit.  We can use this implementation, or use another struct that allows us to read actual capacity.&lt;&#x2F;p&gt;
&lt;p&gt;Problem solved right? However, this &lt;em&gt;is&lt;&#x2F;em&gt; a tale of two lengths!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;vec-with-capacity&quot;&gt;&lt;code&gt;Vec::with_capacity&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;After a bit of digging into the way allocating works on a &lt;code&gt;Vec&lt;&#x2F;code&gt;, if you create a &lt;code&gt;Vec&lt;&#x2F;code&gt; with a given capacity, it &lt;em&gt;shouldn&#x27;t&lt;&#x2F;em&gt; reallocate until the length is greater than the initial capacity, even if it&#x27;s not a power of two.  Within our &lt;code&gt;fetch()&lt;&#x2F;code&gt; method we are setting the capacity explicitly, so we should only allocate once per cache entry, and not reallocate.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;vec&#x2F;struct.Vec.html#method.with_capacity&quot;&gt;In the documentation&lt;&#x2F;a&gt; it&#x27;s implicitly stated that &lt;code&gt;with_capacity&lt;&#x2F;code&gt; does not guarantee that &lt;code&gt;capacity()&lt;&#x2F;code&gt; and &lt;code&gt;len()&lt;&#x2F;code&gt; will be equal, i.e, even in the given the example it&#x27;s written so:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_capacity&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;assert!&lt;&#x2F;span&gt;&lt;span&gt;(vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here that sneaky little &lt;code&gt;&amp;gt;=&lt;&#x2F;code&gt; sign indicates that the capacity does not have to be equal to the value given by &lt;code&gt;with_capacity&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But, &lt;em&gt;in practice currently&lt;&#x2F;em&gt;, if you use &lt;code&gt;with_capacity&lt;&#x2F;code&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;src&#x2F;alloc&#x2F;raw_vec.rs.html#414-428&quot;&gt;it will ask the allocator&lt;&#x2F;a&gt; for that &lt;em&gt;exact&lt;&#x2F;em&gt; amount and won&#x27;t reallocate until there are more entries than the initial capacity:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_capacity&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(i);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This brings us back to our initial implementation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BytesMut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_capacity&lt;&#x2F;span&gt;&lt;span&gt;(byte_len);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;while let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(bytes)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; req&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_next&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bytes);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We should only be allocating once during the call to &lt;code&gt;with_capacity&lt;&#x2F;code&gt;.  Both &lt;code&gt;len()&lt;&#x2F;code&gt; and &lt;code&gt;capacity()&lt;&#x2F;code&gt; &lt;em&gt;should&lt;&#x2F;em&gt; be equal and equal to our given capacity &lt;code&gt;byte_len&lt;&#x2F;code&gt;.  &lt;em&gt;Why&lt;&#x2F;em&gt; are they not equal and why does it, looking at the heap profile, look like there is a reallocation happening?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;inclusive-and-exclusive-ranges&quot;&gt;Inclusive and Exclusive Ranges&lt;&#x2F;h3&gt;
&lt;p&gt;We&#x27;re using standard &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Guides&#x2F;Range_requests#single_part_ranges&quot;&gt;HTTP Range requests&lt;&#x2F;a&gt; for requesting byte ranges.  In rust parlance, they are Inclusive Ranges.  I.e,&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead of &lt;em&gt;Exclusive&lt;&#x2F;em&gt; ranges.  I.e, the standard &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;ops&#x2F;struct.Range.html&quot;&gt;&lt;code&gt;Range&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And essentially everything in rust is expecting a &lt;code&gt;Range&lt;&#x2F;code&gt; instead of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;ops&#x2F;struct.RangeInclusive.html&quot;&gt;&lt;code&gt;RangeInclusive&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.  But when making http range requests we need to convert the other way.&lt;&#x2F;p&gt;
&lt;p&gt;And so to go from &lt;em&gt;exclusive&lt;&#x2F;em&gt; to &lt;em&gt;inclusive&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; range&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; end&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; range&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; inclusive&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span&gt;end;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And to go from &lt;em&gt;inclusive&lt;&#x2F;em&gt; to &lt;em&gt;exclusive&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; range&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; end&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; range&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; exclusive&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;end;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;cache-keys-and-inclusive-ranges&quot;&gt;Cache Keys and Inclusive Ranges&lt;&#x2F;h3&gt;
&lt;p&gt;Our &lt;code&gt;CacheKey&lt;&#x2F;code&gt; implementation, we store the start &amp;amp; end as an exclusive range.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; to_cache_key&lt;&#x2F;span&gt;&lt;span&gt;(path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;, range&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; RangeInclusive&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; CacheKey&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    CacheKey&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; range&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        end&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; range&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then we use this cache key to ask how much we should allocate:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; byte_len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; cache_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;end &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; cache_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;start;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then in our backing request to our object storage, we were converting it &lt;em&gt;back&lt;&#x2F;em&gt; into an inclusive range by:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; range&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; RangeRequest&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cache_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;start,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    end&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cache_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;end &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Can you spot the issue with the code above?&lt;&#x2F;p&gt;
&lt;p&gt;What is wrong with our implementation here?&lt;&#x2F;p&gt;
&lt;p&gt;If you go back and re-read how to convert from range to the other, you &lt;em&gt;might&lt;&#x2F;em&gt; catch it.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s right: the conversion in the above code is &lt;em&gt;backwards&lt;&#x2F;em&gt;.  We were converting it the wrong way!  The &lt;code&gt;byte_len&lt;&#x2F;code&gt; was &lt;em&gt;always&lt;&#x2F;em&gt; two bytes short.  Meaning that the &lt;code&gt;BytesMut&lt;&#x2F;code&gt; would &lt;em&gt;always&lt;&#x2F;em&gt; reallocate.&lt;&#x2F;p&gt;
&lt;p&gt;To make matters worse: even though our &lt;code&gt;byte_len&lt;&#x2F;code&gt; was not the &lt;em&gt;right&lt;&#x2F;em&gt; length, &lt;strong&gt;the two errors cancelled eachother out&lt;&#x2F;strong&gt;.  We ended up inadvertently sending the correct request to the object store, our downstream services got the byte ranges they wanted, and the bug went undetected.  That is, until we reach our assigned memory limits...&lt;&#x2F;p&gt;
&lt;p&gt;Adding some debug assertions in the code it was easy to make our existing tests fail when they ran:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BytesMut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_capacity&lt;&#x2F;span&gt;&lt;span&gt;(byte_len);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;while let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(bytes)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; req&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_next&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bytes);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;debug_assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(), byte_len);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;debug_assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span&gt;(), byte_len);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;the-fix&quot;&gt;The Fix&lt;&#x2F;h2&gt;
&lt;p&gt;So the fix in the end was simple: do a proper inclusive&#x2F;exclusive conversion, which would mean that we only allocate as much as we need.&lt;&#x2F;p&gt;
&lt;p&gt;Converting to the exclusive range cache key:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; to_cache_key&lt;&#x2F;span&gt;&lt;span&gt;(path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;, range&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; RangeInclusive&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; CacheKey&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    CacheKey&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; range&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        end&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; range&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Converting back to the inclusive range request:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; range&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; RangeRequest&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cache_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;start,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    end&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cache_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;end &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this in place, everything worked without having to stop using &lt;code&gt;Bytes&lt;&#x2F;code&gt;, and preventing further deep changes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusions-thoughts&quot;&gt;Conclusions &amp;amp; Thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;While rust is great at managing memory for you, there are situations where you need to keep a close eye on how much memory is being used. A cache service is a great example of that.&lt;&#x2F;p&gt;
&lt;p&gt;What &lt;em&gt;would&lt;&#x2F;em&gt; have been great from the start of the language, and definitely too late to change now, would be designing some of the standard library with fallible allocations from the get go.  If we had an API shaped for that, we would be able to catch errors like this much easier. Yes there are now methods like &lt;code&gt;try_reserve&lt;&#x2F;code&gt; on &lt;code&gt;Vec&lt;&#x2F;code&gt;, but downstream abstractions like &lt;code&gt;BytesMut&lt;&#x2F;code&gt; do not have the same methods.  Thinking this through: for a language that prides itself on explicit behaviour, this feels like one area where it could be less implicit.&lt;&#x2F;p&gt;
&lt;p&gt;In fairness, there could be more structure in place in the cache implementation to prevent this sort of bug from appearing, like using types more strongly to represent ranges etc.. If nothing else, it goes to show that sometimes bugs can be &lt;em&gt;deceptively&lt;&#x2F;em&gt; simple to fix, and having the tools to profile applications is vitally important.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Creating your own custom derive macro</title>
          <pubDate>Sun, 23 Jul 2023 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/creating-your-own-derive-macro/</link>
          <guid>https://cetra3.github.io/blog/creating-your-own-derive-macro/</guid>
          <description xml:base="https://cetra3.github.io/blog/creating-your-own-derive-macro/">&lt;p&gt;One of the things I tackled early on with when creating &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;divedb&quot;&gt;DiveDB&lt;&#x2F;a&gt; was trying to import a lot of metrics from dive logs. At regular intervals, normally every 10 seconds, a dive computer will record metrics about the dive, such as depth, tank pressure, water temperature etc... While this isn&#x27;t a &lt;em&gt;huge&lt;&#x2F;em&gt; amount of entries, nearly every SQL framework I used for it was painfully slow at importing this type of data.&lt;&#x2F;p&gt;
&lt;p&gt;The only crate that I managed to get to work with reasonable performance was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio-postgres&#x2F;latest&#x2F;tokio_postgres&#x2F;&quot;&gt;tokio-postgres&lt;&#x2F;a&gt;.  Itself being lightweight: it doesn&#x27;t include a lot of features you would expect from a full blown SQL framework like &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;diesel.rs&#x2F;&quot;&gt;diesel&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;launchbadge&#x2F;sqlx&quot;&gt;SQLx&lt;&#x2F;a&gt;. I was OK with that, I don&#x27;t mind writing a bit of raw SQL, but one thing I thought was missing was some sort of way to create a struct from a database row.&lt;&#x2F;p&gt;
&lt;p&gt;So I set out to make a really simple trait to hydrate a struct from a row. The obvious candidate for this is a procedural macro. Writing procedural macros has been written about before, but I haven&#x27;t found a terse enough guide that I was happy with. I wanted to document my approach in the odd chance it helps other people.  At the very least I have something to refer to if I need to do this again!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;aim-of-the-macro&quot;&gt;Aim of the Macro&lt;&#x2F;h2&gt;
&lt;p&gt;The Aim of the macro is to be able to write &lt;code&gt;#[derive(MyTrait)]&lt;&#x2F;code&gt; and have it fill in the trait implementation at compile time.&lt;&#x2F;p&gt;
&lt;p&gt;In this case I will be deriving a simple trait that looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tokio_postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Row&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; anyhow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; FromRow&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; hydrate a struct from a database `Row`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; from_row&lt;&#x2F;span&gt;&lt;span&gt;(row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Row&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;        Self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;marker&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Sized&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are a few things I have made the decision not to handle to keep things simple:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;SQLx is already has some great macros for validating against a live schema. I don&#x27;t want to reimplement this here.&lt;&#x2F;li&gt;
&lt;li&gt;I don&#x27;t want to pay the cost of column index lookups for named fields. Instead, we will use indices and expect the queries we write return fields in correct order.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So if I have a struct like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DiveMetric&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; time&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; depth&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; pressure&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; temperature&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It should automatically derive the trait like so:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; FromRow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DiveMetric&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; from_row&lt;&#x2F;span&gt;&lt;span&gt;(row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Row&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            time&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            depth&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            pressure&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            temperature&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;crate-layout&quot;&gt;Crate Layout&lt;&#x2F;h2&gt;
&lt;p&gt;You will need at minimum 2 crates to do this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;One crate for the macro itself.  I.e, it has &lt;code&gt;proc-macro = true&lt;&#x2F;code&gt; in the Manifest, I called this &lt;code&gt;macro&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;One crate has the definitions of the trait. I have called this &lt;code&gt;core&lt;&#x2F;code&gt;.  This crate will include the macro as a dependency&lt;&#x2F;li&gt;
&lt;li&gt;Any extra crates that require this can depend on &lt;code&gt;core&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;procedural-macro-crate&quot;&gt;Procedural Macro Crate&lt;&#x2F;h2&gt;
&lt;p&gt;A Procedural Macro Crate is built at compile time and can influence your source code, pretty much by injecting source code in the form of &quot;tokens&quot; in-line with the rest of your code.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;proc_macro&#x2F;struct.TokenStream.html&quot;&gt;&lt;code&gt;TokenStream&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; interface is very very bare minimum.  You get a list of these tokens and it&#x27;s up to you to work out what they mean.  Luckily there is a crate out there, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dtolnay&#x2F;syn&quot;&gt;&lt;code&gt;syn&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, for parsing a &lt;code&gt;TokenStream&lt;&#x2F;code&gt; into a higher level structure.  Think reflection but at compile time.&lt;&#x2F;p&gt;
&lt;p&gt;So firstly, let&#x27;s set up the crate manifest:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;package&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;divedb_macro&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;version&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;0.1.0&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;edition&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;2021&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;lib&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;proc-macro&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;dependencies&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;syn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { version&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;2&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; features&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;full&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;parsing&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a standard crate, with the only difference is in that &lt;code&gt;lib&lt;&#x2F;code&gt; section: we tell it this is a proc-macro crate.&lt;&#x2F;p&gt;
&lt;p&gt;Then, we are going to create a derive macro with the same name as the trait, i.e, &lt;code&gt;FromRow&lt;&#x2F;code&gt;.  We will just create this in &lt;code&gt;lib.rs&lt;&#x2F;code&gt; the entrypoint to our crate.&lt;&#x2F;p&gt;
&lt;p&gt;The scaffolding we have to lay out is a method that looks something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; proc_macro&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;TokenStream&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[proc_macro_derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FromRow&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; derive_from_row&lt;&#x2F;span&gt;&lt;span&gt;(input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TokenStream&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TokenStream&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; do something with the token stream here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;parsing-the-tokenstream&quot;&gt;Parsing the TokenStream&lt;&#x2F;h3&gt;
&lt;p&gt;First step is to convert a &lt;code&gt;TokenStream&lt;&#x2F;code&gt; into a structure we can work with.  We&#x27;ll use &lt;code&gt;syn&lt;&#x2F;code&gt; to do the heavy lifting here.  There are some helper methods to parse out as a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;syn&#x2F;latest&#x2F;syn&#x2F;struct.DeriveInput.html&quot;&gt;&lt;code&gt;DeriveInput&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; struct:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; parse_macro_input!&lt;&#x2F;span&gt;&lt;span&gt;(input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DeriveInput&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Looking at &lt;code&gt;DeriveInput&lt;&#x2F;code&gt;, there is the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;syn&#x2F;latest&#x2F;syn&#x2F;enum.Data.html&quot;&gt;&lt;code&gt;Data&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; enum, which is an enum of 3 different types, &lt;code&gt;Struct&lt;&#x2F;code&gt;, &lt;code&gt;Enum&lt;&#x2F;code&gt; or &lt;code&gt;Union&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We only care about structs, and don&#x27;t want to derive it for anything else.&lt;&#x2F;p&gt;
&lt;p&gt;So what we can do is an &lt;code&gt;if let&lt;&#x2F;code&gt; match on the variant we want, and otherwise error out with some sort of message that will hopefully remind you when you derive it later on.  There are a few ways to error out &amp;amp; most require a &lt;code&gt;span&lt;&#x2F;code&gt;: the portion of the &lt;code&gt;TokenStream&lt;&#x2F;code&gt; that relates to the error.  I.e, where the red squiggly line will show up. You can also &lt;code&gt;panic!&lt;&#x2F;code&gt; if you are shortcutting massively, but I wouldn&#x27;t recommend it.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve elected to do a catchall in the case it&#x27;s not in a structure that I want to support.&lt;&#x2F;p&gt;
&lt;p&gt;Using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;syn&#x2F;latest&#x2F;syn&#x2F;struct.Error.html&quot;&gt;&lt;code&gt;syn::Error&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, we can provide it a span, and a message.&lt;&#x2F;p&gt;
&lt;p&gt;Since our method needs to return a &lt;code&gt;TokenStream&lt;&#x2F;code&gt;, not a &lt;code&gt;syn::Error&lt;&#x2F;code&gt;, we can convert the error by injecting a &lt;code&gt;compile_error!()&lt;&#x2F;code&gt; in the form of a &lt;code&gt;TokenStream&lt;&#x2F;code&gt; by using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;syn&#x2F;latest&#x2F;syn&#x2F;struct.Error.html#method.to_compile_error&quot;&gt;&lt;code&gt;to_compile_error()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[proc_macro_derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FromRow&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; derive_from_row&lt;&#x2F;span&gt;&lt;span&gt;(input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TokenStream&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TokenStream&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; parse_macro_input!&lt;&#x2F;span&gt;&lt;span&gt;(input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DeriveInput&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Do something with the fields here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Catchall if we don&amp;#39;t match on the structure we don&amp;#39;t want&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    TokenStream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        syn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;            &amp;quot;Only structs with named fields can derive `FromRow`&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_compile_error&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A lot of the examples for proc macros I&#x27;ve seen introduce more methods and structure here, but for brevity I&#x27;ve kept it all in the one method.&lt;&#x2F;p&gt;
&lt;p&gt;With our high level structure out of the way, we can do an &lt;code&gt;if let&lt;&#x2F;code&gt; match on finding a struct:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; syn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Struct&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;ref&lt;&#x2F;span&gt;&lt;span&gt; data)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; we know it&amp;#39;s a struct&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You&#x27;ll find that there are actually 3 variants of a struct: Named field structs, Unnamed (tuple) structs and unit structs:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Named&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Unnamed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Unit&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It might be important if you are fleshing out a derive macro to deal with those other two cases. For this macro we only care about the first variant, the name field struct, not the other two. So we match on that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Fields&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Named&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;ref&lt;&#x2F;span&gt;&lt;span&gt; fields)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;fields {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Deal with a named-field struct&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;emitting-our-tokenstream&quot;&gt;Emitting our TokenStream&lt;&#x2F;h3&gt;
&lt;p&gt;From here, we want to iterate over the fields, and for each field emit a bit of code like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;field_name&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&amp;lt;field_idx&amp;gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However: we can&#x27;t just send a &lt;code&gt;String&lt;&#x2F;code&gt; back from our method, we need to provide a &lt;code&gt;TokenStream&lt;&#x2F;code&gt;.  This is where the second handy crate comes in: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dtolnay&#x2F;quote&quot;&gt;&lt;code&gt;quote&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. We can use the &lt;code&gt;quote!&lt;&#x2F;code&gt; macro to generate code snippets in a mostly-readable fashion and output them as a &lt;code&gt;TokenStream&lt;&#x2F;code&gt;.  One thing to note: &lt;code&gt;quote!&lt;&#x2F;code&gt; will return a &lt;code&gt;proc_macro2&lt;&#x2F;code&gt; &lt;code&gt;TokenStream&lt;&#x2F;code&gt;, so you can either call &lt;code&gt;into()&lt;&#x2F;code&gt; or use &lt;code&gt;TokenStream::from&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;So let&#x27;s iterate over our fields, and for each field, return a snippet, a &lt;code&gt;TokenStream&lt;&#x2F;code&gt;, which we can combine later:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; field_vals&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; fields&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;named&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;(i, field)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; grab the name of the field&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; = &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ident;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    quote!&lt;&#x2F;span&gt;&lt;span&gt;(#name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(#i)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;});&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;re using the standard &lt;code&gt;iter().enumerate()&lt;&#x2F;code&gt; here to get out an index number of the field and the &lt;code&gt;field.ident&lt;&#x2F;code&gt; to reflect the name of the field.&lt;&#x2F;p&gt;
&lt;p&gt;As an alternative, if instead you wanted to use column names instead of column indices, you could adjust this easily:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; field_vals&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; fields&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;named&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; name_string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    quote!&lt;&#x2F;span&gt;&lt;span&gt;(#name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(#name_string)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;});&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, now we have a list of fields, and for each field, we have a snippet of source code, the next is to combine them and implement the &lt;code&gt;FromRow&lt;&#x2F;code&gt; trait.  Once again we can use &lt;code&gt;quote!&lt;&#x2F;code&gt; to do this.&lt;&#x2F;p&gt;
&lt;p&gt;Another thing worth noting is that it&#x27;s as if the proc macro literally injects a bit of source code in-line where you call derive. This means that if you are going to refer to any structs&#x2F;crates&#x2F;modules etc.. it makes things a lot easier to refer to them via their full path.  I.e, don&#x27;t put &lt;code&gt;Row&lt;&#x2F;code&gt;, put &lt;code&gt;::tokio_postgres::Row&lt;&#x2F;code&gt; instead.&lt;&#x2F;p&gt;
&lt;p&gt;With that in mind, here&#x27;s our simple &lt;code&gt;quote!&lt;&#x2F;code&gt; statement:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ident;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;quote!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;divedb_core&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FromRow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span&gt; #name {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; from_row&lt;&#x2F;span&gt;&lt;span&gt;(row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: ::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;tokio_postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Row&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span&gt;anyhow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            #(#field_vals),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Most of this is self-explanatory.  The only weird&#x2F;interesting thing is this part:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#(#field_vals),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will just iterate over our field vals, and include each one.&lt;&#x2F;p&gt;
&lt;p&gt;Putting it all together, we get a pretty terse, but powerful proc macro:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; proc_macro&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;TokenStream&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; quote&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;quote;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; syn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{parse_macro_input,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DeriveInput&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Fields&lt;&#x2F;span&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; This derives the `FromRow` trait for structs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Requires that the query is in field order, as it just uses row indices&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[proc_macro_derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FromRow&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; derive_from_row&lt;&#x2F;span&gt;&lt;span&gt;(input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TokenStream&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TokenStream&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Parse it as a proc macro&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; parse_macro_input!&lt;&#x2F;span&gt;&lt;span&gt;(input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DeriveInput&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; syn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Struct&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;ref&lt;&#x2F;span&gt;&lt;span&gt; data)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Fields&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Named&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;ref&lt;&#x2F;span&gt;&lt;span&gt; fields)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;fields {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; field_vals&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; fields&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;named&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;(i, field)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;                let&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; = &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ident;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;                quote!&lt;&#x2F;span&gt;&lt;span&gt;(#name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(#i)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ident;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TokenStream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;quote!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; divedb_core&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FromRow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span&gt; #name {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;                fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; from_row&lt;&#x2F;span&gt;&lt;span&gt;(row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tokio_postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Row&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;, anyhow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;                    Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                        #(#field_vals),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    TokenStream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        syn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;            &amp;quot;Only structs with named fields can derive `FromRow`&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_compile_error&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;core-crate&quot;&gt;Core Crate&lt;&#x2F;h2&gt;
&lt;p&gt;The core crate implements the trait itself &amp;amp; also exports the macro as well.  If the macro &amp;amp; trait are the same name, you can cheat and &lt;code&gt;pub use&lt;&#x2F;code&gt; the macro crate so you don&#x27;t always have to import the macro &amp;amp; trait separately.&lt;&#x2F;p&gt;
&lt;p&gt;Otherwise the core &lt;code&gt;lib.rs&lt;&#x2F;code&gt; is rather simple:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; anyhow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; Export our derive macro here.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; divedb_macro&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::*&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tokio_postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Row&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Really simple ORM for `tokio_postgres`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; FromRow&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; hydrate a struct from a database `Row`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; from_row&lt;&#x2F;span&gt;&lt;span&gt;(row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Row&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;        Self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;marker&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Sized&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;standard-crate&quot;&gt;Standard Crate&lt;&#x2F;h2&gt;
&lt;p&gt;Now we have the macro crate, the core crate, we can simply &lt;code&gt;use&lt;&#x2F;code&gt; this to derive on our own types:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; divedb_core&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FromRow&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FromRow&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DiveMetric&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; time&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; depth&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; pressure&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; temperature&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;expanding-the-macro&quot;&gt;Expanding the Macro&lt;&#x2F;h3&gt;
&lt;p&gt;Remember when I said that these macros pretty much inject more source code in line?  Well you can see that intermediate output rather easily by using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dtolnay&#x2F;cargo-expand&quot;&gt;&lt;code&gt;cargo expand&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.  This will print out the results of the macro expansion and show what code is actually being generated &amp;amp; a &lt;em&gt;lot&lt;&#x2F;em&gt; more.  If you are writing something super tricky, it really helps to see this output &amp;amp; makes a great tool for debugging procedural macros.&lt;&#x2F;p&gt;
&lt;p&gt;I.e, for our above &lt;code&gt;DiveMetric&lt;&#x2F;code&gt; struct, using column indices:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; divedb_core&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FromRow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DiveMetric&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; from_row&lt;&#x2F;span&gt;&lt;span&gt;(row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tokio_postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Row&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;, anyhow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            time&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            depth&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            pressure&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            temperature&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And for using the column name variant:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; divedb_core&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FromRow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DiveMetric&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; from_row&lt;&#x2F;span&gt;&lt;span&gt;(row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tokio_postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Row&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;, anyhow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            time&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;time&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            depth&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;depth&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            pressure&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;pressure&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            temperature&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;temperature&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;As you see, it&#x27;s not &lt;em&gt;too&lt;&#x2F;em&gt; onerous to make your own custom derives.  There is a bit of boilerplate that is needed, but you can write code to write code and keep things simple.&lt;&#x2F;p&gt;
&lt;p&gt;Without greater support for compile time reflection in rust, you can reach for macros to help you remove the repetitive tasks we face as programmers&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Synchronizing state with Websockets and JSON Patch</title>
          <pubDate>Sun, 29 Jan 2023 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/synchronising-with-websocket/</link>
          <guid>https://cetra3.github.io/blog/synchronising-with-websocket/</guid>
          <description xml:base="https://cetra3.github.io/blog/synchronising-with-websocket/">&lt;p&gt;At &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.formlogic.com&#x2F;&quot;&gt;formlogic&lt;&#x2F;a&gt;, we are using rust for a number of components within our tech stack, including: internal and external web applications, coordinating and logging machining workflows, parsing an industrial domain specific language (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;G-code&quot;&gt;G-Code&lt;&#x2F;a&gt;), and more.&lt;&#x2F;p&gt;
&lt;p&gt;One of the challenges we faced early on was we had state that needed to be synchronized between rust applications, browsers and the database itself. We wanted to make sure that everyone could subscribe to state changes and everyone could have the same view. We also wanted the ability to roll back state, but preserve history i.e, have an append only immutable event log, while also being able to extend the structure of our state if we choose to in the future.&lt;&#x2F;p&gt;
&lt;p&gt;This blog will step through one possible solution for this challenge using a combination of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;WebSockets_API&quot;&gt;WebSockets&lt;&#x2F;a&gt; for transport and &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;jsonpatch.com&#x2F;&quot;&gt;JSON Patch&lt;&#x2F;a&gt; for describing changes to an arbitrary structure.&lt;&#x2F;p&gt;
&lt;p&gt;To provide an example of this, we&#x27;ll be building up everyone&#x27;s favourite &lt;strong&gt;Todo Application&lt;&#x2F;strong&gt;: a list of todos with a mark to say whether they&#x27;re completed or not. However, our version will ensure that all connected clients will, in close to real time, have updates shown.&lt;&#x2F;p&gt;
&lt;p&gt;For those wanting to skip ahead and see the finished product, you can &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;websocket_jsonpatch&#x2F;&quot;&gt;view the source here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;video width=&quot;100%&quot; autoplay muted loop src=&quot;&#x2F;videos&#x2F;websocket_jsonpatch.mp4&quot; &gt;&lt;&#x2F;video&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-json-patch&quot;&gt;What is JSON Patch&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;jsonpatch.com&#x2F;&quot;&gt;JSON Patch&lt;&#x2F;a&gt; is an RFC standard for describing patch updates to an arbitrary JSON structure.&lt;&#x2F;p&gt;
&lt;p&gt;For instance, if you had a JSON object that looked like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  &amp;quot;name&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Hello&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And a patch that looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;    &amp;quot;op&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;replace&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;    &amp;quot;path&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;&#x2F;name&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;    &amp;quot;value&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Hello World!&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then applying this patch, your object will now look like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  &amp;quot;name&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Hello World!&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Another way to think about it, is that JSON Patch can encode transitions of state, and can be considered a lightweight form of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;martinfowler.com&#x2F;eaaDev&#x2F;EventSourcing.html&quot;&gt;event sourcing&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There are a number of libraries available in all languages, including &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;idubrov&#x2F;json-patch&quot;&gt;rust&lt;&#x2F;a&gt; and for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Starcounter-Jack&#x2F;JSON-Patch&quot;&gt;browsers&lt;&#x2F;a&gt;, and as the format itself is just JSON, it makes it easy to save the patches themselves in &lt;code&gt;jsonb&lt;&#x2F;code&gt; column on your database.&lt;&#x2F;p&gt;
&lt;p&gt;JSON Patch does not, by itself, enforce any schema for the JSON document. There are some operations that can cause an error if applied incorrectly, such as out of bounds replacements in arrays, but nothing that enforces that the end result is what you are expecting. For that purpose we&#x27;re going to leverage &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;serde-rs&#x2F;serde&quot;&gt;&lt;code&gt;serde&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for its great type safety, ensuring our state is in the shape we want.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;websockets-and-updates&quot;&gt;WebSockets and Updates&lt;&#x2F;h2&gt;
&lt;p&gt;With JSON Patch we have a stream of changes to a structure we can act upon, but how do we transport it? Well, since we want browsers to be a part of this as well, a great candidate is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;WebSockets_API&quot;&gt;WebSockets&lt;&#x2F;a&gt;. WebSockets are a great way to stream things into a frontend without having the overhead of having a HTTP Connection per message. This channel can stay open for as long as the browser is open. We can receive also messages in near real time: only network latency and a bit of decoding act as a bottleneck.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily WebSocket support is not only a feature of backend frameworks, but also has clients suited to connecting as well. We&#x27;ll only be investigating browsers in this blog for brevity, but one could easily expand it to use something like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;snapview&#x2F;tokio-tungstenite&quot;&gt;&lt;code&gt;tokio-tungstenite&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to consume our messages in rust.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rust-backend&quot;&gt;Rust Backend&lt;&#x2F;h2&gt;
&lt;p&gt;For brevity&#x27;s sake we will choose &lt;code&gt;axum&lt;&#x2F;code&gt; as the backend, and their &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;axum&#x2F;tree&#x2F;main&#x2F;examples&#x2F;websockets&quot;&gt;websockets example&lt;&#x2F;a&gt; as the base. For this example to build by itself, there are a few dependent crates:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;axum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { version&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;0.6.4&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; features&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;ws&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tokio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { version&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; features&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;full&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;ws&lt;&#x2F;code&gt; feature adds in websocket support to axum, otherwise all we&#x27;ll use the defaults&lt;&#x2F;p&gt;
&lt;p&gt;For debug logs, we&#x27;ll use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;tracing&quot;&gt;&lt;code&gt;tracing&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; with &lt;code&gt;tracing-subscriber&lt;&#x2F;code&gt; to get things logged nicely to stderr:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tracing&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;0.1.37&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tracing-subscriber&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;0.3.16&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And for our example we&#x27;re going to use &lt;code&gt;serde&lt;&#x2F;code&gt; and &lt;code&gt;serde_json&lt;&#x2F;code&gt; for serialization, with &lt;code&gt;json-patch&lt;&#x2F;code&gt; as mentioned above. We&#x27;ll also include the &lt;code&gt;futures&lt;&#x2F;code&gt; crate, as we&#x27;ll see that comes in use later when we want to split the rx&#x2F;tx of a websocket channel:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;serde&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { version&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;1.0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; features&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;derive&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;serde_json&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;1.0&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;futures&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;0.3&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;json-patch&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;0.3.0&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;the-main-method&quot;&gt;The Main Method&lt;&#x2F;h3&gt;
&lt;p&gt;With the main method we want to instantiate some logging, set up our routes for our web app &amp;amp; then serve on a port. While the initial example includes some static file hosting, we will skip those routes for brevity and only include the websocket route.&lt;&#x2F;p&gt;
&lt;p&gt;Our main function becomes quite concise:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Set a sensible default for logging to ensure we see something&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;var_os&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;RUST_LOG&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;is_none&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;set_var&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;RUST_LOG&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;websocket_jsonpatch=debug&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Initialise the `fmt` subscriber which will print logs to stderr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    tracing_subscriber&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;fmt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;init&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Add in our application with the websocket handler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; app&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Router&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;route&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;ws&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get&lt;&#x2F;span&gt;&lt;span&gt;(ws_handler))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F; Add in a shared websocket state struct `WsState`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;layer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Extension&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Arc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;WsState&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;())));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Listen on port 3333 for connections&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; addr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; SocketAddr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;127.0.0.1:3333&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    debug!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Listening for requests on {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, addr);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Start up the server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    axum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;bind&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;addr)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;serve&lt;&#x2F;span&gt;&lt;span&gt;(app&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into_make_service&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;the-todo-struct&quot;&gt;The Todo Struct&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s start shaping our todo struct:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We want to name a todo list itself, such as &lt;code&gt;Shopping List&lt;&#x2F;code&gt; or &lt;code&gt;Writing a blog about Rust&lt;&#x2F;code&gt;. This also gives us an easy thing to update in the structure.&lt;&#x2F;li&gt;
&lt;li&gt;We want a list of entries, which have a name and a boolean as to whether they are marked &lt;code&gt;Completed&lt;&#x2F;code&gt; or not.&lt;&#x2F;li&gt;
&lt;li&gt;We want some convenience derives such as for serialization with serde and sensible defaults.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;With that in mind, we have the main &lt;code&gt;Todo&lt;&#x2F;code&gt; struct:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Default&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Todo&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; The main name of the todo list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; The list of todos&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    todos&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BTreeMap&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoRow&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And each Row has the following shape:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Default&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoRow&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; The name of the specific todo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Whether this todo is completed or not&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    completed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;a-note-on-using-a-btreemap-instead-of-a-vec&quot;&gt;A Note on using a &lt;code&gt;BTreeMap&lt;&#x2F;code&gt; instead of a &lt;code&gt;Vec&lt;&#x2F;code&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;An initial version of this blog included todos as a &lt;code&gt;Vec&amp;lt;TodoRow&amp;gt;&lt;&#x2F;code&gt;, but that was found to be quite noisy when clearing out completed todos. Refactoring this to use a &lt;code&gt;BTreeMap&lt;&#x2F;code&gt; instead took not long at all, and is a testament to this design being malleable. Readers are invited to adjust this shape back to a &lt;code&gt;Vec&lt;&#x2F;code&gt; or provide other fields&#x2F;values to see how to make such a change.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;making-changes&quot;&gt;Making Changes&lt;&#x2F;h3&gt;
&lt;p&gt;If you have used the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;redux.js.org&#x2F;&quot;&gt;redux pattern&lt;&#x2F;a&gt; before, you would be familiar with use actions to mutate state. We&#x27;ll build something similar here, to make it easier to describe the intent of the change and to have all the logic in one module. These actions are what are going to be sent from the browser or other clients.&lt;&#x2F;p&gt;
&lt;p&gt;When actions are received, the todo state is changed, and we generate a diff between the old and new JSON, which is then sent over the wire back to the frontend in the form of JSON Patches.&lt;&#x2F;p&gt;
&lt;p&gt;These changes are executed in serial by means of a held mutex, rather than allow concurrent updates to the state. We&#x27;ll also only have one &quot;todo&quot; list, but could imagine an easy extension to have multiple different lists, each with their own changes. For concurrency without making changes serial, a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Conflict-free_replicated_data_type&quot;&gt;CRDT&lt;&#x2F;a&gt; like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;automerge&#x2F;automerge-rs&quot;&gt;&lt;code&gt;automerge&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; could be a suitable candidate. In practice, we&#x27;ve found that, when given a low concurrent user count per JSON object, the simplicity and auditability of JSON patches is a great trade-off.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;actions&quot;&gt;Actions&lt;&#x2F;h3&gt;
&lt;p&gt;We&#x27;re going to have a few actions that are available to use (all of which should be self-descriptive):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Deserialize&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[serde(tag &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;type&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoAction&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Add&lt;&#x2F;span&gt;&lt;span&gt; { row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoRow&lt;&#x2F;span&gt;&lt;span&gt; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    ChangeName&lt;&#x2F;span&gt;&lt;span&gt; { name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Update&lt;&#x2F;span&gt;&lt;span&gt; { index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;, row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoRow&lt;&#x2F;span&gt;&lt;span&gt; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Remove&lt;&#x2F;span&gt;&lt;span&gt; { index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    RemoveCompleted&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We are using a tag to make it easier to define these in TypeScript later on. Serde will use a field named &lt;code&gt;type&lt;&#x2F;code&gt; to store the enum variant.&lt;&#x2F;p&gt;
&lt;p&gt;With those actions, we can then use them to apply to our &lt;code&gt;Todo&lt;&#x2F;code&gt; struct and update the state:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Todo&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; apply&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;, action&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoAction&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        match&lt;&#x2F;span&gt;&lt;span&gt; action {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            TodoAction&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Add&lt;&#x2F;span&gt;&lt;span&gt; { row }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;                &#x2F;&#x2F; Find the next available index&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;                let&lt;&#x2F;span&gt;&lt;span&gt; index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;todos&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;keys&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;max&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;copied&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;unwrap_or_default&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;                &#x2F;&#x2F; Insert this into our map&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;                self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;todos&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(index, row);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            TodoAction&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Update&lt;&#x2F;span&gt;&lt;span&gt; { row, index }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;                self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;todos&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(index, row);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;            &#x2F;&#x2F; Change the name of the todo list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            TodoAction&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ChangeName&lt;&#x2F;span&gt;&lt;span&gt; { name }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; name,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            TodoAction&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Remove&lt;&#x2F;span&gt;&lt;span&gt; { index }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;                self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;todos&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;remove&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;index);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;            &#x2F;&#x2F; Filter and remove all completed todo rows&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            TodoAction&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;RemoveCompleted&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;todos&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;retain&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;_, val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;| !&lt;&#x2F;span&gt;&lt;span&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;completed),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;websockets&quot;&gt;WebSockets&lt;&#x2F;h2&gt;
&lt;p&gt;We are going to use websockets as our primary means of communication between the front and backend, providing a bi-directional channel with which we can send messages.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;shared-wsstate&quot;&gt;Shared WsState&lt;&#x2F;h3&gt;
&lt;p&gt;In the &lt;code&gt;main()&lt;&#x2F;code&gt; function, we added a reference counted &lt;code&gt;WsState&lt;&#x2F;code&gt; struct via &lt;code&gt;AddExtensionLayer&lt;&#x2F;code&gt;. This represents our shared state between all websocket sessions.&lt;&#x2F;p&gt;
&lt;p&gt;Inside this struct, we are going to keep two things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Todo&lt;&#x2F;code&gt; struct as per our modelling above inside a tokio &lt;code&gt;Mutex&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;A list of websocket &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.17&#x2F;futures&#x2F;sink&#x2F;trait.Sink.html&quot;&gt;sinks&lt;&#x2F;a&gt; that we can send updates to. So when one session makes a change, it is reflected on all other sessions.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This struct looks like so:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WsState&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Our main state, behind a tokio Mutex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Mutex&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Todo&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; A list of sessions we will send changes to&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    txs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Mutex&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;SplitSink&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;WebSocket&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Message&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;adding-sessions&quot;&gt;Adding Sessions&lt;&#x2F;h4&gt;
&lt;p&gt;When we add a session, we want to send a full state to get it caught up, and then add it to our list:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; add_session&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, tx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; SplitSink&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;WebSocket&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Message&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Get a mutable lock of our transactions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span&gt; txs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;txs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Send the initial state update&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(err)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; tx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;            &#x2F;&#x2F; This method will not fail in &amp;quot;normal&amp;quot; operations so an `expect()` is OK here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            serde_json&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ServerMessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Full&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Serialize Error&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;        warn!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Could not send initial state update: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Add session to our list of sessions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    txs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(tx);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;applying-state-changes&quot;&gt;Applying State Changes&lt;&#x2F;h3&gt;
&lt;p&gt;On &lt;code&gt;WsState&lt;&#x2F;code&gt; we&#x27;ll create a method called &lt;code&gt;apply&lt;&#x2F;code&gt; which takes a &lt;code&gt;TodoAction&lt;&#x2F;code&gt; and applies this to the state, then broadcasts changes to all connected sessions. We&#x27;ll break this method down as there is a lot happening here.&lt;&#x2F;p&gt;
&lt;p&gt;The signature of this method looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; apply&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, action&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoAction&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first thing we need to do is grab a mutable reference to our existing state:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then we want to get a copy of the state as it stands currently, but as a &lt;code&gt;serde_json::Value&lt;&#x2F;code&gt; which we can use to diff:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; existing_json&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; serde_json&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span&gt;state)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After we have our &lt;code&gt;existing_json&lt;&#x2F;code&gt;, we can use the &lt;code&gt;Todo::apply()&lt;&#x2F;code&gt; method to mutate the value:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; Apply the action to our todo list.  This mutates it in place&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;apply&lt;&#x2F;span&gt;&lt;span&gt;(action);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With that applied, we can grab the new state as a &lt;code&gt;Value&lt;&#x2F;code&gt; as well:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; Serialize out the new JSON for diffing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; new_json&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; serde_json&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span&gt;state)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, we can use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;json-patch&#x2F;0.2.6&#x2F;json_patch&#x2F;fn.diff.html&quot;&gt;&lt;code&gt;diff&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; method from &lt;code&gt;json_patch&lt;&#x2F;code&gt; to automatically generate the patches needed to go from the existing to the new state:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; Get the changes using the `diff` method from `json_patch`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ops&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; diff&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;existing_json,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;new_json)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this, you&#x27;ll notice we are quite agnostic to what the shape is of the state, and how the state changes. All we need to be able to do is serialize it before and after, and we can completely change the structure internally. A further excercise would be to generalize this method to accept anything that implements &lt;code&gt;Serialize&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Ok, we have a list of patches, let&#x27;s print them out so we can inspect them:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;debug!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;New Patches:{:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, ops);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;broadcasting-our-changes&quot;&gt;Broadcasting Our Changes&lt;&#x2F;h4&gt;
&lt;p&gt;Generating changes to state is one half of this method, the other half is to broadcast this out to every session.&lt;&#x2F;p&gt;
&lt;p&gt;We will first check whether there were any changes worth broadcasting, and then will serialize it to a string&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; If there are no changes, don&amp;#39;t bother broadcasting&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; !&lt;&#x2F;span&gt;&lt;span&gt;ops&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;is_empty&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Serialize it to a json string here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; serde_json&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ServerMessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Patch&lt;&#x2F;span&gt;&lt;span&gt; { ops })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The next thing we want to do is grab all of our sessions and lock them for the time being:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; txs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;txs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, some session between now and the last broadcast could have gone away.&lt;&#x2F;p&gt;
&lt;p&gt;What we are going to do is take all the sessions out of the existing vec, replacing it with an empty one using &lt;code&gt;std::mem:take()&lt;&#x2F;code&gt;, and then try sending to each session. If there is no issue sending, we add it back to the list.&lt;&#x2F;p&gt;
&lt;p&gt;If there is an issue sending, we will log the error but not add it back, to be dropped&#x2F;cleaned up when the object is out of scope:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; We take all the txs to iterate, and replace with an empty `Vec`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;for mut&lt;&#x2F;span&gt;&lt;span&gt; tx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; mem&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;txs) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; If there is an issue sending a message we will warn about it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(err)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; tx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Text&lt;&#x2F;span&gt;&lt;span&gt;(message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;()))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;        warn!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Client disconnected: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; If there is no issue sending, then we add it back to our `Vec`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        txs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(tx)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then we&#x27;re done! To recap, when applying changes we first generate a list of patches to apply. We then send that list to all the connected sessions, cleaning up any erroneous sessions in the process.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;axum-websocket-interface&quot;&gt;Axum Websocket Interface&lt;&#x2F;h3&gt;
&lt;p&gt;Axum provides a &lt;code&gt;WebSocketUpgrade&lt;&#x2F;code&gt; struct, with which you can feed it a function (or closure) to start an async task when the websocket upgrade happens. We use this to feed in our &lt;code&gt;WsState&lt;&#x2F;code&gt; value (behind an &lt;code&gt;Arc&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; ws_handler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ws&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WebSocketUpgrade&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Extension&lt;&#x2F;span&gt;&lt;span&gt;(state)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Extension&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Arc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;WsState&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; IntoResponse&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    debug!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;New Websocket Connection&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ws&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;on_upgrade&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;socket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; handle_socket&lt;&#x2F;span&gt;&lt;span&gt;(socket, state))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;server-messages&quot;&gt;Server Messages&lt;&#x2F;h3&gt;
&lt;p&gt;To keep things simple we will have an enum of possible messages the server&#x2F;backend can send to clients. There are going to be only two types: a list of patches to apply or a full todo struct. When clients first connect, we need to get them caught up with the current state of the world, so we send them the full state.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[serde(tag &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;type&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ServerMessage&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Patch&lt;&#x2F;span&gt;&lt;span&gt; { ops&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;PatchOperation&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Full&lt;&#x2F;span&gt;&lt;span&gt; { todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;a Todo&lt;&#x2F;span&gt;&lt;span&gt; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As per the &lt;code&gt;TodoAction&lt;&#x2F;code&gt; we&#x27;ll use a &lt;code&gt;type&lt;&#x2F;code&gt; tag for ease of integration with TypeScript. Also notice that we will be able to send multiple patches in one message. This is for in the case of a change causing a cascade of patches, such as when removing completed items in the todo list.&lt;&#x2F;p&gt;
&lt;p&gt;This &lt;code&gt;ServerMessage&lt;&#x2F;code&gt; enum will be serialized on the wire as JSON. Websockets support standard text messages, as well as binary types. A further exercise would be to use a different encoding, such as &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cbor.io&#x2F;&quot;&gt;&lt;code&gt;CBOR&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, but does make things a bit less human readable&lt;&#x2F;p&gt;
&lt;h3 id=&quot;handle-socket&quot;&gt;Handle Socket&lt;&#x2F;h3&gt;
&lt;p&gt;Our &lt;code&gt;handle_socket&lt;&#x2F;code&gt; method is responsible for initiating new session &amp;amp; feeding that session into the &lt;code&gt;WsState&lt;&#x2F;code&gt; struct.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; handle_socket&lt;&#x2F;span&gt;&lt;span&gt;(socket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WebSocket&lt;&#x2F;span&gt;&lt;span&gt;, state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Arc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;WsState&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Magic happens here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Firstly, we&#x27;ll split up the websocket into a tx&#x2F;rx pair. We&#x27;ll have the &lt;code&gt;handle_socket&lt;&#x2F;code&gt; hold onto the &lt;code&gt;rx&lt;&#x2F;code&gt; part, and move the &lt;code&gt;tx&lt;&#x2F;code&gt; into the &lt;code&gt;WsState&lt;&#x2F;code&gt; value. If you have a struct that implements &lt;code&gt;Stream&lt;&#x2F;code&gt; and &lt;code&gt;Sink&lt;&#x2F;code&gt; you can use futures and &lt;code&gt;StreamExt&lt;&#x2F;code&gt; to split this into two separate objects, with separate ownership of both.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (tx,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span&gt; rx)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; socket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;ll then add this session to our shared state:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_session&lt;&#x2F;span&gt;&lt;span&gt;(tx)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This method will fire off a &lt;code&gt;ServerMessage::Full&lt;&#x2F;code&gt; with the current state, returning early if this fails&lt;&#x2F;p&gt;
&lt;p&gt;Then, we simply loop any messages received from the client &amp;amp; apply them to our shared state. The type of messages we receive from the client will be our &lt;code&gt;TodoAction&lt;&#x2F;code&gt; enum.&lt;&#x2F;p&gt;
&lt;p&gt;To loop while there are messages, we can use the following &lt;code&gt;let&lt;&#x2F;code&gt; binding:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;while let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(msg))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; rx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This loop will terminate if there are no more messages to receive (i.e, the stream is finished and returning &lt;code&gt;None&lt;&#x2F;code&gt;), and if there are any errors receiving messages.&lt;&#x2F;p&gt;
&lt;p&gt;Inside the loop, we decode the message as JSON, and throw a warning if it&#x27;s a message we&#x27;re not expecting. We then apply that message to our shared state. As above, the shared state will in turn broadcast out JSON patches to update the state:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; Loop until there are no messages or an error&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;while let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(msg))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; rx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Text&lt;&#x2F;span&gt;&lt;span&gt;(text)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; msg {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F; Decode our message and warn if it&amp;#39;s something we don&amp;#39;t know about&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Ok&lt;&#x2F;span&gt;&lt;span&gt;(action)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; serde_json&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;TodoAction&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;text) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;            &#x2F;&#x2F; Apply the state, which will broadcast out changes as a JSON patch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(err)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;apply&lt;&#x2F;span&gt;&lt;span&gt;(action)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;                warn!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Error applying state:{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            warn!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Unknown action received:{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, text);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok! So we have the shape of our data, some actions to mutate the state and some scaffolding to wire up the websockets. What&#x27;s next is to build the frontend.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;react-frontend&quot;&gt;React Frontend&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;re going to build a companion browser application to use our backend. This will be built in react, but could be built using any framework, or even vanilla javascript. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vitejs.dev&#x2F;&quot;&gt;Vite&lt;&#x2F;a&gt; will be the build tool of choice, given it has a fast development feedback loop and supports React&#x2F;TypeScript. For styling, we&#x27;ll use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;picturepan2.github.io&#x2F;spectre&#x2F;&quot;&gt;spectre.css&lt;&#x2F;a&gt; to make it look a little better than the standard style and provide some responsivness. You can create a new vite project by running:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;yarn create vite front --template react-ts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;ll want to run the rust backend in another terminal window with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then we want to proxy all requests to &lt;code&gt;&#x2F;ws&lt;&#x2F;code&gt; to the backend which we can do by changing the &lt;code&gt;vite.config.ts&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;export default&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; defineConfig&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  plugins&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;react&lt;&#x2F;span&gt;&lt;span&gt;()]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    proxy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;      &amp;quot;&#x2F;ws&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        target&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;http:&#x2F;&#x2F;127.0.0.1:3333&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ws&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With that in place, we can &lt;code&gt;yarn dev&lt;&#x2F;code&gt; to get up a developer window.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;todo-structure&quot;&gt;Todo Structure&lt;&#x2F;h3&gt;
&lt;p&gt;We want to have the todo structure imitate what&#x27;s in the backend. For brevity here we&#x27;ll just write them by hand, but there does exist tools to have these structures generated automatically (see the blog: &lt;a href=&quot;&#x2F;blog&#x2F;sharing-types-with-the-frontend&#x2F;&quot;&gt;Publishing Rust types to a TypeScript frontend&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Starting off with the &lt;code&gt;Todo&lt;&#x2F;code&gt; struct itself:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;export interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Todo&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  todos&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; { [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; number&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoRow&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;export interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoRow&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; number&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  completed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; boolean&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, we deviate a little bit with the actions. In the backend we have used a tagged enum with the &lt;code&gt;type&lt;&#x2F;code&gt; property to define what action is in use. In typescript, we will use a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;docs&#x2F;handbook&#x2F;2&#x2F;narrowing.html#discriminated-unions&quot;&gt;&lt;strong&gt;Discriminated Union&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; pattern to define these actions in a compatible way:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;export interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Add&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoRow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;export interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ChangeName&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;ChangeName&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;export interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Update&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Update&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoRow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; number&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;export interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Remove&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Remove&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; number&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;export interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; RemoveCompleted&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;RemoveCompleted&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;export type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoAction&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ChangeName&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Update&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Remove&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; RemoveCompleted&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;websocket-component&quot;&gt;Websocket Component&lt;&#x2F;h3&gt;
&lt;p&gt;For the Websocket component, we&#x27;ll cheat a little bit and use some global variables to hold around both the websocket connection itself &amp;amp; the shared state. Using react hooks we&#x27;ll integrate with components to allow state changes to come through.&lt;&#x2F;p&gt;
&lt;p&gt;Firstly, we define our server messages as per the backend. We&#x27;ll be using the same &lt;strong&gt;Discriminated Union&lt;&#x2F;strong&gt; pattern.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Patch&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Patch&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;  &#x2F;&#x2F; `Operation` from `fast-json-patch` module&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ops&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Operation&lt;&#x2F;span&gt;&lt;span&gt;[]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Full&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Full&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ServerMessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Patch&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Full&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, let&#x27;s set up our global variables:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; websocket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WebSocket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; undefined&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; undefined&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We use &lt;code&gt;undefined&lt;&#x2F;code&gt; to indicate those values aren&#x27;t initialised. Both the websocket &amp;amp; the todo itself are initialised at different times.&lt;&#x2F;p&gt;
&lt;p&gt;Then, we&#x27;ll create a &lt;code&gt;setupWebsocket&lt;&#x2F;code&gt; function which will handle the connection &amp;amp; and plumbing needed to send and receive messages. We&#x27;ll want to have a callback function to accept a new &lt;code&gt;todo&lt;&#x2F;code&gt; object which we&#x27;ll use to integrate into react hooks later.&lt;&#x2F;p&gt;
&lt;p&gt;So with the the signature looks like the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; setupWebsocket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;onTodoUpdate&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Todo&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; void&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;   ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then we want to create a new &lt;code&gt;WebSocket&lt;&#x2F;code&gt;, but we need to pass it a valid uri. Websockets use &lt;code&gt;ws:&#x2F;&#x2F;&lt;&#x2F;code&gt; instead of &lt;code&gt;http:&#x2F;&#x2F;&lt;&#x2F;code&gt; and &lt;code&gt;wss:&#x2F;&#x2F;&lt;&#x2F;code&gt; instead of &lt;code&gt;https:&#x2F;&#x2F;&lt;&#x2F;code&gt; for their URLs, so we&#x27;ll split apart the current &lt;code&gt;window.location&lt;&#x2F;code&gt; and use components of it to build our uri:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; loc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; window&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;location&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; uri&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;loc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;protocol&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ===&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;https:&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;wss:&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;ws:&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;loc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;host&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&#x2F;ws`&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;console&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;`Connecting websocket: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;uri&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; = new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; WebSocket&lt;&#x2F;span&gt;&lt;span&gt;(uri)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, with our connection created we will need to listen to different events, and execute accordingly.&lt;&#x2F;p&gt;
&lt;p&gt;Firstly, when the connection is opened, we&#x27;ll log that its connected and then set our global &lt;code&gt;websocket&lt;&#x2F;code&gt; variable equal to this connection:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;onopen&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  console&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Websocket Connected&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  websocket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, there is a case that a websocket connection drops while you have the page open. We want to recover from this somewhat gracefully, retrying the connection until it&#x27;s successful.&lt;&#x2F;p&gt;
&lt;p&gt;One way of doing this is to re-execute the &lt;code&gt;setupWebsocket&lt;&#x2F;code&gt; method after a bit of time has passed, and that&#x27;s what we&#x27;ll do here, retry the setup after half a second has passed. If the websocket has closed gracefully, then we don&#x27;t bother retrying:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; If we receive a close event the backend has gone away, we try reconnecting in a bit of time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;onclose&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;reason&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  websocket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; undefined&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;  &#x2F;&#x2F; https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;CloseEvent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; (reason&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;code&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; !==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt; reason&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;code&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; !==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1001&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    console&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Websocket connection closed&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; reason)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    setTimeout&lt;&#x2F;span&gt;&lt;span&gt;(()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;      setupWebsocket&lt;&#x2F;span&gt;&lt;span&gt;(onTodoUpdate)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 500&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, if there is an error with the websocket we can log what that error is, then close it&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;onerror&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  console&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Error with websocket&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; error)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;close&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok with the websocket life cycle out of the way, now comes to the meat of our event loop. What we&#x27;re going to do is listen for server events, and if either type is received, act accordingly:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;For the &lt;code&gt;Full&lt;&#x2F;code&gt; server message, the &lt;code&gt;todo&lt;&#x2F;code&gt; object will be replaced outright.&lt;&#x2F;li&gt;
&lt;li&gt;For the &lt;code&gt;Patch&lt;&#x2F;code&gt;, we will use the &lt;code&gt;fast-json-patch&lt;&#x2F;code&gt; module to mutate &lt;code&gt;todo&lt;&#x2F;code&gt; in place, and then execute our callback:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Whatever the type of message, the full &lt;code&gt;todo&lt;&#x2F;code&gt; object is provided to the callback, with the patch merging logic happening here, and shielded from our callback update.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;onmessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;message&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;  &#x2F;&#x2F; Parse the message via JSON, asserting what we&amp;#39;ll get from the backend&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span&gt; msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; JSON&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;(message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ServerMessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  switch&lt;&#x2F;span&gt;&lt;span&gt; (msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;type) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    case&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Patch&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;      &#x2F;&#x2F; Mutate the todo state in place, and then send an update&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;      if&lt;&#x2F;span&gt;&lt;span&gt; (todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; !==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; undefined&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; { newDocument: newTodo }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; applyPatch&lt;&#x2F;span&gt;&lt;span&gt;(todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ops&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; false&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;        onTodoUpdate&lt;&#x2F;span&gt;&lt;span&gt;(newTodo)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; newTodo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;      break&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    case&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Full&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;      &#x2F;&#x2F; Send on the full todo state&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;      onTodoUpdate&lt;&#x2F;span&gt;&lt;span&gt;(msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;todo)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;      break&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, we&#x27;re almost done with the websocket, we need to integrate it a tiny bit nicer with react and react hooks.&lt;&#x2F;p&gt;
&lt;p&gt;Firstly, using the &lt;code&gt;useEffect&lt;&#x2F;code&gt; hook, we&#x27;ll expose the &lt;code&gt;todo&lt;&#x2F;code&gt; state to a component which will rerender on object updates. You can provide a function starting with the keyword &lt;code&gt;use&lt;&#x2F;code&gt; to have it part of of the react render lifecycle.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll bind a call back to update a variable &lt;code&gt;todo&lt;&#x2F;code&gt; handled with &lt;code&gt;useState&lt;&#x2F;code&gt; when there are changes, and then return that variable state from the function to use in another component.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;export const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; useWebsocket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;  &#x2F;&#x2F; Keep our local state of the todo app to trigger a render on change&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span&gt; [todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; updateTodo]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; useState&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Todo&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  useEffect&lt;&#x2F;span&gt;&lt;span&gt;(()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Update our app state when changes are received&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    setupWebsocket&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;      updateTodo&lt;&#x2F;span&gt;&lt;span&gt;(msg)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; If the destructor runs, clean up the websocket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; ()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;      if&lt;&#x2F;span&gt;&lt;span&gt; (websocket) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        websocket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; The empty `[]` dependency list makes this `useEffect` callback execute only once on construction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; [])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span&gt; todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Another way of looking at it is this function is purely glue code to make it easy to integrate with react.&lt;&#x2F;p&gt;
&lt;p&gt;Lastly, we&#x27;ll cheat again with our global variables and have a &lt;code&gt;sendAction&lt;&#x2F;code&gt; method which will, if the websocket is up and running, send a &lt;code&gt;TodoAction&lt;&#x2F;code&gt; to the backend:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;export const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; sendAction&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;action&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoAction&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; (websocket) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    websocket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(JSON&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;stringify&lt;&#x2F;span&gt;&lt;span&gt;(action))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;react-components&quot;&gt;React Components&lt;&#x2F;h3&gt;
&lt;p&gt;We now have our general shape of our todo app, and have our websocket connection abstracted away nicely it&#x27;s time to build up components.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll start with the main &lt;code&gt;App&lt;&#x2F;code&gt; component. This will be our root component, and will be responsible for building other components based upon the state. The &lt;code&gt;App&lt;&#x2F;code&gt; component is a perfect candidate to use our &lt;code&gt;useWebsocket&lt;&#x2F;code&gt; hook we have defined.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll add in a small &quot;loading&quot; indicator if the &lt;code&gt;todo&lt;&#x2F;code&gt; state is undefined, otherwise we&#x27;ll pass on our &lt;code&gt;todo&lt;&#x2F;code&gt; state to a component:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; App&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span&gt; todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; useWebsocket&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; className&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;container grid-lg&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; className&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;columns&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; className&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;column col-lg-12 todo-title&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;          &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Todo App Example&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;        &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span&gt;todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ===&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; undefined&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; className&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;loading loading-lg&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span&gt;todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;TodoComponent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  )&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;todo-component&quot;&gt;Todo Component&lt;&#x2F;h4&gt;
&lt;p&gt;Our &lt;code&gt;TodoComponent&lt;&#x2F;code&gt; is responsible for some of the more &quot;global&quot; actions of our state, such as adding a new todo, changing the todo list name and clearing out completed todos.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start with a standard functional component that takes a &lt;code&gt;todo&lt;&#x2F;code&gt; property as input:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; TodoComponent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;{ todo }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; { todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Todo&lt;&#x2F;span&gt;&lt;span&gt; }) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt; &amp;lt;&amp;gt;&amp;lt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, let&#x27;s build in the &lt;code&gt;todo.name&lt;&#x2F;code&gt; property. If we want users to be able to edit it, it should live in an input field:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will ensure the value is reflected, and since our &lt;code&gt;todo&lt;&#x2F;code&gt; object is &quot;hooked&quot; in to react, it will update when it changes.&lt;&#x2F;p&gt;
&lt;p&gt;The next step is to use an &lt;code&gt;onChange&lt;&#x2F;code&gt; callback to the input to send actions to the backed on change. We want to fire the &lt;code&gt;ChangeName&lt;&#x2F;code&gt; action, and so we can use the &lt;code&gt;sendAction&lt;&#x2F;code&gt; function from the websocket module to trigger this change.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  onChange&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;ev&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    sendAction&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;ChangeName&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; ev&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;currentTarget&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With that in place, we have the bare minimum implemented to see state changes. Now would be a great time, if you have been following along, to fire up your IDE and see what happens when you type in that input field (make sure the backend is running!).&lt;&#x2F;p&gt;
&lt;p&gt;Now, for each &lt;code&gt;TodoRow&lt;&#x2F;code&gt; we&#x27;ll create a &lt;code&gt;TodoRowComponent&lt;&#x2F;code&gt;, which will be responsible for the state of that given row:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;entries&lt;&#x2F;span&gt;&lt;span&gt;(todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;todos)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(([&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; row&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;TodoRowComponent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And underneath our the list, we will have two buttons.&lt;&#x2F;p&gt;
&lt;p&gt;One that only displays if there are todos that are completed:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;entries&lt;&#x2F;span&gt;&lt;span&gt;(todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;todos)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;some&lt;&#x2F;span&gt;&lt;span&gt;(([&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; val&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;completed)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;button&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    className&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;btn&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    onClick&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;      sendAction&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;RemoveCompleted&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;  &amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Remove Completed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And one that adds an extra item to the list:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;button&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  onClick&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; entries&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;entries&lt;&#x2F;span&gt;&lt;span&gt;(todo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;todos)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    sendAction&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Add&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        completed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; false&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Add Todo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;todorowcomponent&quot;&gt;TodoRowComponent&lt;&#x2F;h4&gt;
&lt;p&gt;The TodoRowComponent will take a &lt;code&gt;TodoRow&lt;&#x2F;code&gt; and the &lt;code&gt;index&lt;&#x2F;code&gt; of that row, and display actions for the items in our todo list:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; TodoRowComponent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;{ row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; index }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; { row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TodoRow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;span&gt; index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; number&lt;&#x2F;span&gt;&lt;span&gt; }) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can add in a check box to mark things completed or not:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;checkbox&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  checked&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;completed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  onChange&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    sendAction&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Update&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        ...&lt;&#x2F;span&gt;&lt;span&gt;row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        completed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; !&lt;&#x2F;span&gt;&lt;span&gt;row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;completed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And an input for the name of the specific todo list:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;text&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  onChange&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;ev&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    sendAction&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Update&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        ...&lt;&#x2F;span&gt;&lt;span&gt;row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; ev&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;currentTarget&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And a button to remove that row:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;button&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  onClick&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    sendAction&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Remove&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;running-and-debugging&quot;&gt;Running and Debugging&lt;&#x2F;h2&gt;
&lt;p&gt;Ok, we now have a frontend wired up to a backend, with a websocket used for state updates. Let&#x27;s change a few values around and see what is going across the &quot;wire&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;The easiest way to do this, is via your browser&#x27;s network tab, looking for the request to &lt;code&gt;ws:&#x2F;&#x2F;localhost:3000&#x2F;ws&lt;&#x2F;code&gt;. In chrome, the tab you&#x27;re looking for is &lt;code&gt;Messages&lt;&#x2F;code&gt;, and in firefox it&#x27;s &lt;code&gt;Response&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can also use a tool like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vi&#x2F;websocat&quot;&gt;&lt;code&gt;websocat&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to view the messages in a terminal.&lt;&#x2F;p&gt;
&lt;p&gt;Running this up, you&#x27;ll see the initial message come through when subscribed:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;type&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Full&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;todo&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;name&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;todos&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [] } }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, making changes you will see the updates feed in. For instance if you click the &lt;code&gt;Add Todo&lt;&#x2F;code&gt; button, you&#x27;ll see an outbound action:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;type&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Add&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;row&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;name&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;completed&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt; } }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Followed by a patch update from the server:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  &amp;quot;type&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Patch&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  &amp;quot;ops&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;      &amp;quot;op&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;add&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;      &amp;quot;path&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;&#x2F;todos&#x2F;0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;      &amp;quot;value&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;completed&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; false&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;name&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Go ahead and try out other updates to see what patches are generated and get a feel for the JSON patch format.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;&#x2F;h2&gt;
&lt;p&gt;Starting from the backend and then building out the frontend, we&#x27;ve used Websockets and JSON Patch to provide a platform of shared state updates.&lt;&#x2F;p&gt;
&lt;p&gt;Using existing standards and combining them together makes for a powerful and solid foundation. With rust, we get some great concurrency primitives that we can rely on to ensure our logic is correct.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ve demonstrated here that, we can provide a powerful framework, abstracting away our transport and state update logic, with room to grow.&lt;&#x2F;p&gt;
&lt;p&gt;The code for this article is available in a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;websocket_jsonpatch&#x2F;&quot;&gt;source repository here&lt;&#x2F;a&gt;, so please feel free to tweak.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Publishing Rust types to a TypeScript frontend</title>
          <pubDate>Tue, 13 Sep 2022 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/sharing-types-with-the-frontend/</link>
          <guid>https://cetra3.github.io/blog/sharing-types-with-the-frontend/</guid>
          <description xml:base="https://cetra3.github.io/blog/sharing-types-with-the-frontend/">&lt;p&gt;When building in a strongly-typed language such as rust it&#x27;s a shame to have to throw this strictness away, &lt;strong&gt;especially&lt;&#x2F;strong&gt; when dealing with the wild west of frontend stacks. The bigger the project is, the more you want to keep things cohesive.&lt;&#x2F;p&gt;
&lt;p&gt;This cohesion evaporates quickly when you need to pass language barriers. While normal JavaScript does not have types, we can utilise &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;&quot;&gt;TypeScript&lt;&#x2F;a&gt; to share this type information and hopefully maintain some cohesion between languages.&lt;&#x2F;p&gt;
&lt;p&gt;The scenario we&#x27;re targeting here is writing a web backend in rust, and having those types&#x2F;methods available easily for a &lt;code&gt;TypeScript&lt;&#x2F;code&gt; enabled frontend. This article describes a few common methods we can bridge the two languages together using currently available tools and libraries. Most of them follow similar characteristics, but each approach has their own set of tradeoffs.&lt;&#x2F;p&gt;
&lt;p&gt;This blog will primarily use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;actix.rs&#x2F;&quot;&gt;&lt;code&gt;actix-web&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; as the example for the web backend, as it is one I&#x27;m most familiar with, but the libraries used here do have support for other backends.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;derive-macros&quot;&gt;Derive Macros&lt;&#x2F;h2&gt;
&lt;p&gt;Strictly speaking, all these methods use derive macros in some way, but what I am describing here is using derive macros to publish structs&#x2F;objects as typescript definitions. These don&#x27;t include function&#x2F;methods or http requests (which will be discussed later on).&lt;&#x2F;p&gt;
&lt;p&gt;Rust does not have runtime reflection built into the language &amp;amp; so relies on decorating types via macros to provide some sort of approximate &quot;reflection&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;In terms of the two main derive macro libraries to choose from, we have &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;ts-rs&quot;&gt;&lt;code&gt;ts-rs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;schemars&quot;&gt;&lt;code&gt;schemars&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Both of these libraries are integrated tightly with &lt;code&gt;serde&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ts-rs&quot;&gt;ts-rs&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;ts-rs&quot;&gt;&lt;code&gt;ts-rs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; library will allow you to output typescript types for your existing objects:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;TS&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[ts(export)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    first_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;#[ts(export)]&lt;&#x2F;code&gt; attribute will export this type when you run &lt;code&gt;cargo test&lt;&#x2F;code&gt; on your crate.&lt;&#x2F;p&gt;
&lt;p&gt;By default this will be in the &lt;code&gt;bindings&#x2F;&lt;&#x2F;code&gt; directory, with a separate typescript file per object type:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;export interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; number&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  first_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Alternatively, you can use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;ts-rs&#x2F;6.2.0&#x2F;ts_rs&#x2F;trait.TS.html&quot;&gt;&lt;code&gt;TS::decl()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; method to export it as a &lt;code&gt;String&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;decl&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;schemars&quot;&gt;schemars&lt;&#x2F;h3&gt;
&lt;p&gt;Now, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;schemars&quot;&gt;&lt;code&gt;schemars&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; does not export to typescript directly, but will export to &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;json-schema.org&#x2F;&quot;&gt;JSON Schema&lt;&#x2F;a&gt; which can be consumed &amp;amp; converted into typescript with the help of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bcherny&#x2F;json-schema-to-typescript&quot;&gt;conversion tools&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Working similar to &lt;code&gt;ts-rs&lt;&#x2F;code&gt;, you can derive &lt;code&gt;JsonSchema&lt;&#x2F;code&gt; on your objects:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;JsonSchema&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    first_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From there, you can print out the schema with the help the &lt;code&gt;schema_for&lt;&#x2F;code&gt; macro &amp;amp; &lt;code&gt;serde_json&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; schema&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; schema_for!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; serde_json&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_string_pretty&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;schema)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this schema in hand, you can use a tool like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bcherny&#x2F;json-schema-to-typescript&quot;&gt;&lt;code&gt;json-schema-to-typescript&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to output it as typescript types:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; cargo run&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; npx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; json-schema-to-typescript&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;* tslint:disable *&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;**&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; * This file was automatically generated by json-schema-to-typescript.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; * and run json-schema-to-typescript to regenerate this file.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; *&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;export interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  first_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; number&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;k&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; unknown&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;openapi-generators&quot;&gt;OpenAPI Generators&lt;&#x2F;h2&gt;
&lt;p&gt;While straight derive macros are great at defining types, you sometimes also want some type safety around the methods used. If your backend is a web server, it&#x27;s great to auto-generate the appropriate typescript code for making HTTP API calls. Luckily, if you can generate an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;spec.openapis.org&#x2F;oas&#x2F;v3.1.0&quot;&gt;OpenAPI spec&lt;&#x2F;a&gt;, you can auto-generate clients for use in the frontend, all typed and ready to go!&lt;&#x2F;p&gt;
&lt;p&gt;Depending on your backend web framework will dictate what support there are for this method. There is a push for the most common web frameworks to have OpenAPI support with varying states of maturity.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;paperclip-and-actix-web&quot;&gt;Paperclip and Actix Web&lt;&#x2F;h3&gt;
&lt;p&gt;This method is one I am most familiar with, using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;paperclip&quot;&gt;&lt;code&gt;paperclip&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; with an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;actix-web&quot;&gt;&lt;code&gt;actix-web&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; backend. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;paperclip&quot;&gt;&lt;code&gt;paperclip&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate allows you to annotate structs &amp;amp; request methods to have it auto-generate an OpenAPI spec for you:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; actix_web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;App&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HttpServer&lt;&#x2F;span&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; paperclip&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;actix&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    api_v2_operation,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Json&lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Apiv2Schema&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; OpenApiExt&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; serde&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Serialize&lt;&#x2F;span&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Apiv2Schema&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    first_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[api_v2_operation]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; echo_user&lt;&#x2F;span&gt;&lt;span&gt;(body&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Json&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Json&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(body)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[actix_web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;main]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;io&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;()&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    HttpServer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        App&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;wrap_api&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;resource&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;echo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;route&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to&lt;&#x2F;span&gt;&lt;span&gt;(echo_user)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_json_spec_v3_at&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;api&#x2F;spec&#x2F;v3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;bind&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;127.0.0.1:8080&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, you can curl to retrieve the json spec:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; http:&#x2F;&#x2F;127.0.0.1:8080&#x2F;api&#x2F;spec&#x2F;v3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  &amp;quot;openapi&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;3.0.0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  &amp;quot;info&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;title&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;version&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  &amp;quot;paths&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;    &amp;quot;&#x2F;echo&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;      &amp;quot;post&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;        &amp;quot;requestBody&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;          &amp;quot;content&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;            &amp;quot;application&#x2F;json&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;              &amp;quot;schema&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;$ref&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;#&#x2F;components&#x2F;schemas&#x2F;User&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;          &amp;quot;required&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;        &amp;quot;responses&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;          &amp;quot;200&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;            &amp;quot;description&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;OK&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;            &amp;quot;content&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;              &amp;quot;application&#x2F;json&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;                &amp;quot;schema&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;$ref&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;#&#x2F;components&#x2F;schemas&#x2F;User&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  &amp;quot;components&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;    &amp;quot;schemas&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;      &amp;quot;User&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;        &amp;quot;type&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;object&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;        &amp;quot;properties&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;          &amp;quot;first_name&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;type&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;string&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;          &amp;quot;last_name&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;type&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;string&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;          &amp;quot;user_id&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;type&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;integer&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; &amp;quot;format&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;int32&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;        &amp;quot;required&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;first_name&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;last_name&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;user_id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, if you&#x27;re like me and would like it written out to a file rather than rely on a backend to be running, you can do so with a little bit of fiddling around.&lt;&#x2F;p&gt;
&lt;p&gt;Firstly, we want to create a function to configure our services:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; config&lt;&#x2F;span&gt;&lt;span&gt;(cfg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ServiceConfig&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cfg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;resource&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;echo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;route&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to&lt;&#x2F;span&gt;&lt;span&gt;(echo_user)));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then we can adjust our main app to use this to configure actix web:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;App&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;wrap_api&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;configure&lt;&#x2F;span&gt;&lt;span&gt;(config)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_json_spec_v3_at&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;api&#x2F;spec&#x2F;v3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And we can create another function that will write out the api spec to a file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; dump_schema&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; AsRef&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Path&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;(path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; P&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    App&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;wrap_api&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;configure&lt;&#x2F;span&gt;&lt;span&gt;(config)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_raw_json_spec_v3&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;app, spec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let mut&lt;&#x2F;span&gt;&lt;span&gt; file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; File&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;path)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Could not create a file&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;write_all&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;                serde_json&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_string_pretty&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;spec)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Could not serialize spec&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;as_bytes&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Could not write schema&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The reason we keep it separate from the main &lt;code&gt;App&lt;&#x2F;code&gt; builder inside the &lt;code&gt;HttpServer&lt;&#x2F;code&gt; closure is that the builder will be called per worker &amp;amp; so as you can imagine it would write out the file multiple times on server startup.&lt;&#x2F;p&gt;
&lt;p&gt;Now we can call it manually:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;dump_schema&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;openapi.json&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;utoipa&quot;&gt;Utoipa&lt;&#x2F;h3&gt;
&lt;p&gt;More general purpose and targeting a number of different web frameworks, the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;utoipa&quot;&gt;&lt;code&gt;utoipa&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; library is similar in function to &lt;code&gt;paperclip&lt;&#x2F;code&gt;, albeit with a little bit more boilerplate to get going.&lt;&#x2F;p&gt;
&lt;p&gt;As before, a derive macro &lt;code&gt;ToSchema&lt;&#x2F;code&gt; handles the straight type magic:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ToSchema&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    first_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Decorating services is a little more cumbersome, as we need to specify the request &amp;amp; response types alongside a status.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s an actix web example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[utoipa&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;path(post, request_body &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt;, responses((status &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; 200, body &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt;)))]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[post(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;echo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; echo_user&lt;&#x2F;span&gt;&lt;span&gt;(body&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Json&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Json&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(body)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can see, that the &lt;code&gt;User&lt;&#x2F;code&gt; type has to be repeated in both the &lt;code&gt;request_body&lt;&#x2F;code&gt; and &lt;code&gt;body&lt;&#x2F;code&gt; attributes. This could potentially mean that the generated OpenAPI specification does not match reality, so extra care is needed to ensure they match.&lt;&#x2F;p&gt;
&lt;p&gt;It would be nice if the proc macro could work this out by itself rather than having to redefine them in attributes, but it would require tighter integration, something that might be added in the future.&lt;&#x2F;p&gt;
&lt;p&gt;Generating a OpenAPI JSON file is a little bit easier than in paperclip.&lt;&#x2F;p&gt;
&lt;p&gt;Firstly you combine all your components on a struct:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;OpenApi&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[openapi(components(schemas(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;)), paths(echo_user))]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ApiDoc&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then you can use some standard methods to write it out:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;    &amp;quot;openapi.json&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ApiDoc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;openapi&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_pretty_json&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Should serialize&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;typescript-from-openapi&quot;&gt;TypeScript from OpenAPI&lt;&#x2F;h3&gt;
&lt;p&gt;With an &lt;code&gt;openapi.json&lt;&#x2F;code&gt; file you can use a tool such as &lt;code&gt;openapi-generator-cli&lt;&#x2F;code&gt; to generate the requisite definitions:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npx openapi-generator-cli generate -i openapi.json -g typescript&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This won&#x27;t create purely typescript definitions, as there still needs to be a library to make requests and you may want to generate types closer to your frontend framework like using &lt;code&gt;typescript-rxjs&lt;&#x2F;code&gt; etc...&lt;&#x2F;p&gt;
&lt;p&gt;Normally this isn&#x27;t run individually, but rather it is included inside &lt;code&gt;package.json&lt;&#x2F;code&gt; of an existing frontend project.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;graphql&quot;&gt;GraphQL&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.graphql.com&#x2F;&quot;&gt;GraphQL&lt;&#x2F;a&gt; &lt;em&gt;can&lt;&#x2F;em&gt; be used to publish types, albeit indirectly and does require you to modify your backend to support it. The types that can be represented in GraphQL are also quite restricted: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;graphql&#x2F;graphql-spec&#x2F;issues&#x2F;91&quot;&gt;no recursive types&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;41515679&#x2F;can-you-make-a-graphql-type-both-an-input-and-output-type&quot;&gt;no shared types between input&#x2F;output&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;graphql&#x2F;graphql-spec&#x2F;pull&#x2F;395&quot;&gt;incomplete support for sum-types&#x2F;unions&lt;&#x2F;a&gt; to name a few issues I&#x27;ve personally hit using it. If you&#x27;re happy with the high level of opinionation GraphQL forces upon your code base, you are rewarded with some great tooling &amp;amp; infrastructure.&lt;&#x2F;p&gt;
&lt;p&gt;The main two libraries for GraphQL on the backend are &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;async-graphql&#x2F;async-graphql&quot;&gt;&lt;code&gt;async-graphql&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;graphql-rust&#x2F;juniper&quot;&gt;&lt;code&gt;juniper&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;On the frontend, there is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.the-guild.dev&#x2F;graphql&#x2F;codegen&#x2F;docs&#x2F;getting-started&quot;&gt;similar tooling&lt;&#x2F;a&gt; to OpenAPI for generating types &amp;amp; requests. You will, however, need to also write out some specific GraphQL queries, to utilise them.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;async-graphql&quot;&gt;async-graphql&lt;&#x2F;h3&gt;
&lt;p&gt;As with the Derive Macro &amp;amp; OpenAPI generators you start by decorating your structs. We can use the &lt;code&gt;SimpleObject&lt;&#x2F;code&gt; and &lt;code&gt;InputObject&lt;&#x2F;code&gt; derive macros (in GraphQL you need separate types for input...):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; SimpleObject&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    first_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; InputObject&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; UserInput&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    first_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we want to define a &lt;code&gt;Query&lt;&#x2F;code&gt; object which will dictate the methods available via GraphQL:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Query&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Object&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Query&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; echo_user&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; UserInput&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;user_id,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            first_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;first_name,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;last_name,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then we can set up a handler for graphql queries (leaving subscriptions and mutations empty for now):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; graphql_handler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    schema&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Data&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Schema&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Query&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; EmptyMutation&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; EmptySubscription&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    request&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; GraphQLRequest&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; GraphQLResponse&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    schema&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;execute&lt;&#x2F;span&gt;&lt;span&gt;(request&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into_inner&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;graphql&#x2F;graphiql&quot;&gt;GraphiQL&lt;&#x2F;a&gt; endpoint to use a browser to craft graphql queries:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; graphql_playground&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HttpResponse&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    HttpResponse&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;content_type&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;text&#x2F;html; charset=utf-8&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;body&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;GraphiQLSource&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;endpoint&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;graphql&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;finish&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We wrap the schema in &lt;code&gt;web::Data&lt;&#x2F;code&gt; and add it as &lt;code&gt;app_data&lt;&#x2F;code&gt;, then provide our two new services:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[actix_web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;main]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;io&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;()&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; schema&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Schema&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Query&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; EmptyMutation&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; EmptySubscription&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;finish&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; schema_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(schema);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    HttpServer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        App&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;app_data&lt;&#x2F;span&gt;&lt;span&gt;(schema_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;resource&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;graphql&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;route&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to&lt;&#x2F;span&gt;&lt;span&gt;(graphql_handler)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;resource&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;playground&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;route&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to&lt;&#x2F;span&gt;&lt;span&gt;(graphql_playground)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;bind&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;127.0.0.1:8080&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can also write out the schema via the &lt;code&gt;sdl()&lt;&#x2F;code&gt; method on &lt;code&gt;Schema&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;example.graphql&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, schema&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;sdl&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;graphiql-playground&quot;&gt;GraphiQL Playground&lt;&#x2F;h4&gt;
&lt;p&gt;Navigating to &lt;code&gt;http:&#x2F;&#x2F;localhost:8080&#x2F;playground&lt;&#x2F;code&gt; in a browser you will get the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;graphql&#x2F;graphiql&quot;&gt;GraphiQL playground&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;photos&#x2F;graphiql.png&quot;&gt;&lt;img src=&quot;&#x2F;photos&#x2F;graphiql.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;juniper&quot;&gt;juniper&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;graphql-rust&#x2F;juniper&quot;&gt;&lt;code&gt;juniper&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate in this context is very similar to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;async-graphql&#x2F;async-graphql&quot;&gt;&lt;code&gt;async-graphql&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;juniper&lt;&#x2F;code&gt; as a crate has been around a fair bit longer &lt;code&gt;async-graphql&lt;&#x2F;code&gt; &amp;amp; did not start off as an async library. Both are very capable libraries, but I have found &lt;code&gt;async-graphql&lt;&#x2F;code&gt; to be better documented, and more &quot;modern&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;In terms of coding for our example, &lt;code&gt;juniper&lt;&#x2F;code&gt; is very similar to &lt;code&gt;async-graphql&lt;&#x2F;code&gt;, with derive macros on the types you want to define:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; GraphQLObject&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    first_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; GraphQLInputObject&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; UserInput&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    first_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The query object is also very much a slot in:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Query&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[juniper&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;graphql_object]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Query&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; echo_user&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; UserInput&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            user_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;user_id,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            first_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;first_name,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;last_name,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Creating the schema is also similar:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; schema&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Schema&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Query&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; EmptyMutation&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; EmptySubscription&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The handler method deviates slightly, but is mostly the same as above:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; graphql&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    req&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; actix_web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;HttpRequest&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    payload&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; actix_web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Payload&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    schema&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Data&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Schema&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;HttpResponse&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    graphql_handler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;schema,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;(), req, payload)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;juniper_actix&lt;&#x2F;code&gt; integration also provides a &lt;code&gt;graphiql_handler&lt;&#x2F;code&gt; which you can use to mount the playground (&lt;code&gt;v1&lt;&#x2F;code&gt; of &lt;code&gt;graphiql&lt;&#x2F;code&gt; instead of &lt;code&gt;v2&lt;&#x2F;code&gt; at this time of writing).&lt;&#x2F;p&gt;
&lt;p&gt;Putting this together, we get almost an identical layout:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[actix_web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;main]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;io&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;()&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; schema&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Schema&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Query&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; EmptyMutation&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; EmptySubscription&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; schema_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(schema);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    HttpServer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        App&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;app_data&lt;&#x2F;span&gt;&lt;span&gt;(schema_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;resource&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;graphql&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;route&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to&lt;&#x2F;span&gt;&lt;span&gt;(graphql)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;                web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;resource&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;playground&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;route&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;||&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; graphiql_handler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;graphql&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;))),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;bind&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;127.0.0.1:8080&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As with &lt;code&gt;async-graphql&lt;&#x2F;code&gt; the graphql schema can be written out to disk using the &lt;code&gt;as_schema_language()&lt;&#x2F;code&gt; method:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;example.graphql&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, schema&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;as_schema_language&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;graphql-to-typescript&quot;&gt;GraphQL to TypeScript&lt;&#x2F;h3&gt;
&lt;p&gt;Now, the next question is: we have our graphql schema, how do we get to typescript definitions? The easiest way I&#x27;ve found, from a maintenance perspective, is a little bit involved for this particular blog. The gist is that using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.the-guild.dev&#x2F;graphql&#x2F;codegen&#x2F;docs&#x2F;getting-started&quot;&gt;&lt;code&gt;GraphQL Code Generator&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; you can define your queries and then have frontend methods&#x2F;types generated from them.&lt;&#x2F;p&gt;
&lt;p&gt;This does require a bit of scaffolding in your frontend project to get working, but is rather painless when it is set up, besides having to write queries&#x2F;mutations for all of your types.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;&#x2F;h2&gt;
&lt;p&gt;As you can see there are a variety of ways of publishing rust types for use within &lt;code&gt;TypeScript&lt;&#x2F;code&gt;. Having this process is as automated as possible is a great way to icnrease cohesion between front &amp;amp; backend. Whether these methods are right for you depends entirely on your use-case &amp;amp; what tradeoffs you&#x27;re willing to make:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Types Only&lt;&#x2F;strong&gt;: You can use direct translation tools such as &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;ts-rs&quot;&gt;&lt;code&gt;ts-rs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;schemars&quot;&gt;&lt;code&gt;schemars&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;OpenAPI&lt;&#x2F;strong&gt;: You can go the OpenAPI route using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;paperclip&quot;&gt;&lt;code&gt;paperclip&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;utoipa&quot;&gt;&lt;code&gt;utoipa&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;GraphQL&lt;&#x2F;strong&gt;: You can use GraphQL with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;async-graphql&#x2F;async-graphql&quot;&gt;&lt;code&gt;async-graphql&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;graphql-rust&#x2F;juniper&quot;&gt;&lt;code&gt;juniper&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When building &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;divedb.net&#x2F;&quot;&gt;DiveDB&lt;&#x2F;a&gt;, I opted to use GraphQL due to its great frontend tooling &amp;amp; standardised introspection. In future blogs I hope to dive into some of the details of this decision.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Implementing a Job queue with SQLx and Postgres</title>
          <pubDate>Fri, 26 Jun 2020 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/implementing-a-jobq-sqlx/</link>
          <guid>https://cetra3.github.io/blog/implementing-a-jobq-sqlx/</guid>
          <description xml:base="https://cetra3.github.io/blog/implementing-a-jobq-sqlx/">&lt;p&gt;&lt;strong&gt;SQLx&lt;&#x2F;strong&gt; is a new &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;launchbadge&#x2F;sqlx&quot;&gt;async SQL Toolkit&lt;&#x2F;a&gt; for rust that is closer to standard SQL than a more opinionated ORM like &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;diesel.rs&#x2F;&quot;&gt;Diesel&lt;&#x2F;a&gt;. I wanted to give it a bit of a test run and see how easy it would be to convert usage from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sfackler&#x2F;rust-postgres&quot;&gt;tokio-postgres&lt;&#x2F;a&gt;.  So as the next saga in the jobq series (&lt;a href=&quot;..&#x2F;implementing-a-jobq&#x2F;&quot;&gt;part 1&lt;&#x2F;a&gt;, &lt;a href=&quot;..&#x2F;implementing-a-jobq-with-tokio&#x2F;&quot;&gt;part 2&lt;&#x2F;a&gt;), we will be converting &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&quot;&gt;jobq&lt;&#x2F;a&gt; crate to use &lt;code&gt;sqlx&lt;&#x2F;code&gt;.  You can find the &lt;em&gt;SQLx&lt;&#x2F;em&gt; branch here: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;tree&#x2F;sqlx&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;tree&#x2F;sqlx&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As a little spoiler: I found it quite easy to adjust and a pleasure to use but found the documentation a little lacking.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;object-relational-mappers-orms&quot;&gt;Object Relational Mappers (ORMs)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;ORMs&lt;&#x2F;strong&gt; definitely serve a purpose. &lt;em&gt;ORMs&lt;&#x2F;em&gt; provide an opinionated way to manage the database schema and craft queries in an easy way.  Normally you construct queries using builders, or other language constructs, and get given the results back straight in your language types (structs in the case of rust).  Migration is a lot easier as most offer a managed way to run migrations for you.  You don&#x27;t need to know SQL either, and can simply run functions in your language to build up queries to the database.&lt;&#x2F;p&gt;
&lt;p&gt;Writing raw SQL in some ORMs is a second class citizen, which is where I have a problem.  I personally find the cognitive load of having to wrangle the builder pattern to pull out SQL is not worth it.  I am quite comfortable writing SQL and have done for many years, and so I have steered away from using highly opinionated ORMs in the past.  In the world of Java I much prefer &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mybatis.org&#x2F;mybatis-3&#x2F;&quot;&gt;MyBatis&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;jdbi.org&#x2F;&quot;&gt;Jdbi&lt;&#x2F;a&gt; over &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hibernate.org&#x2F;&quot;&gt;Hibernate&lt;&#x2F;a&gt;.  In Rust, I am using standard &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sfackler&#x2F;rust-postgres&quot;&gt;tokio-postgres&lt;&#x2F;a&gt; over &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;diesel.rs&#x2F;&quot;&gt;diesel&lt;&#x2F;a&gt; for the same reasons (that: and diesel async support is not there yet and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;diesel-rs&#x2F;diesel&#x2F;issues&#x2F;399&quot;&gt;doesn&#x27;t look like it will be&lt;&#x2F;a&gt; anytime soon...).&lt;&#x2F;p&gt;
&lt;p&gt;Now if you are not familiar with SQL this is definitely a different story, and may find you have a different opinion on how productive you are.  That&#x27;s fine too, as this is one reason ORMs exist: to make it easier to code.  I would still recommend spending time grokking SQL, as it is quite a great skill to have in your toolbox.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;diesel-orm&quot;&gt;Diesel ORM&lt;&#x2F;h3&gt;
&lt;p&gt;Picking on &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;diesel.rs&#x2F;&quot;&gt;diesel&lt;&#x2F;a&gt; for a second: here is their &lt;em&gt;Complex Queries&lt;&#x2F;em&gt; example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; versions&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Version&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;belonging_to&lt;&#x2F;span&gt;&lt;span&gt;(krate)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;select&lt;&#x2F;span&gt;&lt;span&gt;(id)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;order&lt;&#x2F;span&gt;&lt;span&gt;(num&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;desc&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;limit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; downloads&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; version_downloads&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(date&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;gt&lt;&#x2F;span&gt;&lt;span&gt;(now&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 90&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;days&lt;&#x2F;span&gt;&lt;span&gt;()))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(version_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;eq&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;any&lt;&#x2F;span&gt;&lt;span&gt;(versions)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;order&lt;&#x2F;span&gt;&lt;span&gt;(date)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;load&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Download&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;conn)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here is the same query in SQL:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; version_downloads.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  WHERE date&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;NOW&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;#39;90 days&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    AND&lt;&#x2F;span&gt;&lt;span&gt; version_id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; ANY(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;      SELECT&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; versions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        WHERE&lt;&#x2F;span&gt;&lt;span&gt; crate_id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        ORDER BY&lt;&#x2F;span&gt;&lt;span&gt; num &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;DESC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        LIMIT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;  ORDER BY date&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which one do you find more readable? I find the SQL easier to read.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sqlx-orm&quot;&gt;SQLx ORM&lt;&#x2F;h3&gt;
&lt;p&gt;I still consider &lt;code&gt;SQLx&lt;&#x2F;code&gt; an ORM, but with SQL as a first-class citizen.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s how you&#x27;d do the same with &lt;strong&gt;SQLx&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; query&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;SELECT version_downloads.*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;  WHERE date &amp;gt; (NOW() - &amp;#39;90 days&amp;#39;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;    AND version_id = ANY(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;      SELECT id FROM versions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;        WHERE crate_id = $1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;        ORDER BY num DESC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;        LIMIT 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;  ORDER BY date&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;sqlx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;query_as&lt;&#x2F;span&gt;&lt;span&gt;(query)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;bind&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;num)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;fetch_all&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;pool);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If your &lt;code&gt;Version&lt;&#x2F;code&gt; struct derived &lt;code&gt;sqlx::FromRow&lt;&#x2F;code&gt;, then this would all work nicely.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;converting-to-sqlx&quot;&gt;Converting to SQLx&lt;&#x2F;h2&gt;
&lt;p&gt;Converting to SQLx was a mostly painless experience, and only &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;compare&#x2F;051b2c2a89fbed0a67bc989c4d3bf29a745ab3ce...sqlx&quot;&gt;very minimal changes&lt;&#x2F;a&gt; were needed for the jobq code base.  In the end, only the structs &amp;amp; db files were needed to be adjusted, but I could reuse all of the query strings and sql building logic.&lt;&#x2F;p&gt;
&lt;p&gt;As I am not starting with SQLx, some of the touted features I didn&#x27;t use (like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;launchbadge&#x2F;sqlx#compile-time-verification&quot;&gt;compile time verification&lt;&#x2F;a&gt;).  There were also a few gotchas I ran into, but did not find it hard to work through them after a bit of reading.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;migrations-and-raw-sql&quot;&gt;Migrations and Raw SQL&lt;&#x2F;h3&gt;
&lt;p&gt;I haven&#x27;t implemented migrations properly in jobq: it&#x27;s just a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;sqlx&#x2F;src&#x2F;setup.sql&quot;&gt;simple sql script&lt;&#x2F;a&gt; that is run at startup.  SQLx does have &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;launchbadge&#x2F;sqlx&#x2F;tree&#x2F;master&#x2F;sqlx-cli&quot;&gt;utilities for this&lt;&#x2F;a&gt;, and is also quite strong on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;launchbadge&#x2F;sqlx#compile-time-verification&quot;&gt;compile time verification&lt;&#x2F;a&gt; to make this more type safe.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;However:&lt;&#x2F;strong&gt; I just want to run the script at startup.  It&#x27;s simple &amp;amp; I can do it from standard postgres cli, so I should be able to it simply from rust as well.  The &lt;code&gt;sqlx::query&lt;&#x2F;code&gt; method will convert the SQL to a prepared statement, which does not play nice with such a query:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;sqlx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;query&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;include_str!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;setup.sql&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;execute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;pool)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here&#x27;s the error you may get:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cannot insert multiple commands into a prepared statement&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead, you can use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;sqlx&#x2F;0.3.5&#x2F;sqlx&#x2F;trait.Executor.html&quot;&gt;&lt;code&gt;Executor&lt;&#x2F;code&gt; trait&lt;&#x2F;a&gt; which is implemented for &lt;code&gt;&amp;amp;PgPool&lt;&#x2F;code&gt;.  This does make it a little awkward to write having to have the extra brackets:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;pool)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;execute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;include_str!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;setup.sql&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;mapping-a-postgresql-query-to-rust-structs&quot;&gt;Mapping a postgresql query to rust structs&lt;&#x2F;h3&gt;
&lt;p&gt;sqlx has a &lt;code&gt;query_as&lt;&#x2F;code&gt; method which allows you to convert returned result rows into rust structs, a bit like serde is used to serialize&#x2F;deserialize data.&lt;&#x2F;p&gt;
&lt;p&gt;This works by deriving &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;sqlx&#x2F;0.3.5&#x2F;sqlx&#x2F;derive.FromRow.html&quot;&gt;&lt;code&gt;sqlx::FromRow&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; on your structs:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;, sqlx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FromRow&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Job&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; username&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; uuid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Uuid&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; params&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Value&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; priority&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Priority&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Status&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As I am using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;f4441203fd4b4d2d73d5f7a91b228723c7330aa6&#x2F;src&#x2F;setup.sql#L2-L9&quot;&gt;custom enums&lt;&#x2F;a&gt;, I also need to derive &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;sqlx&#x2F;0.3.5&#x2F;sqlx&#x2F;derive.Type.html&quot;&gt;&lt;code&gt;sqlx::Type&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; on them:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;, sqlx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Status&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Queued&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Processing&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Completed&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Failed&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(&lt;em&gt;Side note: custom enums may not be a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;softwareengineering.stackexchange.com&#x2F;questions&#x2F;305148&#x2F;why-would-you-store-an-enum-in-db&quot;&gt;hot idea for maintainability&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;)&lt;&#x2F;p&gt;
&lt;p&gt;With that I can do away with the old &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;051b2c2a89fbed0a67bc989c4d3bf29a745ab3ce&#x2F;src&#x2F;db.rs#L53-L79&quot;&gt;&lt;code&gt;get_jobs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; method, as this is handled for me now by SQLx.&lt;&#x2F;p&gt;
&lt;p&gt;I can then use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;sqlx&#x2F;0.3.5&#x2F;sqlx&#x2F;postgres&#x2F;trait.PgQueryAs.html#tymethod.fetch_all&quot;&gt;&lt;code&gt;fetch_all&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; method to return is as a &lt;code&gt;Vec&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_processing_jobs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; query&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;select id, name, username, uuid, params, priority, status from jobq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                 where status = &amp;#39;Processing&amp;#39; order by priority asc, time asc&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;sqlx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;query_as&lt;&#x2F;span&gt;&lt;span&gt;(query)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;fetch_all&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;pool)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Worthy of note: the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;sqlx&#x2F;0.3.5&#x2F;sqlx&#x2F;postgres&#x2F;trait.PgQueryAs.html#tymethod.fetch&quot;&gt;&lt;code&gt;fetch&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; method returns a futures &lt;code&gt;Stream&lt;&#x2F;code&gt; to iterate through, making a much tighter integration with async&lt;&#x2F;p&gt;
&lt;h3 id=&quot;binding-parameters&quot;&gt;Binding Parameters&lt;&#x2F;h3&gt;
&lt;p&gt;I didn&#x27;t need to change SQL statements at all, but did need to adjust some of the binding parameters using the &lt;code&gt;bind&lt;&#x2F;code&gt; builder pattern:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; complete_job&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; query&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;update jobq set status = &amp;#39;Completed&amp;#39;, duration = extract(epoch from now() - &lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;) where id = $1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    sqlx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;query&lt;&#x2F;span&gt;&lt;span&gt;(query)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;bind&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;id)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;execute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;pool)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is different to &lt;code&gt;tokio-postgres&lt;&#x2F;code&gt; accepting an array of parameters.  I have ran into issues before when trying to pass dynamic arguments and trying to wrangle life times.  Here is how I have worked around this in the past (not exactly pretty):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;pool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;query&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    &amp;amp;*&lt;&#x2F;span&gt;&lt;span&gt;query,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    params&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;| &amp;amp;**&lt;&#x2F;span&gt;&lt;span&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ToSql&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Sync&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;_&amp;gt;&amp;gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;as_slice&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;&#x2F;h2&gt;
&lt;p&gt;As you can see from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;compare&#x2F;051b2c2a89fbed0a67bc989c4d3bf29a745ab3ce...sqlx&quot;&gt;diff of the commits&lt;&#x2F;a&gt;, the conversion to use SQLx was an easy excercise.  I have found SQLx quite a bit more lightweight and more to my liking than some of the heavier ORMs I&#x27;ve dealt with in the past.  Being async first means that this will be a great fit for the ecosystem: I can see it becoming the defacto async story for databases in the future.&lt;&#x2F;p&gt;
&lt;p&gt;One area which may need some improvement is the documentation &amp;amp; examples.  As it is a comparitively young library with the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;launchbadge&#x2F;sqlx&#x2F;commit&#x2F;d29b24abf0f491d912333f34d7b5187e4c30bb08&quot;&gt;first commit a year ago&lt;&#x2F;a&gt;, I assume that this will only get better with time.  The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;launchbadge&#x2F;sqlx&quot;&gt;README&lt;&#x2F;a&gt;  and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;sqlx&quot;&gt;api docs&lt;&#x2F;a&gt; were enough for me to get into trouble.&lt;&#x2F;p&gt;
&lt;p&gt;If you are looking to talk to a database with async rust, make sure you consider SQLx!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Drawing SVG Graphs with Rust</title>
          <pubDate>Fri, 22 May 2020 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/drawing-svg-graphs-rust/</link>
          <guid>https://cetra3.github.io/blog/drawing-svg-graphs-rust/</guid>
          <description xml:base="https://cetra3.github.io/blog/drawing-svg-graphs-rust/">&lt;p&gt;I have just released the first version of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;lorikeet-dash&quot;&gt;lorikeet-dash&lt;&#x2F;a&gt; and part of that exercise was to find out a way to draw SVG graphs using rust.&lt;&#x2F;p&gt;
&lt;p&gt;I thought my findings &amp;amp; approach may be useful for others looking to do the same thing and so I have documented the design evolution in this blog.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s what the end result looks like in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;lorikeet-dash&quot;&gt;&lt;code&gt;lorikeet-dash&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; project:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;cetra3&#x2F;lorikeet-dash&#x2F;master&#x2F;dash.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;defining-the-graph&quot;&gt;Defining the Graph&lt;&#x2F;h2&gt;
&lt;p&gt;First we want to define what a graph is.  A minimal example of what a graph would have is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A List of Points&lt;&#x2F;li&gt;
&lt;li&gt;A Name&#x2F;Description&lt;&#x2F;li&gt;
&lt;li&gt;A Colour for the line&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So, in a rust struct, this would look like the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Graph&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; points&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Point&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; colour&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Copy&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Point&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s add some initial helper methods, one to create a new graph, and another to add points to it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Graph&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;(name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;, colour&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Graph&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            name,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            points&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            colour,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; add_point&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;, x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt;, y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;points&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Point&lt;&#x2F;span&gt;&lt;span&gt; { x, y });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;svg-template&quot;&gt;SVG Template&lt;&#x2F;h2&gt;
&lt;p&gt;An SVG image is an XML file, which means that we can use standard templating engines to generate SVG with some parameters.  I am going to use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;tera&quot;&gt;&lt;code&gt;tera&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; in this example, as &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;lorikeet&quot;&gt;&lt;code&gt;lorikeet&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; already uses it.  You could, however, use any template engine.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start with a simple SVG template, of which just simply draws the graph name:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;xml&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; version&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;1.0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; standalone&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;no&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;?&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;svg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  width&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;100%&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  height&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;100%&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  viewBox&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;0 0 {{height + padding * 2}} {{width + padding * 2}}&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  preserveAspectRatio&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;xMidYMid meet&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  xmlns&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;  &amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;text&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    x&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{{width&#x2F;2 + padding}}&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    y&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{{padding &#x2F; 2}}&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    font-family&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    dominant-baseline&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;middle&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    text-anchor&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;middle&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    font-size&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;18&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    fill&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;#74838f&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    font-weight&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;700&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;    &amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {{name}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;text&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;svg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s visit some decisions I have made here:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We are including a &lt;code&gt;width&lt;&#x2F;code&gt; &amp;amp; &lt;code&gt;height&lt;&#x2F;code&gt; for the viewbox.  Having the SVG display at its natural resolution increases the clarity of the line, so we&#x27;ll allow them to be adjusted when generating an SVG.&lt;&#x2F;li&gt;
&lt;li&gt;There is a &lt;code&gt;padding&lt;&#x2F;code&gt; value to include around the graph so that axis labels and the name of the graph will fit on the SVG.  To make things simple this can be hardset to a value such as &lt;code&gt;50&lt;&#x2F;code&gt;.  We&#x27;ll subtract that x 2 from the provided width&#x2F;height.&lt;&#x2F;li&gt;
&lt;li&gt;We&#x27;re using a big &lt;code&gt;font-family&lt;&#x2F;code&gt; list which should display roughly similar fonts depending on your OS.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;With our tera template svg ready, we can use the &lt;code&gt;include_str&lt;&#x2F;code&gt; macro to have this compiled in:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Tera&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;one_off&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;include_str!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;graph.svg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;context,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Could not draw graph&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;drawing-the-name&quot;&gt;Drawing the Name&lt;&#x2F;h3&gt;
&lt;p&gt;We&#x27;ll add a &lt;code&gt;draw_svg(&amp;amp;self, width: usize, height: usize)&lt;&#x2F;code&gt; method to the &lt;code&gt;Graph&lt;&#x2F;code&gt; struct which should start by drawing the name as per the above template.  The arguments are simply the width &amp;amp; height to draw.  To ensure that the viewbox of the svg comes out the right size, we&#x27;ll subtract the padding from both x 2.&lt;&#x2F;p&gt;
&lt;p&gt;To put it another way, the &lt;code&gt;width&lt;&#x2F;code&gt; and &lt;code&gt;height&lt;&#x2F;code&gt; become the width and height of the graph itself rather than the SVG.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; draw_svg&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, width&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;, height&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span&gt; context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;hardset the padding around the graph&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; padding&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 50&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;ensure the viewbox is as per input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; width&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; width&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; padding&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; height&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; height&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; padding&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;width&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;width);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;height&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;height);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;padding&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;padding);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Tera&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;one_off&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;include_str!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;graph.svg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;context,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Could not draw graph&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;Context&lt;&#x2F;code&gt; here is what tera uses to provide variables to a template.  Anything that implements &lt;code&gt;serde::Serialize&lt;&#x2F;code&gt; can be put into the context.  At this moment we&#x27;re providing a few strings and width&#x2F;height parameters.&lt;&#x2F;p&gt;
&lt;p&gt;This can be run to spit out an SVG:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Example&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;#8ff0a4&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;draw_svg&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;800&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 400&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Running this, should output the following SVG:&lt;&#x2F;p&gt;
&lt;div&gt;
&lt;svg
  width=&quot;100%&quot;
  height=&quot;100%&quot;
  viewBox=&quot;0 0 800 50&quot;
  preserveAspectRatio=&quot;xMidYMid meet&quot;
  xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;
  &gt;
  &lt;text
    x=&quot;400&quot;
    y=&quot;25&quot;
    font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot;
    dominant-baseline=&quot;middle&quot;
    text-anchor=&quot;middle&quot;
    font-size=&quot;18&quot;
    fill=&quot;#74838f&quot;
    font-weight=&quot;700&quot;
    &gt;
    Example
  &lt;&#x2F;text&gt;
&lt;&#x2F;svg&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;drawing-the-points&quot;&gt;Drawing the Points&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s fill up the graph with some dummy points so we have something to draw (note: we are assuming you&#x27;ll add the points in order here):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_point&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_point&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_point&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_point&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_point&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;scaling-the-axis&quot;&gt;Scaling the Axis&lt;&#x2F;h3&gt;
&lt;p&gt;To keep things simple, we&#x27;ll start from the origin &amp;amp; scale both the x and y axis by the max value of either.  We&#x27;ll pull out both of those values and use these to scale the points within the svg:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; max_x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span&gt;points&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;point&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; point&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;fold&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;. &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;max);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; max_y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span&gt;points&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;point&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; point&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;fold&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;. &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;max);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;drawing-a-line&quot;&gt;Drawing a Line&lt;&#x2F;h3&gt;
&lt;p&gt;To draw a line between points in an SVG, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;SVG&#x2F;Tutorial&#x2F;Paths&quot;&gt;you can use the &lt;code&gt;path&lt;&#x2F;code&gt; element with draw commands&lt;&#x2F;a&gt;.  A simple line would look like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; d&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;M10 10 L15 15&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That is: move to point 10,10 and then draw a line to point 15,15.  These points are in the SVG space, so we will need to translate our graph points onto this space, keeping in mind padding, width and height and scaling.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;translating-the-points&quot;&gt;Translating the points&lt;&#x2F;h3&gt;
&lt;p&gt;We want to draw a line between each of the points in the SVG but scaled to fit within the viewport.&lt;&#x2F;p&gt;
&lt;p&gt;To add another complication, the chart origin is in the bottom left, whereas the SVG origin is the top left.&lt;&#x2F;p&gt;
&lt;p&gt;For both the x and y axis, we want to scale down based upon the max value (&lt;code&gt;width&lt;&#x2F;code&gt; and &lt;code&gt;height&lt;&#x2F;code&gt; here are the chart width):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;x = x &#x2F; max_x * width&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;y = y &#x2F; max_y * height&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the x axis, we need to shift them along the right based upon padding, otherwise they will sit on the left side of the svg:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;x = x &#x2F; max_x * width + padding&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the y axis, we want to flip this based upon the height, to translate the origin, then add &lt;code&gt;height + padding&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;y = y &#x2F; max_y * (height * -1.0) + height + padding&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;iterating-through&quot;&gt;Iterating through&lt;&#x2F;h3&gt;
&lt;p&gt;We have our points commands, now let&#x27;s iterate through and convert them to a bunch of draw commands.  First we will use &lt;code&gt;M&lt;&#x2F;code&gt; to move to start drawing, then we will use &lt;code&gt;L&lt;&#x2F;code&gt; to draw a line between each.&lt;&#x2F;p&gt;
&lt;p&gt;We can use &lt;code&gt;enumerate()&lt;&#x2F;code&gt; on the iterator to get whether this is the first or subsequent value, and then join it together as a big string:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span&gt;points&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Point&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; max_x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; width&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; padding&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; max_y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; (height&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; * -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; (padding&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; height)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;(i, point)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;M {} {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, point&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x, point&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;L {} {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, point&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x, point&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot; &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will output a path string like so:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;M 190 383.33333333333337 L 330 250 L 470 283.3333333333333 L 610 50 L 750 250&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;adding-to-the-svg&quot;&gt;Adding to the SVG&lt;&#x2F;h3&gt;
&lt;p&gt;We can add the path &amp;amp; colour to the Context:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;path&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;path);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;colour&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;colour);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then add the following to have it drawn in the SVG:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; stroke&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{{colour}}&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; stroke-linejoin&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;round&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; d&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{{path}}&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; stroke-width&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;2.0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; fill&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;none&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If all goes well, the graph should start looking more like a graph:&lt;&#x2F;p&gt;
&lt;div&gt;
&lt;svg
  width=&quot;100%&quot;
  height=&quot;100%&quot;
  viewBox=&quot;0 0 800 500&quot;
  preserveAspectRatio=&quot;xMidYMid meet&quot;
  xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;
  &gt;
  &lt;text
    x=&quot;400&quot;
    y=&quot;25&quot;
    font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot;
    dominant-baseline=&quot;middle&quot;
    text-anchor=&quot;middle&quot;
    font-size=&quot;18&quot;
    fill=&quot;#74838f&quot;
    font-weight=&quot;700&quot;
    &gt;
    Example
  &lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#8ff0a4&quot; stroke-linejoin=&quot;round&quot; d=&quot;M 190 383.33333333333337 L 330 250 L 470 283.3333333333333 L 610 50 L 750 250&quot; stroke-width=&quot;2.0&quot; fill=&quot;none&quot; &#x2F;&gt;
&lt;&#x2F;svg&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;adding-in-the-axis&quot;&gt;Adding in the Axis&lt;&#x2F;h2&gt;
&lt;p&gt;We need to add in some axis scale so we know what the graph values represent.  I&#x27;m gonna cheat here &amp;amp; break up both the x and y axis the same amount of times each.  We&#x27;ll break up the axis 5 times each, but have this set in the context to be changes later:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;lines&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Tera allows us to do a loop within the template, so we&#x27;ll use that to add some lines and nudges.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% for i in range(end=(lines + 1)) %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... draw some lines here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% endfor %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s set some variables within the template, based upon the current line we&#x27;re drawing.  These are the offsets for both the axis:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% set offset_x = padding + loop.index0&#x2F;lines * width%}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% set offset_y = padding + loop.index0&#x2F;lines * height%}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;horizontal-lines&quot;&gt;Horizontal Lines&lt;&#x2F;h3&gt;
&lt;p&gt;We will draw 5 horizontal dashed lines, to give scale to the y value.  This will start on the left side of the graph and continue to the end of the graph.  We&#x27;ll draw a solid horizontal line when &lt;code&gt;y = 0&lt;&#x2F;code&gt; (keep in mind the axis is flipped in SVG), which means we skip drawing this for the last line:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% if loop.last == false %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; stroke&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;#74838f&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; stroke-dasharray&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;10 6&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; stroke-width&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;0.5&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  d&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;M {{padding}} {{offset_y}} L {{width + padding}} {{offset_y}}&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% else %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; stroke&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;#74838f&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; stroke-width&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;2&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; fill&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;none&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  d&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;M {{padding}} {{offset_y}} L {{width + padding}} {{offset_y}}&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% endif %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now our graph will be a bit easier to read:&lt;&#x2F;p&gt;
&lt;div&gt;
&lt;?xml version=&quot;1.0&quot; standalone=&quot;no&quot;?&gt;
&lt;svg
  width=&quot;100%&quot;
  height=&quot;100%&quot;
  viewBox=&quot;0 0 800 500&quot;
  preserveAspectRatio=&quot;xMidYMid meet&quot;
  xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;
  &gt;
  &lt;text 
    x=&quot;400&quot;
    y=&quot;25&quot;
    font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot;
    dominant-baseline=&quot;middle&quot;
    text-anchor=&quot;middle&quot;
    font-size=&quot;18&quot;
    fill=&quot;#74838f&quot;
    font-weight=&quot;700&quot;
    &gt;
    Example
  &lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 50 L 750 50&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 130 L 750 130&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 210 L 750 210&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 290 L 750 290&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 370 L 750 370&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2&quot; fill=&quot;none&quot;  d=&quot;M 50 450 L 750 450&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#8ff0a4&quot; stroke-linejoin=&quot;round&quot; d=&quot;M 190 383.33333333333337 L 330 250 L 470 283.3333333333333 L 610 50 L 750 250&quot; stroke-width=&quot;2.0&quot; fill=&quot;none&quot; &#x2F;&gt;
&lt;&#x2F;svg&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;vertical-lines&quot;&gt;Vertical Lines&lt;&#x2F;h3&gt;
&lt;p&gt;We will just put little 10px nudges in the axis rather than dotted vertical lines.&lt;&#x2F;p&gt;
&lt;p&gt;In the existing for loop, we can add the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; stroke&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;#74838f&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; stroke-width&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;2.0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; d&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;M {{offset_x}} {{height + padding}} L {{offset_x}} {{height + padding + 10}}&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will create nudges where we&#x27;ll put our axis labels:&lt;&#x2F;p&gt;
&lt;div&gt;
&lt;?xml version=&quot;1.0&quot; standalone=&quot;no&quot;?&gt;
&lt;svg
  width=&quot;100%&quot;
  height=&quot;100%&quot;
  viewBox=&quot;0 0 800 500&quot;
  preserveAspectRatio=&quot;xMidYMid meet&quot;
  xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;
  &gt;
  &lt;text 
    x=&quot;400&quot;
    y=&quot;25&quot;
    font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot;
    dominant-baseline=&quot;middle&quot;
    text-anchor=&quot;middle&quot;
    font-size=&quot;18&quot;
    fill=&quot;#74838f&quot;
    font-weight=&quot;700&quot;
    &gt;
    Example
  &lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 50 L 750 50&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot;  stroke-width=&quot;2.0&quot;  d=&quot;M 50 450 L 50 460&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 130 L 750 130&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot;  stroke-width=&quot;2.0&quot;  d=&quot;M 190 450 L 190 460&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 210 L 750 210&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot;  stroke-width=&quot;2.0&quot;  d=&quot;M 330 450 L 330 460&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 290 L 750 290&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot;  stroke-width=&quot;2.0&quot;  d=&quot;M 470 450 L 470 460&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 370 L 750 370&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot;  stroke-width=&quot;2.0&quot;  d=&quot;M 610 450 L 610 460&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2&quot; fill=&quot;none&quot;  d=&quot;M 50 450 L 750 450&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot;  stroke-width=&quot;2.0&quot;  d=&quot;M 750 450 L 750 460&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#8ff0a4&quot; stroke-linejoin=&quot;round&quot; d=&quot;M 190 383.33333333333337 L 330 250 L 470 283.3333333333333 L 610 50 L 750 250&quot; stroke-width=&quot;2.0&quot; fill=&quot;none&quot; &#x2F;&gt;
&lt;&#x2F;svg&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;axis-labels&quot;&gt;Axis Labels&lt;&#x2F;h3&gt;
&lt;p&gt;We can add in axis labels in the same for loop.&lt;&#x2F;p&gt;
&lt;p&gt;For the y-axis, the loop starts at the top of the graph and goes down, so we will use the following formula to present the 1&#x2F;5th value:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(lines - loop.index0)&#x2F;lines * max_y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can use the tera &lt;code&gt;round&lt;&#x2F;code&gt; helper to round the value up, so there is not a lot of decimal places:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{{((lines - loop.index0)&#x2F;lines * max_y) | round}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Putting this together:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;text&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  x&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{{padding - 5}}&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  font-family&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  y&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{{offset_y}}&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  dominant-baseline&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;middle&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  text-anchor&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;end&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  font-size&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;12&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  fill&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;#74838f&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  font-weight&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;bold&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; {{((lines - loop.index0)&#x2F;lines * max_y) | round}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;text&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And quite similarly, the x-axis can be generated the same way (width &lt;code&gt;y&lt;&#x2F;code&gt; being fixed to where the nudge starts &amp;amp; &lt;code&gt;x&lt;&#x2F;code&gt; being the offset):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;text&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  x&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{{offset_x}}&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  font-family&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  y&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{{height + padding + 10}}&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  dominant-baseline&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;hanging&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  text-anchor&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;middle&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  font-size&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;12&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  fill&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;#74838f&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;  font-weight&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;bold&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; {{loop.index0&#x2F;lines * max_x | round}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;text&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE680;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Putting this all together, we should have our labels in the right place:&lt;&#x2F;p&gt;
&lt;div&gt;
&lt;?xml version=&quot;1.0&quot; standalone=&quot;no&quot;?&gt;
&lt;svg
  width=&quot;100%&quot;
  height=&quot;100%&quot;
  viewBox=&quot;0 0 800 500&quot;
  preserveAspectRatio=&quot;xMidYMid meet&quot;
  xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;
  &gt;
  &lt;text 
    x=&quot;400&quot;
    y=&quot;25&quot;
    font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot;
    dominant-baseline=&quot;middle&quot;
    text-anchor=&quot;middle&quot;
    font-size=&quot;18&quot;
    fill=&quot;#74838f&quot;
    font-weight=&quot;700&quot;
    &gt;
    Example
  &lt;&#x2F;text&gt;
  &lt;text x=&quot;45&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;50&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;end&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot; &gt;6&lt;&#x2F;text&gt;
  &lt;text x=&quot;50&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;460&quot; dominant-baseline=&quot;hanging&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot;&gt;0&lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 50 L 750 50&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2.0&quot;  d=&quot;M 50 450 L 50 460&quot; &#x2F;&gt;
  &lt;text x=&quot;45&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;130&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;end&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot; &gt;5&lt;&#x2F;text&gt;
  &lt;text x=&quot;190&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;460&quot; dominant-baseline=&quot;hanging&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot;&gt;1&lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 130 L 750 130&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2.0&quot;  d=&quot;M 190 450 L 190 460&quot; &#x2F;&gt;
  &lt;text x=&quot;45&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;210&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;end&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot; &gt;4&lt;&#x2F;text&gt;
  &lt;text x=&quot;330&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;460&quot; dominant-baseline=&quot;hanging&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot;&gt;2&lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 210 L 750 210&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2.0&quot;  d=&quot;M 330 450 L 330 460&quot; &#x2F;&gt;
  &lt;text x=&quot;45&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;290&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;end&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot; &gt;2&lt;&#x2F;text&gt;
  &lt;text x=&quot;470&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;460&quot; dominant-baseline=&quot;hanging&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot;&gt;3&lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 290 L 750 290&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2.0&quot;  d=&quot;M 470 450 L 470 460&quot; &#x2F;&gt;
  &lt;text x=&quot;45&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;370&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;end&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot; &gt;1&lt;&#x2F;text&gt;
  &lt;text x=&quot;610&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;460&quot; dominant-baseline=&quot;hanging&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot;&gt;4&lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 370 L 750 370&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2.0&quot;  d=&quot;M 610 450 L 610 460&quot; &#x2F;&gt;
  &lt;text x=&quot;45&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;450&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;end&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot; &gt;0&lt;&#x2F;text&gt;
  &lt;text x=&quot;750&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;460&quot; dominant-baseline=&quot;hanging&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot;&gt;5&lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2&quot; fill=&quot;none&quot;  d=&quot;M 50 450 L 750 450&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2.0&quot;  d=&quot;M 750 450 L 750 460&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#8ff0a4&quot; stroke-linejoin=&quot;round&quot; d=&quot;M 190 383.33333333333337 L 330 250 L 470 283.3333333333333 L 610 50 L 750 250&quot; stroke-width=&quot;2.0&quot; fill=&quot;none&quot; &#x2F;&gt;
&lt;&#x2F;svg&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;bonus-smooth-lines&quot;&gt;Bonus: Smooth Lines&lt;&#x2F;h3&gt;
&lt;p&gt;One trick &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;schepers.cc&#x2F;getting-to-the-point&quot;&gt;I have found&lt;&#x2F;a&gt; is that you can make simple smoth lines by treating the points as a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Centripetal_Catmull%E2%80%93Rom_spline&quot;&gt;Catmull-Rom spline&lt;&#x2F;a&gt;, and then &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;lorikeet-dash&#x2F;blob&#x2F;a90107e73bc1e18136ce7a4e28e4c3c11a802f22&#x2F;src&#x2F;chart.rs#L155-L189&quot;&gt;converting to Cubic Beziers&lt;&#x2F;a&gt;, which SVG will draw happily.&lt;&#x2F;p&gt;
&lt;p&gt;Using this method, you can make your charts nice and smooth:&lt;&#x2F;p&gt;
&lt;div&gt;
&lt;?xml version=&quot;1.0&quot; standalone=&quot;no&quot;?&gt;
&lt;svg
  width=&quot;100%&quot;
  height=&quot;100%&quot;
  viewBox=&quot;0 0 800 500&quot;
  preserveAspectRatio=&quot;xMidYMid meet&quot;
  xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;
  &gt;
  &lt;text 
    x=&quot;400&quot;
    y=&quot;25&quot;
    font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot;
    dominant-baseline=&quot;middle&quot;
    text-anchor=&quot;middle&quot;
    font-size=&quot;18&quot;
    fill=&quot;#74838f&quot;
    font-weight=&quot;700&quot;
    &gt;
    Example
  &lt;&#x2F;text&gt;
  &lt;text x=&quot;45&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;50&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;end&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot; &gt;6&lt;&#x2F;text&gt;
  &lt;text x=&quot;50&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;460&quot; dominant-baseline=&quot;hanging&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot;&gt;0&lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 50 L 750 50&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2.0&quot;  d=&quot;M 50 450 L 50 460&quot; &#x2F;&gt;
  &lt;text x=&quot;45&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;130&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;end&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot; &gt;5&lt;&#x2F;text&gt;
  &lt;text x=&quot;190&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;460&quot; dominant-baseline=&quot;hanging&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot;&gt;1&lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 130 L 750 130&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2.0&quot;  d=&quot;M 190 450 L 190 460&quot; &#x2F;&gt;
  &lt;text x=&quot;45&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;210&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;end&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot; &gt;4&lt;&#x2F;text&gt;
  &lt;text x=&quot;330&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;460&quot; dominant-baseline=&quot;hanging&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot;&gt;2&lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 210 L 750 210&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2.0&quot;  d=&quot;M 330 450 L 330 460&quot; &#x2F;&gt;
  &lt;text x=&quot;45&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;290&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;end&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot; &gt;2&lt;&#x2F;text&gt;
  &lt;text x=&quot;470&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;460&quot; dominant-baseline=&quot;hanging&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot;&gt;3&lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 290 L 750 290&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2.0&quot;  d=&quot;M 470 450 L 470 460&quot; &#x2F;&gt;
  &lt;text x=&quot;45&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;370&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;end&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot; &gt;1&lt;&#x2F;text&gt;
  &lt;text x=&quot;610&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;460&quot; dominant-baseline=&quot;hanging&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot;&gt;4&lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-dasharray=&quot;10 6&quot; stroke-width=&quot;0.5&quot;  d=&quot;M 50 370 L 750 370&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2.0&quot;  d=&quot;M 610 450 L 610 460&quot; &#x2F;&gt;
  &lt;text x=&quot;45&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;450&quot; dominant-baseline=&quot;middle&quot; text-anchor=&quot;end&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot; &gt;0&lt;&#x2F;text&gt;
  &lt;text x=&quot;750&quot; font-family=&quot;-apple-system, system-ui, BlinkMacSystemFont, Roboto&quot; y=&quot;460&quot; dominant-baseline=&quot;hanging&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;#74838f&quot; font-weight=&quot;bold&quot;&gt;5&lt;&#x2F;text&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2&quot; fill=&quot;none&quot;  d=&quot;M 50 450 L 750 450&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#74838f&quot; stroke-width=&quot;2.0&quot;  d=&quot;M 750 450 L 750 460&quot; &#x2F;&gt;
  &lt;path stroke=&quot;#8ff0a4&quot; stroke-linejoin=&quot;round&quot; d=&quot;M 190 383.33333333333337 C 213.3333 361.1111, 283.3333 266.6667, 330.0000 250.0000 C 376.6667 233.3333, 423.3333 316.6667, 470.0000 283.3333 C 516.6667 250.0000, 563.3333 55.5556, 610.0000 50.0000 C 656.6667 44.4444, 726.6667 216.6667, 750.0000 250.0000&quot; stroke-width=&quot;2.0&quot; fill=&quot;none&quot; &#x2F;&gt;
&lt;&#x2F;svg&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;second-bonus-scuba-dive-graph&quot;&gt;Second Bonus: Scuba Dive Graph&lt;&#x2F;h3&gt;
&lt;p&gt;I have also used a similar method to plot a dive, displaying the &lt;strong&gt;Depth&lt;&#x2F;strong&gt; and &lt;strong&gt;Air&lt;&#x2F;strong&gt; on a split axis, with my &lt;em&gt;maximum depth&lt;&#x2F;em&gt; displayed:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;photos&#x2F;dive.svg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;We used tera, as a template engine, to generate an SVG chart with rust.  Some basic geometry was needed, but the results show for themselves. I hope you have found this educational and gives you some ideas.&lt;&#x2F;p&gt;
&lt;p&gt;Also: try out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;lorikeet-dash&quot;&gt;lorikeet-dash&lt;&#x2F;a&gt; and let me know what you think!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Implementing a Job queue with Tokio-Serde</title>
          <pubDate>Wed, 13 May 2020 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/implementing-a-jobq-with-tokio/</link>
          <guid>https://cetra3.github.io/blog/implementing-a-jobq-with-tokio/</guid>
          <description xml:base="https://cetra3.github.io/blog/implementing-a-jobq-with-tokio/">&lt;p&gt;In the &lt;a href=&quot;..&#x2F;implementing-a-jobq&#x2F;&quot;&gt;last blog&lt;&#x2F;a&gt; of this series, I implemented job queue with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;tmq&quot;&gt;tmq&lt;&#x2F;a&gt;.  I noted back then that &lt;strong&gt;tmq&lt;&#x2F;strong&gt; is great if you need to interact with other languages, but may be a little overkill if you are just using rust.  I wondered what it&#x27;d take to build the job queue with a smaller library footprint, using something like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;carllerche&#x2F;tokio-serde&quot;&gt;tokio-serde&lt;&#x2F;a&gt; instead of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;tmq&quot;&gt;tmq&lt;&#x2F;a&gt;.  It was successful, and this blog will step through some of the changes needed.&lt;&#x2F;p&gt;
&lt;p&gt;To follow along, these changes are on the &lt;code&gt;tokio_serde&lt;&#x2F;code&gt; branch of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;tree&#x2F;tokio_serde&quot;&gt;jobq repo&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you are getting lost make sure you &lt;a href=&quot;..&#x2F;implementing-a-jobq&#x2F;&quot;&gt;review the last blog&lt;&#x2F;a&gt; to see some of the logic &amp;amp; design tradeoffs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-tokio-serde&quot;&gt;What is Tokio-Serde&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Tokio-Serde&lt;&#x2F;strong&gt; is a little glue library that allows you to serialise&#x2F;deserialise objects on the wire. With the help of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio-util&#x2F;0.3.1&#x2F;tokio_util&#x2F;codec&#x2F;index.html&quot;&gt;tokio-util&#x27;s codec feature&lt;&#x2F;a&gt;, you can use &lt;em&gt;Tokio-Serde&lt;&#x2F;em&gt; to encode&#x2F;decode bytes into discrete messages to be passed on the wire.&lt;&#x2F;p&gt;
&lt;p&gt;From the &lt;em&gt;Tokio-Serde&lt;&#x2F;em&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio-serde&#x2F;&quot;&gt;documentation&lt;&#x2F;a&gt; using tokio-serde is 3 layers deep:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tokio::net::TcpStream&lt;&#x2F;code&gt;: The raw Stream&#x2F;Sink where we can get&#x2F;send bytes&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;tokio_util::codec::Framed&lt;&#x2F;code&gt;: The ability to chunk bytes into discrete frames&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;tokio_serde::Framed&lt;&#x2F;code&gt;: The ability to take these frames &amp;amp; then serialize&#x2F;deserialize them&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;the-tcp-stream&quot;&gt;The TCP Stream&lt;&#x2F;h3&gt;
&lt;p&gt;The TCP stream is your standard tcp connection.  In tokio, you can either &lt;code&gt;bind&lt;&#x2F;code&gt; or &lt;code&gt;connect&lt;&#x2F;code&gt; to a TCP socket.&lt;&#x2F;p&gt;
&lt;p&gt;With &lt;code&gt;connect&lt;&#x2F;code&gt;, you will get a straight tcp stream, if successful:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; tcp_stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TcpStream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;connect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;127.0.0.1:17653&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With &lt;code&gt;bind&lt;&#x2F;code&gt; you will get a listener, which will produce tcp streams when new connections come in:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; listener&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TcpListener&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;bind&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;127.0.0.1:17653&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;while let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(tcp_stream)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; listener&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_next&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;do something with the tcp stream&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;the-frame&quot;&gt;The Frame&lt;&#x2F;h3&gt;
&lt;p&gt;Ok so we have bytes coming across the wire now from our standard TCP stream.  As bytes come in, the tcp stream will be woken up so work can commence on it.  But TCP streams do not have a beginning or end, they are just a stream of bytes. We need something to &lt;em&gt;break&lt;&#x2F;em&gt; up this stream of bytes into discrete objects.  This is where &lt;code&gt;tokio_util::codec::Framed&lt;&#x2F;code&gt; comes in: it chunks down bytes on the wire into frames.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;tokio_util&lt;&#x2F;code&gt; crate comes with the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio-util&#x2F;0.3.1&#x2F;tokio_util&#x2F;codec&#x2F;trait.Encoder.html&quot;&gt;Encoder&lt;&#x2F;a&gt;&#x2F;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio-util&#x2F;0.3.1&#x2F;tokio_util&#x2F;codec&#x2F;trait.Decoder.html&quot;&gt;Decoder&lt;&#x2F;a&gt; traits which allow you to implement this.  &lt;code&gt;tokio-util&lt;&#x2F;code&gt; also comes with a simple, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio-util&#x2F;0.3.1&#x2F;tokio_util&#x2F;codec&#x2F;length_delimited&#x2F;index.html&quot;&gt;Length Delimited Codec&lt;&#x2F;a&gt; which, on the wire looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----------+--------------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| length   |          payload               |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----------+--------------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When decoding, this will read the length header, allocate some memory and wait until the payload is fully delivered.  If there are not enough bytes on the wire to do this, then it will be continuously polled until it is ready, keeping around a buffer. The semantics of &lt;code&gt;Decoder&lt;&#x2F;code&gt; mean that if you return no bytes, then it&#x27;s an indication there needs to be more to decode a frame successfully.&lt;&#x2F;p&gt;
&lt;p&gt;When encoding, the whole thing is ready to go, so tack on the length, your payload and let tokio handle the rest.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-serde-frame&quot;&gt;The Serde Frame&lt;&#x2F;h3&gt;
&lt;p&gt;We now have some raw bytes that have been bundled into frames which can be encoded&#x2F;decoded from the raw bytes into something more meaningful.  Rather than implement this by hand, we can rely on &lt;code&gt;tokio-serde&lt;&#x2F;code&gt; with one of the existing codecs, such as JSON, CBOR, Bincode or Messagepack.&lt;&#x2F;p&gt;
&lt;p&gt;Our existing job queue uses CBOR so we&#x27;ll use that here as well.  We can use the same messages &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;master&#x2F;src&#x2F;lib.rs&quot;&gt;we have previously used&lt;&#x2F;a&gt; but we will condense down the Client&#x2F;Worker to just &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;518c6c025a9e10477819fcc87acf8747383e9ba3&#x2F;src&#x2F;lib.rs#L21-L25&quot;&gt;&lt;code&gt;ClientMessage&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ServerMessage&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Hello&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; Hello with client name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Request&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;JobRequest&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Completed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Failed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ClientMessage&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Hello&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Order&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Acknowledged&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Putting these 3 layers together, we get a &lt;code&gt;Stream&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Sink&lt;&#x2F;code&gt; we can send values to:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; tcp_stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TcpStream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;connect&lt;&#x2F;span&gt;&lt;span&gt;(addr)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; length_delimited&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tokio_util&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;codec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Framed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(tcp_stream,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; LengthDelimitedCodec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tokio_serde&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Framed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(length_delimited,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Cbor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With that we have our transport that we want: length delimited cbor frames.  On the wire this is not too different to ZeroMQ, but would probably shave a few bytes here and there.  Now we need to implement the Server&#x2F;Client components.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implementing-a-server&quot;&gt;Implementing a Server&lt;&#x2F;h2&gt;
&lt;p&gt;We want to accept connections from clients&#x2F;workers and then route out messages to the appropriate connection.  We will leave the server logic itself &lt;em&gt;mostly&lt;&#x2F;em&gt; untouched, and instead replace the &lt;code&gt;tmq::router&lt;&#x2F;code&gt; with a new &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;tokio_serde&#x2F;src&#x2F;router.rs&quot;&gt;&lt;code&gt;Router&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;  struct which uses &lt;code&gt;tokio-serde&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-router&quot;&gt;The Router&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;tokio_serde&#x2F;src&#x2F;router.rs&quot;&gt;&lt;code&gt;Router&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; struct handles incoming client connections and allows our server logic to send messages based upon their name.&lt;&#x2F;p&gt;
&lt;p&gt;We have multiple &lt;em&gt;clients&#x2F;workers&lt;&#x2F;em&gt; that will be connecting to our jobq server so we will need to keep around some state to handle those connections.  How will we do that? Well, a simple &lt;code&gt;HashMap&amp;lt;String, Connection&amp;gt;&lt;&#x2F;code&gt; is probably a good start.  When a connection comes in, we want to add it to our map of known clients.&lt;&#x2F;p&gt;
&lt;p&gt;If a connection drops off (i.e, returns &lt;code&gt;Poll::Ready(None)&lt;&#x2F;code&gt; from the &lt;code&gt;Stream&lt;&#x2F;code&gt;) then we can clean it from our known connections. If a new client with the same name comes in, we can just drop off the old client connection (alternatively, we could reject the new one).  These semantics are obviously different from the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;api.zeromq.org&#x2F;4-3:zmq-socket#toc25&quot;&gt;ZeroMQ Router socket&lt;&#x2F;a&gt;, and not nearly as robust, but are good enough for a PoC.&lt;&#x2F;p&gt;
&lt;p&gt;The router can be implemented as a &lt;code&gt;Stream&lt;&#x2F;code&gt; which, when polled will check:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Any pending tcp connections&lt;&#x2F;li&gt;
&lt;li&gt;Any pending clients that are in the middle of handshaking&lt;&#x2F;li&gt;
&lt;li&gt;Any pending messages from existing clients&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This can be seen as a loop, whereby each time we hit &lt;code&gt;poll_next&lt;&#x2F;code&gt; we will hit all 3 areas in case we have anything waiting for us.  If there is nothing in one area, then we move onto the next one, and so on.  We can do an &lt;code&gt;if let Poll::Ready()&lt;&#x2F;code&gt; pattern here to skip things that aren&#x27;t ready.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;pending-clients&quot;&gt;Pending Clients&lt;&#x2F;h4&gt;
&lt;p&gt;How do we know the client name when connecting?  Well we can implement a list of pending clients.  When they send a &lt;code&gt;ServerMessage::Hello&lt;&#x2F;code&gt;  message, we can then put them in our known clients list.  This is a pretty lightweight handshake, but accomplishes our goals.&lt;&#x2F;p&gt;
&lt;p&gt;First, we convert the tcp stream from listener into a list of pending clients:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Ready&lt;&#x2F;span&gt;&lt;span&gt;(val)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Pin&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;listener)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;poll_next&lt;&#x2F;span&gt;&lt;span&gt;(cx) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span&gt; val {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(tcp_stream))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; length_delimited&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;                CodecFramed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(tcp_stream,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; LengthDelimitedCodec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; framed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Framed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(length_delimited,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Cbor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;pending_clients&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(framed);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span&gt;(err))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            error!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Error checking for new requests:{:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        None&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, with that checked off, we can then consult our pending clients.  Note here I am swapping out the pending clients &lt;code&gt;Vec&lt;&#x2F;code&gt; with an empty &lt;code&gt;Vec&lt;&#x2F;code&gt; to avoid doubly borrowing as mutable.  There may be an easier&#x2F;more efficient way of doing this and would be interested in knowing what that may look like.&lt;&#x2F;p&gt;
&lt;p&gt;We will repopulate the list as we go through, so we won&#x27;t lose any pending clients, but one or two may drop off if they are not doing the handshake correctly or they have already disconnected.  We&#x27;ll also add the &lt;code&gt;Hello&lt;&#x2F;code&gt; message to our messages to send as a &lt;code&gt;Stream&lt;&#x2F;code&gt; response.  That&#x27;s our &lt;code&gt;buffer&lt;&#x2F;code&gt; that we will be using.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; new_pending&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;mem&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;swap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;pending_clients,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; new_pending);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;for mut&lt;&#x2F;span&gt;&lt;span&gt; pending&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; new_pending&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Ready&lt;&#x2F;span&gt;&lt;span&gt;(val)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Pin&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; pending)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;poll_next&lt;&#x2F;span&gt;&lt;span&gt;(cx) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        match&lt;&#x2F;span&gt;&lt;span&gt; val {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ServerMessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Hello&lt;&#x2F;span&gt;&lt;span&gt;(name)))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;                debug!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;New Client connection from `{}`&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ServerMessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Hello&lt;&#x2F;span&gt;&lt;span&gt;(name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;()));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;clients&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(name, pending);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(msg))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;                warn!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Received unknown message during handshake:{:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, msg);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span&gt;(err))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;                error!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Error checking for new requests:{:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            None&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;pending_clients&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(pending);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;existing-clients&quot;&gt;Existing Clients&lt;&#x2F;h4&gt;
&lt;p&gt;We&#x27;ll do the same &lt;em&gt;trick&lt;&#x2F;em&gt; for the client &lt;code&gt;HashMap&lt;&#x2F;code&gt;: swap it out for an empty one as we&#x27;re processing.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll put all received messages into an internal buffer, which we will use later to send the actual response from the stream.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; new_clients&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HashMap&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;mem&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;swap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;clients,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; new_clients);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (name,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span&gt; client)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; new_clients&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Pin&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; client)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;poll_next&lt;&#x2F;span&gt;&lt;span&gt;(cx) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(val)))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            trace!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Received message from `{}`: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name, val);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(val);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;clients&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(name, client);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;            &#x2F;&#x2F;Finished&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            debug!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Client `{}` disconnecting&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span&gt;(err)))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;            &#x2F;&#x2F;Error&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            error!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Error from `{}`: {} Removing connection.&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name, err);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Pending&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;clients&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(name, client);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;returning-messages&quot;&gt;Returning Messages&lt;&#x2F;h4&gt;
&lt;p&gt;We&#x27;ve buffered up the returned messages into a &lt;code&gt;Vec&lt;&#x2F;code&gt; and we can return one.  But if there are more after popping we can let the waker know we may have more stuff to process:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(val)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;pop&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;() &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;waker&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;wake_by_ref&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(val)));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Pending&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;sending-messages&quot;&gt;Sending Messages&lt;&#x2F;h3&gt;
&lt;p&gt;Sending messages requires that you know the name of the client, but it is otherwise a simple wrapper:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; send_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;, client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;, msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ClientMessage&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(connection)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;clients&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;get_mut&lt;&#x2F;span&gt;&lt;span&gt;(client) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(msg)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;anyhow!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Client `{}` not connected!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, client));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can even expose a way to check if any clients are connected of that name, and simply not bother sending a message in this case:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; is_connected&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;    self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;clients&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;contains_key&lt;&#x2F;span&gt;&lt;span&gt;(client)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;changes-to-the-server&quot;&gt;Changes to the Server&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;Server&lt;&#x2F;code&gt; struct itself does not really change all that much.  Instead of using a &lt;code&gt;tmq::router&lt;&#x2F;code&gt; we&#x27;ll use our new &lt;code&gt;Router&lt;&#x2F;code&gt;.  Although strictly not equivalent, for the purpose of the job queue, this is an OK analogue:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; router&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Router&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;job_address)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;while let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(server_msg)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; router&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; existing server logic here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;implementing-clients&quot;&gt;Implementing Clients&lt;&#x2F;h2&gt;
&lt;p&gt;Not much has changed here as well.  We could get away with not using our own struct definition here at all and just set up a connection, but would be great if we had something we could plop in where the old &lt;code&gt;tmq::dealer&lt;&#x2F;code&gt; was used.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;dealer&quot;&gt;Dealer&lt;&#x2F;h3&gt;
&lt;p&gt;We implement a &lt;code&gt;Dealer&lt;&#x2F;code&gt; struct which simply wraps a &lt;code&gt;tokio_serde::Framed&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ClientFramed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Framed&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    CodecFramed&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;TcpStream&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; LengthDelimitedCodec&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    ClientMessage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    ServerMessage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Cbor&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ClientMessage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ServerMessage&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Dealer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ClientFramed&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Dealer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ToSocketAddrs&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(addr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; tcp_stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TcpStream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;connect&lt;&#x2F;span&gt;&lt;span&gt;(addr)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; length_delimited&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; CodecFramed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(tcp_stream,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; LengthDelimitedCodec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Framed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(length_delimited,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Cbor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; { connection })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the dealer, both receiving and sending marry up with &lt;code&gt;Stream&lt;&#x2F;code&gt; and &lt;code&gt;Sink&lt;&#x2F;code&gt; quite well, so we can implement that quite easily:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Dealer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ClientMessage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; poll_next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Pin&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, cx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Context&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Poll&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        match&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Pin&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; self_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;connection)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;poll_next&lt;&#x2F;span&gt;&lt;span&gt;(cx) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(val))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;err&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;()))),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Pending&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Pending&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;worker-changes&quot;&gt;Worker Changes&lt;&#x2F;h3&gt;
&lt;p&gt;The worker doesn&#x27;t change much, we &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;518c6c025a9e10477819fcc87acf8747383e9ba3&#x2F;src&#x2F;worker.rs#L19&quot;&gt;call split&lt;&#x2F;a&gt; on the &lt;code&gt;Dealer&lt;&#x2F;code&gt; struct to get our two pipes, but otherwise treat it as per normal:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; send_skt, recv)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Dealer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;job_address)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;running-the-changes&quot;&gt;Running the Changes&lt;&#x2F;h2&gt;
&lt;p&gt;Running the branch we should see a lot of the same chatter we saw from the &lt;a href=&quot;..&#x2F;implementing-a-jobq&#x2F;&quot;&gt;previous version&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 2020-05-13 11:13:02 DEBUG jobq::server &amp;gt; New: Job { id: 5500, username: &amp;quot;test_client&amp;quot;, name: &amp;quot;test&amp;quot;, uuid: 95182793-7a08-4329-a9f1-4be0c1f1d041, params: Null, priority: Normal, status: Queued }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 2020-05-13 11:13:02 WARN  jobq::server &amp;gt; Job failed: 5496, Reason: Simulating failure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 2020-05-13 11:13:02 WARN  jobq::server &amp;gt; Job failed: 5484, Reason: Simulating failure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 2020-05-13 11:13:02 WARN  jobq::server &amp;gt; Job failed: 5472, Reason: Simulating failure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 2020-05-13 11:13:03 WARN  jobq::server &amp;gt; Job failed: 5460, Reason: Simulating failure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Implementing a more barebones messaging system native in rust took not much time at all.  While this solution is not nearly as robust as using ZeroMQ, it does provide a more building blocks approach to messaging, reducing external dependencies.  I found the hardest portion was gluing everything together between the 3 main crates and getting the types right.  &lt;em&gt;Tokio-Serde&lt;&#x2F;em&gt; could use a bit more fleshing out and does seem quite embryonic still, but it is enough to get your hands dirty.&lt;&#x2F;p&gt;
&lt;p&gt;The initial design of the jobq made it easy to slot in another transport layer as well.  All the structs &amp;amp; types were all ready and rolling to go, we just needed a couple of extra libraries to fill in the pieces.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Lorikeet 0.11.0 - Upgrading to async</title>
          <pubDate>Tue, 21 Apr 2020 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/lorikeet-0-11-0/</link>
          <guid>https://cetra3.github.io/blog/lorikeet-0-11-0/</guid>
          <description xml:base="https://cetra3.github.io/blog/lorikeet-0-11-0/">&lt;p&gt;I have just spent some time doing an initial async version of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;lorikeet&quot;&gt;lorikeet&lt;&#x2F;a&gt; now that the async&#x2F;await syntax is stable and the ecosystem has caught up.  The major blocker was reqwest, as this is used extensively in the &lt;code&gt;http&lt;&#x2F;code&gt; test.&lt;&#x2F;p&gt;
&lt;p&gt;This async version is available now as version &lt;code&gt;0.11.0&lt;&#x2F;code&gt;.  You can also install the cli by running &lt;code&gt;cargo install lorikeet&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-lorikeet&quot;&gt;What is Lorikeet&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Lorikeet&lt;&#x2F;strong&gt; is a command line tool and a rust library to run tests for smoke testing and integration testing.  &lt;em&gt;Lorikeet&lt;&#x2F;em&gt; currently supports bash commands and simple HTTP requests along with system information (RAM, Disk &amp;amp; CPU).  There is more information on the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;lorikeet&quot;&gt;github readme&lt;&#x2F;a&gt; about how to write test files, including how to structure dependent tests and make assertions on the output.&lt;&#x2F;p&gt;
&lt;p&gt;As a simple example, here&#x27;s a test plan to check to see whether reddit is up, and then tries to login if it is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;check_reddit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  http&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; https:&#x2F;&#x2F;www.reddit.com&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  regex&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; the front page of the internet&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;login_to_reddit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  http&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;    url&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; https:&#x2F;&#x2F;www.reddit.com&#x2F;api&#x2F;login&#x2F;{{user}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;    form&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;      user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;user&lt;&#x2F;span&gt;&lt;span&gt;}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;      passwd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;pass&lt;&#x2F;span&gt;&lt;span&gt;}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;      api_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  jmespath&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; length(json.errors)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  matches&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  require&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; check_reddit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can run this as a simple cli command, ensuring that you have a &lt;code&gt;config.yml&lt;&#x2F;code&gt; looks something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;pass&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Running it you will see the results:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;$ lorikeet -c config.yml test.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; check_reddit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  pass&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  output&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; the front page of the internet&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  duration&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; 1416.591ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; login_to_reddit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  pass&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  output&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;&quot;&gt;  duration&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; 1089.0276ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;skipping-futures-0-1&quot;&gt;Skipping futures 0.1&lt;&#x2F;h2&gt;
&lt;p&gt;In retrospect, I am glad that I skipped out on rewriting lorikeet with the classic combinator style futures.  The migration from standard blocking code to async code is much easier than writing from combinators.  Having done the former with &lt;a href=&quot;..&#x2F;mpart-async-0-3-0&#x2F;&quot;&gt;mpart-async&lt;&#x2F;a&gt;, it felt quite easy to sprinkle in a few &lt;code&gt;async&lt;&#x2F;code&gt; and &lt;code&gt;await&lt;&#x2F;code&gt; statements to get things all wired up.&lt;&#x2F;p&gt;
&lt;p&gt;As an example, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;lorikeet&#x2F;blob&#x2F;0.10.0&#x2F;src&#x2F;step.rs#L391-L394&quot;&gt;waiting for the request&lt;&#x2F;a&gt; used to be:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; response&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;execute&lt;&#x2F;span&gt;&lt;span&gt;(request&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;err&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;err&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Error connecting to url {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, with async, things are not much different:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; response&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;execute&lt;&#x2F;span&gt;&lt;span&gt;(request&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;err&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;err&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Error connecting to url {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;using-tokio-sync-primitives&quot;&gt;Using tokio sync primitives&lt;&#x2F;h2&gt;
&lt;p&gt;Tokio has a few primitives that are very close to their std counterparts.&lt;&#x2F;p&gt;
&lt;p&gt;Lorikeet now uses a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;0.2.18&#x2F;tokio&#x2F;sync&#x2F;struct.Mutex.html&quot;&gt;tokio mutex&lt;&#x2F;a&gt; to record the outcome of each of the steps:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;steps&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;[index]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Completed&lt;&#x2F;span&gt;&lt;span&gt;(outcome);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Also using an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;0.2.18&#x2F;tokio&#x2F;sync&#x2F;mpsc&#x2F;fn.unbounded_channel.html&quot;&gt;unbounded channel&lt;&#x2F;a&gt; so each step can inform the main runner when they are finished:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (tx,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span&gt; rx)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; unbounded_channel&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; later on....&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(finished_idx)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; rx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;recv&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Interesting to note that the &lt;code&gt;UnboundedSender&lt;&#x2F;code&gt; &lt;code&gt;send()&lt;&#x2F;code&gt; method is not async and does not block either.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;multipart-file-uploads&quot;&gt;Multipart File Uploads&lt;&#x2F;h2&gt;
&lt;p&gt;The new version of reqwest &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;seanmonstar&#x2F;reqwest&#x2F;issues&#x2F;646&quot;&gt;does not support file uploads&lt;&#x2F;a&gt; easily.  You don&#x27;t want to buffer the entire file in memory.  Luckily I have had some experience on how to wire this up with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;mpart-async&quot;&gt;mpart-async&lt;&#x2F;a&gt;, and can reuse some of the learnings there.&lt;&#x2F;p&gt;
&lt;p&gt;This does require the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;tokio-util&quot;&gt;tokio-util&lt;&#x2F;a&gt; crate, which bridges &lt;code&gt;AsyncRead&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;AsyncWrite&lt;&#x2F;code&gt; with &lt;code&gt;Sink&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Stream&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The relevent glue section &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;lorikeet&#x2F;blob&#x2F;ef8ba4a0f08e82d4cb33524b9e74cc50beec9078&#x2F;src&#x2F;step&#x2F;http.rs#L157-L167&quot;&gt;is as follows&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; file_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; path_struct&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span&gt;file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;file_name&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_string_lossy&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;unwrap_or_default&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; File&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;path_struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;file)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;err&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; reader&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Body&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;wrap_stream&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FramedRead&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(file,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BytesCodec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;form&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;part&lt;&#x2F;span&gt;&lt;span&gt;(key,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Part&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;stream&lt;&#x2F;span&gt;&lt;span&gt;(reader)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;file_name&lt;&#x2F;span&gt;&lt;span&gt;(file_name)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;detecting-blocking-code&quot;&gt;Detecting Blocking Code&lt;&#x2F;h2&gt;
&lt;p&gt;There is no annotation or warning whenever you are using blocking code in an async context.  This is an issue especially when porting over older code which was previously blocking.  Chances are I have missed a few sections that are blocking and will need to revisit them accordingly.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily, the fail case for blocking code is usually reduced throughput, down to the number of worker threads, so it is not cataclysmic if there are some blocking sections in your async code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I was happy with the ease at which it was to convert existing sections to async by sprinkling a few keywords here and there.  I am concerned that it is too easy to have blocking sections, so I hope there is some tooling&#x2F;linting around that in the future.&lt;&#x2F;p&gt;
&lt;p&gt;Please give lorikeet a go and try out some of the newer features from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;lorikeet&quot;&gt;the readme&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Implementing a Job queue with Tokio, PostgreSQL &amp; ZeroMQ</title>
          <pubDate>Thu, 09 Apr 2020 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/implementing-a-jobq/</link>
          <guid>https://cetra3.github.io/blog/implementing-a-jobq/</guid>
          <description xml:base="https://cetra3.github.io/blog/implementing-a-jobq/">&lt;p&gt;One of the challenges I have had with on premise solutions is the lack of reliable environments and constrained resources.   Not only are you limited in your ability to control things, you need to ensure that things continue on in the case of failure.&lt;&#x2F;p&gt;
&lt;p&gt;I was tasked with rewriting the job processing pipeline for my company&#x27;s product, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.schoolbench.com.au&#x2F;&quot;&gt;SchoolBench&lt;&#x2F;a&gt;, to ensure a greater level of robustness in the case of service or system failure.&lt;&#x2F;p&gt;
&lt;p&gt;This article steps through an approach to this using async rust &amp;amp; the help of tokio ZeroMQ library: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;tmq&quot;&gt;tmq&lt;&#x2F;a&gt; along with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;tokio-postgres&quot;&gt;tokio-postgres&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;As some excellent work has been put in bringing tmq to async, I thought it pertinent to look at reapproaching the pipeline using async code.  I have published an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&quot;&gt;initial prototype&lt;&#x2F;a&gt; of what the end result may look like, and will be stepping through the approach here, and some of the tradeoffs I made&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-tmq-zeromq&quot;&gt;Why TMQ&#x2F;ZeroMQ?&lt;&#x2F;h2&gt;
&lt;p&gt;For those not familiar with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zeromq.org&#x2F;&quot;&gt;ZeroMQ&lt;&#x2F;a&gt;, it is a messaging library with a lot of features, from standard publish&#x2F;subscribe to more elaborate arrangements.  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;tmq&quot;&gt;tmq&lt;&#x2F;a&gt; is a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tokio.rs&quot;&gt;tokio&lt;&#x2F;a&gt; compatible binding that allows you to bridge ZeroMQ with the async world of rust.&lt;&#x2F;p&gt;
&lt;p&gt;You would use ZeroMQ if you need to interact with other languages easily and don&#x27;t want it to be too opinionated on what message formats are being sent.  If you are purely using rust then this may be not be a great fit, but it does still provide you some great interprocess &amp;amp; internetwork capabilities that you won&#x27;t get from just tokio.&lt;&#x2F;p&gt;
&lt;p&gt;We use ZeroMQ in SchoolBench as it is a polyglot application and has a lot of components written in python &amp;amp; java as well as rust.  It is lightweight enough not to cause overheads &amp;amp; complex enough for the use cases I have thrown at it so far.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;prior-work&quot;&gt;Prior Work&lt;&#x2F;h2&gt;
&lt;p&gt;There are some existing rust based job queues that do similar things and may be more suited to your own personal tastes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kureuil&#x2F;batch-rs&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;kureuil&#x2F;batch-rs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;badboy&#x2F;oppgave&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;badboy&#x2F;oppgave&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rusty-celery&#x2F;rusty-celery&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;rusty-celery&#x2F;rusty-celery&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Probably lots more I haven&#x27;t found&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Most of them use some sort of message broker, such as &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rabbitmq.com&#x2F;&quot;&gt;RabbitMQ&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;redis.io&#x2F;&quot;&gt;Redis&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-a-job&quot;&gt;What is a Job?&lt;&#x2F;h2&gt;
&lt;p&gt;It helps to explain what a job is.  In the context of SchoolBench a job is a piece of work that may take some time to do (think seconds), is quite intensive, and may fail. Once an asset is saved into SchoolBench, lots of processes are kicked off in the background to &lt;em&gt;fill in the blanks&lt;&#x2F;em&gt; and provide information about the asset.&lt;&#x2F;p&gt;
&lt;p&gt;Some examples of jobs are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Running &lt;a href=&quot;..&#x2F;face-detection-with-tensorflow-rust&#x2F;&quot;&gt;Facial Recognition&lt;&#x2F;a&gt; on images using tensorflow&lt;&#x2F;li&gt;
&lt;li&gt;Generating Thumbnails and Watermarked renditions of images&lt;&#x2F;li&gt;
&lt;li&gt;Calculating whether a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;dhash&quot;&gt;photo is a duplicate&lt;&#x2F;a&gt; of another photo and marking the set of duplicates&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A lot of these are quite intensive &amp;amp; can sometimes fail in weird and wonderful ways:  An image uploaded may be corrupted, so renditions may not run;  There may be an issue running the neural net;  The VM may be experience ballooning and fail to allocate memory, etc...&lt;&#x2F;p&gt;
&lt;p&gt;So we need a way of describing a discrete piece of work which may happen some time in the future and may happen by a completely isolated process.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;resource-contention&quot;&gt;Resource Contention&lt;&#x2F;h3&gt;
&lt;p&gt;We have very limited resources in an on premise environment. After providing a minimum recommendation it is important to tune for that worst case.  This is different in a cloud environment where you can spin up guests in a work stealing fashion if you throw more money at your infrastructure. on premise is usually more fixed in terms of server and hardware allocations, and so we need to plan for that.&lt;&#x2F;p&gt;
&lt;p&gt;This is one area where the job queue deviates from a lot of existing systems out there: we assume we&#x27;re just running on the one set of CPUs and so there is a fixed number of active jobs at any given time.&lt;&#x2F;p&gt;
&lt;p&gt;We also want a simple way to prioritise tasks as they are submitted, so that some jobs finish first, with higher value jobs such as thumbnail generation happening first. The job queue uses a simple 3-tier priority system to do this: High, Medium &amp;amp; Low.&lt;&#x2F;p&gt;
&lt;p&gt;This simple system could mean if there are not enough resources to finish jobs then there is a chance that lower tier jobs may never get around to completing.  In practice the sort of work loads we have seen this is not the case, but it is a possibility. In which case more processors would be needed to keep up with the load or another style of priority to be implemented (such as fair queueing).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;persistence&quot;&gt;Persistence&lt;&#x2F;h3&gt;
&lt;p&gt;Jobs need to survive crashes and server restarts in a robust fashion.  Existing job queues utilise an existing persistence layer&#x2F;message broker such as &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;redis.io&#x2F;&quot;&gt;Redis&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rabbitmq.com&#x2F;&quot;&gt;RabbitMQ&lt;&#x2F;a&gt;.  I have chosen PostgreSQL as the persistence layer as it is performant enough, and is already in use for metadata storage.  However, you could easily swap out another type of persistence with a bit of refactoring.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-overall-process&quot;&gt;The Overall Process&lt;&#x2F;h2&gt;
&lt;p&gt;The high level proces is as follows:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A User Action triggers some sort of logic which requests a job.  This could be an automatic rule somewhere or could be the a user specifically requesting a job to run&lt;&#x2F;li&gt;
&lt;li&gt;A server listens for requests and puts them into a queue&lt;&#x2F;li&gt;
&lt;li&gt;If there are jobs that can be processed then they are submitted to the individual worker who is responsible for finishing the job&lt;&#x2F;li&gt;
&lt;li&gt;When a job completes or fails, then it is marked as so with a duration on how long things take&lt;&#x2F;li&gt;
&lt;li&gt;Everytime a new event is triggered, such as a job in a queue or a job completed&#x2F;failed, the server checks to see if it can mark jobs as processing&lt;&#x2F;li&gt;
&lt;li&gt;All job status updates &amp;amp; information is persisted to a db, so that things can pick up again if there is a failure &amp;amp; reports can be ran using standard SQL tools&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;client-server-worker&quot;&gt;Client, Server, Worker&lt;&#x2F;h3&gt;
&lt;p&gt;We split the roles of the job queue into 3 different types:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Clients&lt;&#x2F;strong&gt; that submit requests to the server&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;strong&gt;Server&lt;&#x2F;strong&gt; which does the main job queue loop&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;strong&gt;Workers&lt;&#x2F;strong&gt; that receive jobs and do work, returning whether the work was completed &lt;em&gt;(not the work outcome itself, just the status; we assume that the worker will update something out of band like another db or filesystem)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;One possible thing to note is that there is only ever one server, but there can be as many workers and clients as allowed.  The workers themselves can also be clients and submit requests if they want to.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;communication&quot;&gt;Communication&lt;&#x2F;h3&gt;
&lt;p&gt;The server, worker and clients all communicate via a ZeroMQ &lt;code&gt;DEALER&#x2F;ROUTER&lt;&#x2F;code&gt; socket.&lt;&#x2F;p&gt;
&lt;p&gt;Clients and Workers use the &lt;code&gt;DEALER&lt;&#x2F;code&gt; style socket to retrieve &amp;amp; send messages, but also identify themselves, and the server uses &lt;code&gt;ROUTER&lt;&#x2F;code&gt;. The identity is included as the first ZeroMQ multipart frame when it is received and so can be used to route messages back to the appropriate place.&lt;&#x2F;p&gt;
&lt;p&gt;The messages are serialised on the wire as &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cbor.io&#x2F;&quot;&gt;CBOR&lt;&#x2F;a&gt; using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;serde_cbor&quot;&gt;serde_cbor&lt;&#x2F;a&gt;.  CBOR was chosen because it allows for the message type to be flexible &amp;amp; there are plenty of implementations in other languages.  JSON could be used as well, as arguably the support for JSON is much higher, but would mean larger message sizes.&lt;&#x2F;p&gt;
&lt;p&gt;With serde it&#x27;s pretty easy to adjust what serialisation is used, so some experimentation could be worthwhile.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-job-structs&quot;&gt;The Job Structs&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;a09ebcaff164c2153cdceba0031dbfb7caa1ea3b&#x2F;src&#x2F;lib.rs#L42-L50&quot;&gt;&lt;code&gt;Job&lt;&#x2F;code&gt; struct&lt;&#x2F;a&gt; is defined as follows (with the &lt;code&gt;Status&lt;&#x2F;code&gt; &amp;amp; &lt;code&gt;Priority&lt;&#x2F;code&gt; enums listed too):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Job&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; ID of the Job so it can be tracked&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; username&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; Username of who submitted the job&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; Name of the job&#x2F;worker, `rendition`, etc..&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; uuid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Uuid&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; Unique ID of the asset&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; params&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Value&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; Any parameters of the job in question&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; priority&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Priority&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; The priority of the job&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Status&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; The status of the job&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The job has a current status which starts with &lt;code&gt;Queued&lt;&#x2F;code&gt;, goes to &lt;code&gt;Processing&lt;&#x2F;code&gt; when it is active and then marked as either &lt;code&gt;Completed&lt;&#x2F;code&gt; or &lt;code&gt;Failed&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Status&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Queued&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Processing&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Completed&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Failed&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The priority is a simple 3-tier system of &lt;code&gt;High&lt;&#x2F;code&gt;, &lt;code&gt;Normal&lt;&#x2F;code&gt; &amp;amp; &lt;code&gt;Low&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Priority&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    High&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Normal&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Low&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;message-types&quot;&gt;Message types&lt;&#x2F;h3&gt;
&lt;p&gt;Messages are split up based upon who the destination is with a shared &lt;code&gt;Hello&lt;&#x2F;code&gt; message that can be serialised as any enum:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ServerMessage&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Hello&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Request&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;JobRequest&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Completed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Failed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ClientMessage&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Hello&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Acknowledged&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WorkerMessage&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Hello&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Order&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The  &lt;code&gt;JobRequest&lt;&#x2F;code&gt; is very similar to a &lt;code&gt;Job&lt;&#x2F;code&gt; but does not have an allocated id or status yet:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; JobRequest&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; username&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; uuid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Uuid&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; params&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Value&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; priority&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Priority&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;the-params-value&quot;&gt;The Params Value&lt;&#x2F;h3&gt;
&lt;p&gt;One thing to note is the &lt;code&gt;params&lt;&#x2F;code&gt; is of the type &lt;code&gt;serde_json::Value&lt;&#x2F;code&gt;.  This is really to allow the greatest flexibility into what parameters are sent with each job &amp;amp; also to have it persist to PostgreSQL as a &lt;code&gt;jsonb&lt;&#x2F;code&gt; column.&lt;&#x2F;p&gt;
&lt;p&gt;Alternatively, a tighter &lt;code&gt;enum&lt;&#x2F;code&gt; could be used for different job names if you knew ahead of time the jobs that will be requested.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;serialisation-helpers&quot;&gt;Serialisation helpers&lt;&#x2F;h3&gt;
&lt;p&gt;To reduce some of the repetitiveness, there is a serialisation helper which simply serialises to &lt;code&gt;CBOR&lt;&#x2F;code&gt; for any struct that implements &lt;code&gt;Serialize&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ToMpart&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; to_mpart&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Multipart&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; to_msg&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Message&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; serde&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ser&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ToMpart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; to_mpart&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Multipart&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; serde_cbor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_vec&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Multipart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bytes]))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; to_msg&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Message&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; serde_cbor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_vec&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bytes))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;client-requests&quot;&gt;Client Requests&lt;&#x2F;h2&gt;
&lt;p&gt;Clients can send requests by constructing job requests and sending them to the server.  They just need to construct the &lt;code&gt;Request&lt;&#x2F;code&gt; enum and send it on the wire:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; send,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span&gt; recv)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; dealer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;set_identity&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;b&amp;quot;test_client&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;connect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;config&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;job_address)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Multipart&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; job&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; JobRequest&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;test&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    username&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;test_client&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    params&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Null&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    uuid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Uuid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new_v4&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    priority&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; PriorityLow&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;send&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ServerMessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Request&lt;&#x2F;span&gt;&lt;span&gt;(job)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_mpart&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;worker-processing&quot;&gt;Worker Processing&lt;&#x2F;h2&gt;
&lt;p&gt;For workers doing the work, they should do something &amp;amp; then return whether it&#x27;s failed or completed.&lt;&#x2F;p&gt;
&lt;p&gt;To make this easier, a &lt;code&gt;Worker&lt;&#x2F;code&gt; trait is implemented.  Since some work will be async &amp;amp; some not, we want our trait to be async-capable.  At the writing of this article you can&#x27;t have &lt;code&gt;async&lt;&#x2F;code&gt; in trait definitions, but there is the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;async-trait&quot;&gt;async_trait&lt;&#x2F;a&gt; crate that allows you to decorate a trait definition and do what we&#x27;re after.&lt;&#x2F;p&gt;
&lt;p&gt;For errors we&#x27;re going to use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;anyhow&quot;&gt;anyhow&lt;&#x2F;a&gt; crate, but a more generic error approach could be used with a bit of a refactor.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[async_trait]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Worker&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Sized&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; JOB_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;static str&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; process&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, job&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Job&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The implementation of this trait means that you can do lots within the &lt;code&gt;process&lt;&#x2F;code&gt; body and simplifies it.&lt;&#x2F;p&gt;
&lt;p&gt;An original version had the &lt;code&gt;process&lt;&#x2F;code&gt; method accept &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt;, but that caused some contention when trying to process jobs concurrently.  Instead you&#x27;ll need some interior mutability if you need to provide any mutable references to &lt;code&gt;&amp;amp;self&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;As an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;worker.rs#L82-L94&quot;&gt;example&lt;&#x2F;a&gt;, the test worker will simply wait for 100 milliseconds and then fail every 12th job based upon the id:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Worker&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TestWorker&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; JOB_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;static str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;test&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; process&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, job&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Job&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;        delay_for&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Duration&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_millis&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; job&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;%&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 12&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;anyhow!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Simulating failure&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;the-work-method&quot;&gt;The Work Method&lt;&#x2F;h3&gt;
&lt;p&gt;There is another method, &lt;code&gt;work&lt;&#x2F;code&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;worker.rs#L16&quot;&gt;on the trait&lt;&#x2F;a&gt; which sets up &amp;amp; hides some of the complexity away of getting a worker to listen for requests coming through.   This is plumbing to make it easy to run a &lt;code&gt;Worker&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; work&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, job_address&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can &lt;code&gt;await&lt;&#x2F;code&gt; this method for anything that implements &lt;code&gt;Worker&lt;&#x2F;code&gt; to have it process incoming requests:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; jobq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;worker&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Worker&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TestWorker&lt;&#x2F;span&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;tokio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async move&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(err)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; TestWorker&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;work&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;worker_config&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;job_address)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;        error!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;});&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Under the hood it uses the job address to communicate with a Server and glues up some requests&lt;&#x2F;p&gt;
&lt;p&gt;Firstly, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;worker.rs#L20-L23&quot;&gt;it creates a dealer socket&lt;&#x2F;a&gt;, setting the identity accordingly:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; send_skt, recv)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; dealer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;set_identity&lt;&#x2F;span&gt;&lt;span&gt;(job_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;as_bytes&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;connect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;job_address)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Multipart&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As ZeroMQ sockets are &lt;code&gt;Send&lt;&#x2F;code&gt; but not &lt;code&gt;Sync&lt;&#x2F;code&gt;, we spin up a background task connected by an &lt;code&gt;unbounded&lt;&#x2F;code&gt; queue which allows the sender to be cloned.  This allows both heartbeats to be sent every 10 seconds from a background task &amp;amp; also send results of processing:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (send,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span&gt; recv_skt)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; unbounded&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ServerMessage&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;tokio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async move&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    while let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(jobq_message)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; recv_skt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Ok&lt;&#x2F;span&gt;&lt;span&gt;(msg)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; jobq_message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_mpart&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(err)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; send_skt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(msg)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;                error!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Error sending message:{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;});&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;worker.rs#L39-L46&quot;&gt;10 second heartbeat&lt;&#x2F;a&gt; is similiarly set up as a separate task:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;tokio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async move&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(err)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ping_sender&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ServerMessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Hello&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            error!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Error:{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;        delay_for&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Duration&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_millis&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;10000&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;});&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is then a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;worker.rs#L48-L75&quot;&gt;big combinator statement&lt;&#x2F;a&gt; which in effect listens for job requests &amp;amp; then runs them in parallel:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;recv&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;filter_map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span&gt; val&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;from)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; serde_cbor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;msg[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;from))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;WorkerMessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Order&lt;&#x2F;span&gt;&lt;span&gt;(job))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(job)),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;WorkerMessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Hello&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            debug!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Pong: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, job_type);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Err&lt;&#x2F;span&gt;&lt;span&gt;(err)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            error!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Error decoding message:{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;job&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;process&lt;&#x2F;span&gt;&lt;span&gt;(job&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;()), send&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(), job))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;for_each_concurrent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;(status,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span&gt; send, job)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; async move&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; server_message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; match&lt;&#x2F;span&gt;&lt;span&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ServerMessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Completed&lt;&#x2F;span&gt;&lt;span&gt;(job),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Err&lt;&#x2F;span&gt;&lt;span&gt;(err)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ServerMessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Failed&lt;&#x2F;span&gt;&lt;span&gt;(job, err&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;()),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(err)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; send&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(server_message)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;        error!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Error sending server message: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is a bit of cloning here that could probably be avoided, but the overhead of cloning a job is not that big.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.4&#x2F;futures&#x2F;stream&#x2F;trait.StreamExt.html#method.for_each_concurrent&quot;&gt;&lt;code&gt;for_each_concurrent&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; allows the worker to run concurrently, and is one of the reasons the trait takes &lt;code&gt;&amp;amp;self&lt;&#x2F;code&gt; rather than &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;All of this is essentially generic on the &lt;code&gt;Worker&lt;&#x2F;code&gt; trait, meaning this plumbing is handled for you when you call &lt;code&gt;work(&amp;amp;address)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;blocking-tasks&quot;&gt;Blocking Tasks&lt;&#x2F;h3&gt;
&lt;p&gt;Some tasks may be blocking, which is a no-no in the async world.  If one of the async worker threads is blocked then it can&#x27;t listen for more events &amp;amp; will slow things down.  Luckily tokio does provide the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;0.2.18&#x2F;tokio&#x2F;task&#x2F;fn.spawn_blocking.html&quot;&gt;&lt;code&gt;spawn_blocking&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; helper for executing blocking work on a dedicated threadpool:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;   tokio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;task&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;spawn_blocking&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; do_blocking_work&lt;&#x2F;span&gt;&lt;span&gt;(job));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;??&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The double &lt;code&gt;.await??&lt;&#x2F;code&gt; is because the &lt;code&gt;JoinHandle&lt;&#x2F;code&gt; returned from &lt;code&gt;spawn_blocking&lt;&#x2F;code&gt; itself could fail and the internal result from the closure could fail.&lt;&#x2F;p&gt;
&lt;p&gt;To control how many threads are used for blocking operations, you need to manually &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;0.2.18&#x2F;tokio&#x2F;runtime&#x2F;struct.Builder.html&quot;&gt;build your tokio run time&lt;&#x2F;a&gt;, rather than use the &lt;code&gt;tokio::main&lt;&#x2F;code&gt; macro.&lt;&#x2F;p&gt;
&lt;p&gt;The the number of blocking threads is &lt;code&gt;max_threads - core_threads&lt;&#x2F;code&gt;.  For instance, if you wanted only 2 dedicated blocking threads:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; rt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tokio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;runtime&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Builder&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;threaded_scheduler&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;enable_all&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;core_threads&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;max_threads&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;the-server-loop&quot;&gt;The Server Loop&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;master&#x2F;src&#x2F;server.rs&quot;&gt;server loop&lt;&#x2F;a&gt; is the main loop responsible for coordinating tasks &amp;amp; otherwise tasks are finished in the order they are supposed to.  The server here responds to messages from the ZeroMQ socket &amp;amp; acts according to the message received.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setup-phase&quot;&gt;Setup Phase&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;server.rs#L26-L36&quot;&gt;setup phase&lt;&#x2F;a&gt; involves setting up a db handle, then querying the database for any outstanding processing jobs.  This is to ensure that they don&#x27;t become stuck as part of a server restart, but can mean that there may be duplicate jobs submitted.  If your jobs provide the same outcome based upon the job at hand this isn&#x27;t a big deal, so the workers should do work that is idempotent if at all possible.&lt;&#x2F;p&gt;
&lt;p&gt;Once that is done, the server keeps an active count of jobs &amp;amp; increments&#x2F;decrements them when jobs finish&#x2F;fail or start.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;main-loop&quot;&gt;Main Loop&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;server.rs#L38-L119&quot;&gt;main loop&lt;&#x2F;a&gt; simply waits until a message is received, and acts accordingly:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;while let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(msg)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; recv&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_next&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; This is the `ROUTER` socket identity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; client_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; = &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;msg[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; This is the message&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; server_msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; serde_cbor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_slice&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ServerMessage&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;msg[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span&gt; server_msg {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;hello-message&quot;&gt;Hello Message&lt;&#x2F;h4&gt;
&lt;p&gt;If a &lt;code&gt;Hello&lt;&#x2F;code&gt; message is received then the server will send any outstanding processing jobs it knows about:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;Drain out existing processing jobs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (jobs, outstanding)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    processing&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;partition&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;job&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; job&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span&gt; name);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;processing&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; outstanding;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; job&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; jobs {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    send_job&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;handle, job,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; send)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;processing&lt;&#x2F;code&gt; vec is only ever populated at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;server.rs#L34&quot;&gt;server start&lt;&#x2F;a&gt;, and so should mostly be empty unless the server was restarted with jobs that were active.&lt;&#x2F;p&gt;
&lt;p&gt;After checking all this it responds back with a &lt;code&gt;Hello&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;job-request&quot;&gt;Job Request&lt;&#x2F;h4&gt;
&lt;p&gt;If a &lt;code&gt;Request&lt;&#x2F;code&gt; message comes in, the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;server.rs#L70&quot;&gt;server adds this to the db&lt;&#x2F;a&gt; &amp;amp; then sends an &lt;code&gt;Acknowledged&lt;&#x2F;code&gt; message &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;server.rs#L84-L91&quot;&gt;back to the client&lt;&#x2F;a&gt; with the populated details.  This doesn&#x27;t yet start the job however, merely it sets the job in a &lt;code&gt;Queued&lt;&#x2F;code&gt; state.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;completed&quot;&gt;Completed&lt;&#x2F;h4&gt;
&lt;p&gt;If a &lt;code&gt;Completed&lt;&#x2F;code&gt; message comes in then the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;server.rs#L93-L97&quot;&gt;server marks it as completed&lt;&#x2F;a&gt; decrementing the active job count.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;failed&quot;&gt;Failed&lt;&#x2F;h4&gt;
&lt;p&gt;If a &lt;code&gt;Failed&lt;&#x2F;code&gt; message comes in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;server.rs#L98-L102&quot;&gt;server will mark the job as failed&lt;&#x2F;a&gt; and submit the reason with it, decrementing the active job count&lt;&#x2F;p&gt;
&lt;h4 id=&quot;error-deserialising&quot;&gt;Error Deserialising&lt;&#x2F;h4&gt;
&lt;p&gt;There is a possibility that a connected client could send an invalid message, so we just log with a &lt;code&gt;warn&lt;&#x2F;code&gt; level in this case, skipping the message:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; server_msg {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ....&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Err&lt;&#x2F;span&gt;&lt;span&gt;(err)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;        warn!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Could not deserialize message:{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, err);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;submit-tasks&quot;&gt;Submit Tasks&lt;&#x2F;h3&gt;
&lt;p&gt;After the main loop matching against the message types, the server checks to see if there are any active slots &amp;amp; if so, queries the database for any queued jobs:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; If we have less active tasks lets check the queued stuff&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; active&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;num {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; jobs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; handle&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;get_queued_jobs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;num &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; active&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; job&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; jobs {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;        send_job&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;handle, job,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; send)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        active&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; active&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After this processing, the server then waits again for the next message.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;database-persistence&quot;&gt;Database Persistence&lt;&#x2F;h2&gt;
&lt;p&gt;One of the requirements is ensuring that jobs stay around and are persisted somewhere.   The prototype uses &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.postgresql.org&#x2F;&quot;&gt;PostgreSQL&lt;&#x2F;a&gt; to do this.&lt;&#x2F;p&gt;
&lt;p&gt;As this is async, we&#x27;ll use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;tokio-postgres&quot;&gt;tokio-postgres&lt;&#x2F;a&gt; to perform updates.  tokio postgres has some &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio-postgres&#x2F;0.5.3&#x2F;tokio_postgres&#x2F;&quot;&gt;nice docs&lt;&#x2F;a&gt; to get us started, so we will use their example to build a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;a09ebcaff164c2153cdceba0031dbfb7caa1ea3b&#x2F;src&#x2F;db.rs&quot;&gt;database handler&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tokio_postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;NoTls&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[tokio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;main]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; By default, tokio_postgres uses the tokio crate as its runtime.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Connect to the database.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; (client, connection)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        tokio_postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;connect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;host=localhost user=postgres&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NoTls&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; The connection object performs the actual communication with the database,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; so spawn it off to run on its own.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    tokio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async move&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(e)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            eprintln!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;connection error: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Now we can execute a simple statement that just returns its parameter.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; rows&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;query&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;SELECT $1::TEXT&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;hello world&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; And then check that we got back the same string we sent over.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; rows[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(value,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;hello world&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;enums-and-postgres-types&quot;&gt;Enums and Postgres Types&lt;&#x2F;h3&gt;
&lt;p&gt;You can use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;postgres-types&quot;&gt;&lt;code&gt;postgres_types&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate to save simple enums to a table.&lt;&#x2F;p&gt;
&lt;p&gt;So the &lt;code&gt;Priority&lt;&#x2F;code&gt; struct can be persisted to the db like so:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;CREATE TYPE&lt;&#x2F;span&gt;&lt;span&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Priority&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; enum (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;#39;High&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;#39;Normal&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;#39;Low&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;a-simple-migration&quot;&gt;A Simple Migration&lt;&#x2F;h3&gt;
&lt;p&gt;Hopefully our schema never changes.. Right?&lt;&#x2F;p&gt;
&lt;p&gt;Well, in the prototype it won&#x27;t. So we can simply embed an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;master&#x2F;src&#x2F;setup.sql&quot;&gt;SQL script&lt;&#x2F;a&gt; to run when the a db handler &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;a09ebcaff164c2153cdceba0031dbfb7caa1ea3b&#x2F;src&#x2F;db.rs#L13-L27&quot;&gt;starts up&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DbHandle&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Arc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DbHandle&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;(url&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; (client, connection)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tokio_postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;connect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;url,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; NoTls&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        tokio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async move&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(e)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; connection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;                error!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;connection error: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;batch_execute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;include_str!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;setup.sql&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;DbHandle&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Arc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(client),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This &lt;code&gt;setup.sql&lt;&#x2F;code&gt; script should be designed to run more than once, but skip the parts that it&#x27;s already done.  There are a couple tricks to do this, but obviously doesn&#x27;t work if you are adding&#x2F;removing columns from a table etc..&lt;&#x2F;p&gt;
&lt;p&gt;For the enum types, you can just check the &lt;code&gt;pg_type&lt;&#x2F;code&gt; to make sure that they exist &amp;amp; if not add them:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;IF NOT EXISTS&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; FROM&lt;&#x2F;span&gt;&lt;span&gt; pg_type &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; typname &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;#39;Status&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;THEN&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    CREATE TYPE&lt;&#x2F;span&gt;&lt;span&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Status&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; enum (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;#39;Queued&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;#39;Processing&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;#39;Completed&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;#39;Failed&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;END IF&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the table &amp;amp; indexes you can do a &lt;code&gt;CREATE &amp;lt;blah&amp;gt; IF NOT EXISTS&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;CREATE INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; IF&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; NOT EXISTS&lt;&#x2F;span&gt;&lt;span&gt; status_idx &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;ON&lt;&#x2F;span&gt;&lt;span&gt; jobq (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This won&#x27;t error out if the index&#x2F;table already exists, meaning you&#x27;re safe to run the &lt;code&gt;setup.sql&lt;&#x2F;code&gt; multiple times!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;getting-jobs-from-the-db&quot;&gt;Getting jobs from the DB&lt;&#x2F;h3&gt;
&lt;p&gt;Querying for jobs is quite simple, you just select the columns you want and do a &lt;code&gt;get()&lt;&#x2F;code&gt; or &lt;code&gt;try_get()&lt;&#x2F;code&gt; on them:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DbHandle&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ....&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_queued_jobs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, num&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; query&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;select &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                        id,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                        name,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                        username,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                        uuid,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                        params,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                        priority,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                        status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                     from jobq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                     where &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                        status = &amp;#39;Queued&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                     order by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                     priority asc, time asc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                     limit $1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let mut&lt;&#x2F;span&gt;&lt;span&gt; jobs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; result {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; username&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; uuid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; params&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; priority&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;try_get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            jobs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;                Job&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    id,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    username,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    name,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    uuid,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    params,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    priority,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    status,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(jobs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are a number of other methods as &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;db.rs#L29&quot;&gt;complete_job&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;db.rs#L37&quot;&gt;fail_job&lt;&#x2F;a&gt; that handle the SQL stuff &amp;amp; make it simple for the Server to use.&lt;&#x2F;p&gt;
&lt;p&gt;Keeping things persisted in the database means we can use standard SQL tools to introspect the job queue and see where it&#x27;s at.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;recording-the-job-duration&quot;&gt;Recording the job duration&lt;&#x2F;h3&gt;
&lt;p&gt;The duration of the job is recorded when the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;jobq&#x2F;blob&#x2F;2028ea12388bd077056d984016ecf46c88e6626c&#x2F;src&#x2F;db.rs#L29-L35&quot;&gt;job is finished&#x2F;failed&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; complete_job&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; query&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;update jobq set status = &amp;#39;Completed&amp;#39;, duration = extract(epoch from now() - &lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;) where id = $1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;    self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;query&lt;&#x2F;span&gt;&lt;span&gt;(query,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;id])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This could&#x27;ve been done inside rust as well using &lt;code&gt;Instant&lt;&#x2F;code&gt; but would require a bit more state to be handled in the Server.  I&#x27;ve elected here to use a PostgreSQL solution instead to lean on the db.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;running-the-example&quot;&gt;Running the example&lt;&#x2F;h2&gt;
&lt;p&gt;The example starts the test worker, a server and a client to submit 500 simple jobs:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;500&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; priority&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; if&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Priority&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;High&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Priority&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Normal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; job&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; JobRequest&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;test&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        username&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;test_client&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        params&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Null&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        uuid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Uuid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new_v4&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        priority,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    send&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ServerMessage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Request&lt;&#x2F;span&gt;&lt;span&gt;(job)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_mpart&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Running with &lt;code&gt;cargo run&lt;&#x2F;code&gt; you will see the output after some time, with the simulated failures:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;log&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;2020-04-14 16:04:33&lt;&#x2F;span&gt;&lt;span style=&quot;color: #80BFFF;&quot;&gt; DEBUG&lt;&#x2F;span&gt;&lt;span&gt; jobq         &amp;gt; Message:Acknowledged(Job { id: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;2999&lt;&#x2F;span&gt;&lt;span&gt;, username: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;test_client&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;test&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, uuid: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;fe6e21fc-8064-4c9a-965d-b1d124f2416d&lt;&#x2F;span&gt;&lt;span&gt;, params: Null, priority: High, status: Queued })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;2020-04-14 16:04:33&lt;&#x2F;span&gt;&lt;span style=&quot;color: #80BFFF;&quot;&gt; DEBUG&lt;&#x2F;span&gt;&lt;span&gt; jobq::server &amp;gt; New: Job { id: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;3000&lt;&#x2F;span&gt;&lt;span&gt;, username: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;test_client&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;test&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, uuid: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;d20b4e9b-477b-45ca-9a6a-1f6423378779&lt;&#x2F;span&gt;&lt;span&gt;, params: Null, priority: Normal, status: Queued }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;2020-04-14 16:04:33&lt;&#x2F;span&gt;&lt;span style=&quot;color: #80BFFF;&quot;&gt; DEBUG&lt;&#x2F;span&gt;&lt;span&gt; jobq         &amp;gt; Message:Acknowledged(Job { id: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;3000&lt;&#x2F;span&gt;&lt;span&gt;, username: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;test_client&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;test&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, uuid: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;d20b4e9b-477b-45ca-9a6a-1f6423378779&lt;&#x2F;span&gt;&lt;span&gt;, params: Null, priority: Normal, status: Queued })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;2020-04-14 16:04:39&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F27983;&quot;&gt; WARN&lt;&#x2F;span&gt;&lt;span&gt;  jobq::server &amp;gt; Job failed: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;3000&lt;&#x2F;span&gt;&lt;span&gt;, Reason: Simulating failure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;2020-04-14 16:04:39&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F27983;&quot;&gt; WARN&lt;&#x2F;span&gt;&lt;span&gt;  jobq::server &amp;gt; Job failed: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;2988&lt;&#x2F;span&gt;&lt;span&gt;, Reason: Simulating failure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;2020-04-14 16:04:39&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F27983;&quot;&gt; WARN&lt;&#x2F;span&gt;&lt;span&gt;  jobq::server &amp;gt; Job failed: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;2976&lt;&#x2F;span&gt;&lt;span&gt;, Reason: Simulating failure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can also run some simple stats directly against the db to see how long things have taken (hopefully ~100ms):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;select&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F28779;&quot;&gt; avg&lt;&#x2F;span&gt;&lt;span&gt;(duration) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; jobq;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    avg     &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;10634147&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; row&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;&#x2F;h2&gt;
&lt;p&gt;I hope for anyone new that this article will help dip their feet into the waters of rust and async to see what can be built.&lt;&#x2F;p&gt;
&lt;p&gt;Taking a few libraries and gluing them together we can get a pretty decent, albeit rough, outline of a background job queue.  The new &lt;code&gt;async&#x2F;await&lt;&#x2F;code&gt; ecosystem while embryonic already has the tools there to build some cool stuff.&lt;&#x2F;p&gt;
&lt;p&gt;There will be a separate article around the release of &lt;code&gt;tmq&lt;&#x2F;code&gt; version &lt;code&gt;0.2.0&lt;&#x2F;code&gt; and some of the changes that have been made, but thought it might be great to provide a good example of working code before getting aroudn to that.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Handling Breaking API Changes</title>
          <pubDate>Mon, 03 Feb 2020 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/breaking-api-changes/</link>
          <guid>https://cetra3.github.io/blog/breaking-api-changes/</guid>
          <description xml:base="https://cetra3.github.io/blog/breaking-api-changes/">&lt;p&gt;While upgrading dependencies (basically deleting &lt;code&gt;Cargo.lock&lt;&#x2F;code&gt;) in a big rust project I hit an issue.  A &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;serde-rs&#x2F;json&#x2F;commit&#x2F;97f87f2587037dcd50b9504815ee1f1540b1c2b8&quot;&gt;new commit&lt;&#x2F;a&gt; in &lt;code&gt;serde_json&lt;&#x2F;code&gt; caused has upstream failure in another library, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mtdowling&#x2F;jmespath.rs&#x2F;issues&#x2F;33&quot;&gt;jmespath&lt;&#x2F;a&gt;, and possibly more crates. Because these structs and enums visibility has changed, this could be interpreted as a breaking change, depending on what you consider &lt;em&gt;public&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;While &lt;code&gt;jmespath&lt;&#x2F;code&gt; was doing the wrong thing here, using undocumented API, it got me thinking about what can library maintainers and library consumers do to ensure semver compatibility, and what tools are out there to assist both groups.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-semantic-versioning&quot;&gt;What is Semantic Versioning&lt;&#x2F;h2&gt;
&lt;p&gt;Semantic versioning (semver) is one standard used for version numbers which appears to have gained the most traction.   Since cargo and friends use semver to identify what versions to use, it is important to understand (excuse my pun) the semantics of what this means.&lt;&#x2F;p&gt;
&lt;p&gt;The full documentation of semver is on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;semver.org&#x2F;&quot;&gt;https:&#x2F;&#x2F;semver.org&#x2F;&lt;&#x2F;a&gt;, but for brevity there are 3 numbers:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Major: Any breaking API changes&lt;&#x2F;li&gt;
&lt;li&gt;Minor: Additions of new features or functionality that are backwards compatible&lt;&#x2F;li&gt;
&lt;li&gt;Patch: Bugfixes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There is some interesting differences for libraries &lt;code&gt;&amp;lt; 1.0.0&lt;&#x2F;code&gt; which I was not aware of for longer than I care to admit.  Namely either minor or patch numbers can be changes as you see fit.  I.e, &lt;code&gt;0.3.0&lt;&#x2F;code&gt; could be wildly different from &lt;code&gt;0.3.1&lt;&#x2F;code&gt;, including breaking changes.&lt;&#x2F;p&gt;
&lt;p&gt;However: Cargo is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;reference&#x2F;specifying-dependencies.html&quot;&gt;more strict&lt;&#x2F;a&gt; than the semver documentation for &lt;code&gt;&amp;lt; 1.0.0&lt;&#x2F;code&gt; libraries:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This compatibility convention is different from SemVer in the way it treats versions before 1.0.0. While SemVer says there is no compatibility before 1.0.0, Cargo considers &lt;code&gt;0.x.y&lt;&#x2F;code&gt; to be compatible with &lt;code&gt;0.x.z&lt;&#x2F;code&gt;, where &lt;code&gt;y ≥ z&lt;&#x2F;code&gt; and &lt;code&gt;x &amp;gt; 0&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;why-we-need-it&quot;&gt;Why we need it&lt;&#x2F;h2&gt;
&lt;p&gt;We need some way of portraying changes to an API and, while it&#x27;s not perfect, it appears to be a defacto standard which makes interoperability with other libraries and crates a lot easier.&lt;&#x2F;p&gt;
&lt;p&gt;It also gives cargo a programmatic way of finding updated versions, when it&#x27;s used appropriately.&lt;&#x2F;p&gt;
&lt;p&gt;So it is one part advertising the intent of the version and another part ensuring that things will compile if you bump up certain numbers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;api-evolution-rfc&quot;&gt;API Evolution RFC&lt;&#x2F;h2&gt;
&lt;p&gt;The Semver website is very general in its language and isn&#x27;t specific to rust.  There is, however, a great RFC that has some excellent guidelines both for the language itself &amp;amp; for library maintainers: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;1105-api-evolution.md&quot;&gt;RFC 1105: API Evolution&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here are a couple of excerpts:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;h4 id=&quot;major-change-going-from-stable-to-nightly&quot;&gt;Major change: going from stable to nightly&lt;&#x2F;h4&gt;
&lt;p&gt;Changing a crate from working on stable Rust to &lt;em&gt;requiring&lt;&#x2F;em&gt; a nightly is
considered a breaking change. That includes using &lt;code&gt;#[feature]&lt;&#x2F;code&gt; directly, or
using a dependency that does so. Crate authors should consider using Cargo
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;doc.crates.io&#x2F;manifest.html#the-%5Bfeatures%5D-section&quot;&gt;&quot;features&quot;&lt;&#x2F;a&gt; for
their crate to make such use opt-in.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;h4 id=&quot;major-change-renaming-moving-removing-any-public-items&quot;&gt;Major change: renaming&#x2F;moving&#x2F;removing any public items.&lt;&#x2F;h4&gt;
&lt;p&gt;Although renaming an item might seem like a minor change, according to the
general policy design this is not a permitted form of breakage: it&#x27;s not
possible to annotate code in advance to avoid the breakage, nor is it possible
to prevent the breakage from affecting dependencies.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This RFC has some great advice, and I wish it was more publicly known, but seems relatively obscure.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-non-exhaustive-attribute&quot;&gt;The Non-Exhaustive Attribute&lt;&#x2F;h2&gt;
&lt;p&gt;Another RFC related to versioning is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;2008-non-exhaustive.md&quot;&gt;Non-Exhaustive&lt;&#x2F;a&gt;, which is a handy way of planning breaking changes ahead of time.  It works with enums by forcing open ended &lt;code&gt;match&lt;&#x2F;code&gt; statements, which means consumers of your enum won&#x27;t break if a new variant is introducted. It also works with structs and ensures users consuming libraries can&#x27;t create them.&lt;&#x2F;p&gt;
&lt;p&gt;This was recently &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2019&#x2F;12&#x2F;19&#x2F;Rust-1.40.0.html&quot;&gt;stabilised in Rust 1.40&lt;&#x2F;a&gt; so it&#x27;s a rather new feature of the language (on a side note: it&#x27;s not easy to find when a particular RFC is stabilised, it would be great to have this reflected in the RFC somewhere).&lt;&#x2F;p&gt;
&lt;p&gt;As an example if you have an enum like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[non_exhaustive]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Other&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You would need to &lt;code&gt;match&lt;&#x2F;code&gt; against the enum like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; error {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;ref&lt;&#x2F;span&gt;&lt;span&gt; s)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt; ...&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Other&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt; ...&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    _&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&amp;gt; ...&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Your library could then introduce a new variant, which wouldn&#x27;t break the existing consumer:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[non_exhaustive]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    Message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    IOError&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Other&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;other-tools&quot;&gt;Other Tools&lt;&#x2F;h2&gt;
&lt;p&gt;There have been some tools to both manage breaking changes in the past, a lot of the things I found were unmaintained or not in active use.  There might also be some great language features that I haven&#x27;t discovered yet that crate authors are already using.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-semver-trick&quot;&gt;The Semver Trick&lt;&#x2F;h3&gt;
&lt;p&gt;Documented here is the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dtolnay&#x2F;semver-trick&quot;&gt;semver trick&lt;&#x2F;a&gt;, which touts to be able to assist in this with downstream dependencies.&lt;&#x2F;p&gt;
&lt;p&gt;There is mention of a &lt;code&gt;libcpocalypse&lt;&#x2F;code&gt;, which does not sound nice and may happen again if there is a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;libc&#x2F;issues&#x2F;547&quot;&gt;major version increase&lt;&#x2F;a&gt; to &lt;code&gt;libc&lt;&#x2F;code&gt;.  I tried to find some information about where this had happened before but searching for the term circles back to this project and doesn&#x27;t give a great overview of the pains users had to go through before.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rust-semverver&quot;&gt;Rust Semverver&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-dev-tools&#x2F;rust-semverver&quot;&gt;rust-semverver&lt;&#x2F;a&gt; is a Google Summer of Code Project which checks semver compliance with rust crates by using a novel approach:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The approach taken is to compile both versions of the crate to rlibs and to link them as dependencies of a third, empty, dummy crate. Then, a custom compiler driver is run on the said dummy and all necessary analysis is performed in that context, where type information and other resources are available.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;semantic-rs&quot;&gt;Semantic-RS&lt;&#x2F;h3&gt;
&lt;p&gt;An existing tool called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;semantic-rs&#x2F;semantic-rs&quot;&gt;semantic-rs&lt;&#x2F;a&gt; touts to be able to do this for your crates automatically.  This doesn&#x27;t appear to have any changes for over a year, but does have an active issue register, but no PRs have been accepted for a while.  It is highly opinionated as well, and may not be appropriate to bolt on to an existing library.  This looks like something you need to use from the beginning as well.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rust-breaking-changes&quot;&gt;Rust Breaking Changes&lt;&#x2F;h3&gt;
&lt;p&gt;This also doesn&#x27;t appear to be maintained, but was an automatic listing of breaking changes to rust: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;killercup.github.io&#x2F;bitrust&#x2F;&quot;&gt;https:&#x2F;&#x2F;killercup.github.io&#x2F;bitrust&#x2F;&lt;&#x2F;a&gt;.   I do wonder though how many of those changes are internal, as I don&#x27;t believe there have been many external breaking changes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;future-proofing&quot;&gt;Future Proofing&lt;&#x2F;h3&gt;
&lt;p&gt;There is a chapter of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;api-guidelines&#x2F;about.html&quot;&gt;Rust API Guidelines&lt;&#x2F;a&gt; which deals with how to future proof an API, but as with other tools I have found does not appear to be updated in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;api-guidelines&#x2F;commits&#x2F;master&#x2F;src&#x2F;future-proofing.md&quot;&gt;quite a while&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Future Proofing&lt;&#x2F;strong&gt;: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;api-guidelines&#x2F;future-proofing.html&quot;&gt;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;api-guidelines&#x2F;future-proofing.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;While there has been a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2018&#x2F;03&#x2F;12&#x2F;roadmap.html#library-improvements&quot;&gt;historic push to get crates to 1.0.0&lt;&#x2F;a&gt;, There does not appear to be much in the way of modern tooling in order to help with this and the focus of previous efforts see them moving elsewhere.&lt;&#x2F;p&gt;
&lt;p&gt;With more libraries reaching &lt;code&gt;1.0.0&lt;&#x2F;code&gt; I think it&#x27;s important to introduce more safety nets for library authors and consumers.  As an idea, we can potentially see whether a crate has breaking change through lints etc.. so why don&#x27;t we do that when we publish to crates.io?&lt;&#x2F;p&gt;
&lt;p&gt;There is a lot of room for improvement here, and as new users come on board and new companies look at adopting, it&#x27;s important that the stability of semver is maintained.  I still think the way that cargo handles this is much better than other ecosystems.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Lessons learnt updating a library to std::future</title>
          <pubDate>Wed, 22 Jan 2020 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/mpart-async-0-3-0/</link>
          <guid>https://cetra3.github.io/blog/mpart-async-0-3-0/</guid>
          <description xml:base="https://cetra3.github.io/blog/mpart-async-0-3-0/">&lt;p&gt;With the new &lt;code&gt;std::future&lt;&#x2F;code&gt; way of doing things and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tokio.rs&quot;&gt;tokio&lt;&#x2F;a&gt; slowly reaching maturation, it&#x27;s time to look at updating the libraries out there that are using &lt;em&gt;the old ways&lt;&#x2F;em&gt;.  For one of my libraries, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;tmq&quot;&gt;tmq&lt;&#x2F;a&gt;, a Tokio ZeroMQ library, there is some &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;tmq&#x2F;pull&#x2F;5&quot;&gt;awesome work already done&lt;&#x2F;a&gt; to get this updated.&lt;&#x2F;p&gt;
&lt;p&gt;But, I thought it pertinent to at least get my feet in the water to see how hard it would be, from a library maintainer perspective, to update to &lt;code&gt;std::future&lt;&#x2F;code&gt;.  For this effort, I chose my small library: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;mpart-async&quot;&gt;mpart-async&lt;&#x2F;a&gt;.   You can see the changes I have made by comparing the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;mpart-async&#x2F;compare&#x2F;0.2.1...0.3.0&quot;&gt;versions&lt;&#x2F;a&gt; here.  This blog is a small collection of notes &amp;amp; gotches I found when porting code across.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;mpart-async&lt;&#x2F;code&gt; is a &lt;em&gt;mostly&lt;&#x2F;em&gt; agnostic library for client side &lt;code&gt;multipart&#x2F;form-data&lt;&#x2F;code&gt; requests.  There are existing libraries out there, like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;multipart&quot;&gt;multipart&lt;&#x2F;a&gt;, but I found the API a little unwieldy for my taste (That: and async support is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;abonander&#x2F;multipart-async&quot;&gt;still in alpha&lt;&#x2F;a&gt; according to the readme). I wanted something that worked, and was simple, but didn&#x27;t offer an opinion on the web client. I use both the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;actix&#x2F;actix-web&#x2F;tree&#x2F;master&#x2F;awc&quot;&gt;actix client&lt;&#x2F;a&gt; &amp;amp;  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;hyper&quot;&gt;hyper&lt;&#x2F;a&gt; to make multipart requests depending on the project.&lt;&#x2F;p&gt;
&lt;p&gt;The challenge is that with multipart requests you mostly have fields &amp;amp; binary files.  For binary files, you can appreciate, should not be buffered entirely in memory, but streamed out as the bytes become available.  So &lt;code&gt;mpart-async&lt;&#x2F;code&gt; works with multiple internal streams of files and also provides a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;mpart-async&#x2F;blob&#x2F;981ba0437e19fa47f94a913cf9aaa4717fbe12bc&#x2F;src&#x2F;filestream.rs&quot;&gt;convenience wrapper&lt;&#x2F;a&gt; (if using tokio) for sending files given a path.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-new-example&quot;&gt;A New Example&lt;&#x2F;h2&gt;
&lt;p&gt;All these changes to support &lt;code&gt;async fn&lt;&#x2F;code&gt; and is it actually easier to consume&#x2F;use async libraries?&lt;&#x2F;p&gt;
&lt;p&gt;Given the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;hyper&quot;&gt;hyper&lt;&#x2F;a&gt; example, I would say yes.&lt;&#x2F;p&gt;
&lt;p&gt;Compare the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;mpart-async&#x2F;blob&#x2F;981ba0437e19fa47f94a913cf9aaa4717fbe12bc&#x2F;examples&#x2F;hyper.rs&quot;&gt;new example&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[tokio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;main]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Setup a mock server to accept connections.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;....&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span&gt; mpart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; MultipartRequest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mpart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_field&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mpart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_file&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;test&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Cargo.toml&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; request&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Request&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;http:&#x2F;&#x2F;localhost:3000&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;header&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;            CONTENT_TYPE&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;multipart&#x2F;form-data; boundary={}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, mpart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;get_boundary&lt;&#x2F;span&gt;&lt;span&gt;()),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;body&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Body&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;wrap_stream&lt;&#x2F;span&gt;&lt;span&gt;(mpart))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;request&lt;&#x2F;span&gt;&lt;span&gt;(request)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;mpart-async&#x2F;blob&#x2F;c928f015fa31cd57533d4ba43551a9a96b61b0a2&#x2F;examples&#x2F;hyper.rs&quot;&gt;older one&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; current_thread::Runtime can&amp;#39;t be used because of the blocking file operations&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span&gt; rt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Runtime&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;new rt&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Setup a mock server to accept connections.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;....&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Open `Cargo.toml` file and create a request&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; request&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; File&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Cargo.toml&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;            &#x2F;&#x2F; A Stream of BytesMut decoded from an AsyncRead&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; framed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; FramedRead&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(file,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BytesCodec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let mut&lt;&#x2F;span&gt;&lt;span&gt; mpart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; MultipartRequest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            mpart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_field&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            mpart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_stream&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                &amp;quot;foofile&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                &amp;quot;Cargo.toml&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;                &amp;quot;application&#x2F;toml&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                framed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;freeze&lt;&#x2F;span&gt;&lt;span&gt;()),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            Request&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;http:&#x2F;&#x2F;localhost:3000&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;header&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;                    CONTENT_TYPE&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;                    format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;multipart&#x2F;form-data; boundary={}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, mpart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;get_boundary&lt;&#x2F;span&gt;&lt;span&gt;()),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                )&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;body&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Body&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;wrap_stream&lt;&#x2F;span&gt;&lt;span&gt;(mpart))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Send request&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; task&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; request&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;request&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; hyper&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;request&lt;&#x2F;span&gt;&lt;span&gt;(request)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;response&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                response&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into_body&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;concat2&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;                        if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Ok&lt;&#x2F;span&gt;&lt;span&gt;(data)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_utf8&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;body) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;                            println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Response: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, data);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;                        Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    rt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;(task)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;request failed&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While there are still a few warts (such as having to manually add the boundary header), I find the code a lot more readable and easy to follow, rather than your standard combinator paths.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;no-more-error-associated-type&quot;&gt;No more &lt;code&gt;Error&lt;&#x2F;code&gt; Associated Type&lt;&#x2F;h2&gt;
&lt;p&gt;The most drastic change to the &lt;code&gt;Stream&lt;&#x2F;code&gt; trait is that there is no longer an &lt;code&gt;Error&lt;&#x2F;code&gt; associated type.  The old &lt;code&gt;Stream&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Future&lt;&#x2F;code&gt; traits had both &lt;code&gt;Item&lt;&#x2F;code&gt; and &lt;code&gt;Error&lt;&#x2F;code&gt;, as it assumed that streams were always going to be fallible.  The new traits do away with the &lt;code&gt;Error&lt;&#x2F;code&gt; associated type.  Instead, if you want your &lt;code&gt;Stream&lt;&#x2F;code&gt; to possibly be an error then you need to return a &lt;code&gt;Result&lt;&#x2F;code&gt; as your &lt;code&gt;Item&lt;&#x2F;code&gt; type.&lt;&#x2F;p&gt;
&lt;p&gt;For the &lt;code&gt;Stream&lt;&#x2F;code&gt; trait, the method you implement has changed to &lt;code&gt;poll_next&lt;&#x2F;code&gt; and uses the &lt;code&gt;std::task::Poll&lt;&#x2F;code&gt; enum as a return type.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;Poll&lt;&#x2F;code&gt; enum did feel a little inside out when I started using it, but makes sense in terms of there being no &lt;code&gt;Error&lt;&#x2F;code&gt; type.  You don&#x27;t return a &lt;code&gt;Result&amp;lt;Async&amp;lt;Option&amp;gt;, _&amp;gt;...&lt;&#x2F;code&gt; you instead return a &lt;code&gt;Poll&amp;lt;Option&amp;lt;Result&amp;lt;_,_&amp;gt;&amp;gt;&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Generally, this means if you wrote this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Async&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(bytes)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You instead will return:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Poll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;Ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(bytes)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;streamext-traits-and-friends&quot;&gt;&lt;code&gt;StreamExt&lt;&#x2F;code&gt; traits and friends&lt;&#x2F;h2&gt;
&lt;p&gt;As a consequence of no &lt;code&gt;Error&lt;&#x2F;code&gt; associated type, and an example of different ergonomics, if you are dealing with &lt;code&gt;Result&lt;&#x2F;code&gt; items, you may want to use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.1&#x2F;futures&#x2F;stream&#x2F;trait.TryStreamExt.html&quot;&gt;TryStreamExt&lt;&#x2F;a&gt; trait instead of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.1&#x2F;futures&#x2F;stream&#x2F;trait.StreamExt.html&quot;&gt;StreamExt&lt;&#x2F;a&gt;.  They are basically the same trait but one deals with &lt;code&gt;Result&lt;&#x2F;code&gt; a bit more nicely.  I&#x27;m not sure whether a simpler solution will be possible with higher kinded types in the future, but for now it is a tiny bit more complex than futures 0.1.&lt;&#x2F;p&gt;
&lt;p&gt;Interestingly, the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.1&#x2F;futures&#x2F;stream&#x2F;index.html&quot;&gt;index page&lt;&#x2F;a&gt; for stream docs doesn&#x27;t currently mention that the &lt;code&gt;TryStreamExt&lt;&#x2F;code&gt; trait exists &amp;amp; I only found out about it by asking questions in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;discord.gg&#x2F;tokio&quot;&gt;discord chat&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But wait, there is also &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;0.2.10&#x2F;tokio&#x2F;stream&#x2F;trait.StreamExt.html&quot;&gt;StreamExt&lt;&#x2F;a&gt; from tokio  which is subtly different, but does as of &lt;code&gt;0.2.10&lt;&#x2F;code&gt; allow you to run &lt;code&gt;collect()&lt;&#x2F;code&gt; on &lt;code&gt;Result&amp;lt;Bytes, _&amp;gt;&lt;&#x2F;code&gt; item streams.&lt;&#x2F;p&gt;
&lt;p&gt;When would you use either &lt;code&gt;StreamExt&lt;&#x2F;code&gt;?  I would say that if you want to be more general, you should probably use the &lt;code&gt;futures&lt;&#x2F;code&gt;  implementation.  Bearing in mind you can&#x27;t run &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.1&#x2F;futures&#x2F;stream&#x2F;trait.TryStreamExt.html#method.try_collect&quot;&gt;&lt;code&gt;try_collect()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; on &lt;code&gt;Result&amp;lt;Bytes, _&amp;gt;&lt;&#x2F;code&gt; at the moment due to an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;bytes&#x2F;issues&#x2F;324&quot;&gt;outstanding issue&lt;&#x2F;a&gt; with the bytes crate.  Why does this matter? Well, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hyper.rs&#x2F;&quot;&gt;hyper&lt;&#x2F;a&gt; passes around streams of &lt;code&gt;Result&amp;lt;Bytes, _&amp;gt;&lt;&#x2F;code&gt; when you are streaming a body in &amp;amp; out of a request.  Working with this particular stream signature is a bit clunky still, but I&#x27;m sure that this will be resolved in due course.&lt;&#x2F;p&gt;
&lt;p&gt;So we have:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;StreamExt&lt;&#x2F;code&gt; from &lt;code&gt;futures&lt;&#x2F;code&gt; that works on &lt;code&gt;Stream&lt;&#x2F;code&gt; that aren&#x27;t &lt;code&gt;Result&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;TryStreamExt&lt;&#x2F;code&gt; from &lt;code&gt;futures&lt;&#x2F;code&gt; that works on &lt;code&gt;Stream&lt;&#x2F;code&gt; that are &lt;code&gt;Result&lt;&#x2F;code&gt; but doesn&#x27;t work well with &lt;code&gt;Result&amp;lt;Bytes,_&amp;gt;&lt;&#x2F;code&gt; when trying to &lt;code&gt;try_collect()&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;StreamExt&lt;&#x2F;code&gt; from &lt;code&gt;tokio&lt;&#x2F;code&gt; that works with &lt;code&gt;Result&amp;lt;Bytes,_&amp;gt;&lt;&#x2F;code&gt; and allows you to &lt;code&gt;collect()&lt;&#x2F;code&gt; to get the output but now means you have a dependency on &lt;code&gt;tokio&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This might end up confusing more than just me, and I do hope that it&#x27;s simplified in the future.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily in the core of the API I don&#x27;t need to use them, only for tests &amp;amp; filestream, which means I&#x27;m quite happy to depend on the &lt;code&gt;tokio&lt;&#x2F;code&gt; implementation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapping-inner-streams-in-pin&quot;&gt;Wrapping inner streams in &lt;code&gt;Pin&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I got tripped up on this for a while, and needed to again ask in chat for the answer here. If you have an inner stream and you want to call &lt;code&gt;poll_next&lt;&#x2F;code&gt; on it, you need to wrap it in a &lt;code&gt;Pin&lt;&#x2F;code&gt;, otherwise the &lt;code&gt;Stream&lt;&#x2F;code&gt; trait does not stick and you will get some gnarly error message with some weird suggestions:&lt;&#x2F;p&gt;
&lt;p&gt;The my original shot at the code was:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;poll_next&lt;&#x2F;span&gt;&lt;span&gt;(cx)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But it needs to be:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Pin&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stream)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;poll_next&lt;&#x2F;span&gt;&lt;span&gt;(cx)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The compiler error message is not too helpful here, and insists I restrict &lt;code&gt;S&lt;&#x2F;code&gt; by &lt;code&gt;Stream&lt;&#x2F;code&gt;, even though it is already restricted by &lt;code&gt;Stream&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;error[E0599]: no method named `poll_next` found for type `S` in the current scope&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   --&amp;gt; src&#x2F;lib.rs:282:41&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;282 |                     match stream.stream.poll_next(cx) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                                         ^^^^^^^^^ method not found in `S`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    = help: items from traits can only be used if the type parameter is bounded by the trait&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;help: the following trait defines an item `poll_next`, perhaps you need to restrict type parameter `S` with it:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;254 | impl&amp;lt;E, S: futures::Stream + Stream&amp;gt; Stream for MultipartRequest&amp;lt;S&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |         ^^^^^^^^^^^^^^^^^^^^&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You need to make sure that your inner stream implements &lt;code&gt;Unpin&lt;&#x2F;code&gt; as well to go down this path:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;E&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; MultipartRequest&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;S&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    S&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Stream&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Bytes&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; E&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Unpin&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;storing-the-results-from-an-async-fn-in-a-struct&quot;&gt;Storing the results from an &lt;code&gt;async fn&lt;&#x2F;code&gt; in a struct&lt;&#x2F;h2&gt;
&lt;p&gt;Some of the methods in tokio are returns from an &lt;code&gt;async fn&lt;&#x2F;code&gt; , like the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;0.2.10&#x2F;tokio&#x2F;fs&#x2F;struct.File.html#method.open&quot;&gt;File::open&lt;&#x2F;a&gt; method, which I use for &lt;code&gt;FileStream&lt;&#x2F;code&gt;.  I found the answer on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;58354633&#x2F;cannot-use-impl-future-to-store-async-function-in-a-vector&quot;&gt;stack overflow&lt;&#x2F;a&gt; as to how to do this with &lt;code&gt;std::future&lt;&#x2F;code&gt;, since &lt;code&gt;async fn&lt;&#x2F;code&gt; returns an opaque type.&lt;&#x2F;p&gt;
&lt;p&gt;For the older version, the OpenFuture was a concrete type:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; FileStream&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    inner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FramedRead&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;File&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BytesCodec&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; OpenFuture&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;PathBuf&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The newer version is a return from an &lt;code&gt;async fn&lt;&#x2F;code&gt; and is opaque, so we wrap it using &lt;code&gt;Box::pin&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; FileStream&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    inner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FramedRead&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;File&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BytesCodec&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Pin&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Output&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;File&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Send&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Sync&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can then instantiate this with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;pin&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;File&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;()))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then it&#x27;s easy to call passing on the context from an existing &lt;code&gt;poll()&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(cx)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;notifying-a-task&quot;&gt;Notifying a task&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;FileStream&lt;&#x2F;code&gt; has two stages.  One is the future to open the file. The second is streaming out the bytes of the file.  When the future resolves to open the file, I want to notify the context that it should be polled again to start streaming.&lt;&#x2F;p&gt;
&lt;p&gt;The old way of doing this was &lt;code&gt;task::current().notify()&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;inner &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FramedRead&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(file,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BytesCodec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;task&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;current&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;notify&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The new way appears to be using  &lt;code&gt;cx.waker().wake_by_ref()&lt;&#x2F;code&gt; where &lt;code&gt;cx&lt;&#x2F;code&gt; is the context received from the poll:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;inner &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;FramedRead&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(file,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BytesCodec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;waker&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;wake_by_ref&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I say appears because the test written works without &lt;code&gt;wake_by_ref()&lt;&#x2F;code&gt; being called.  Requires a bit more investigation here I think to know exactly what&#x27;s going on.  My &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;mpart-async&#x2F;blob&#x2F;981ba0437e19fa47f94a913cf9aaa4717fbe12bc&#x2F;src&#x2F;filestream.rs#L56&quot;&gt;simple test example&lt;&#x2F;a&gt; works either way, strangely.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;It is not too onerous to convert to &lt;code&gt;std::future&lt;&#x2F;code&gt; for an existing library.  I would assume the leap from the old &lt;code&gt;tokio-core&lt;&#x2F;code&gt; would be harder, as the changes &lt;em&gt;feel&lt;&#x2F;em&gt; mostly cosmetic here.&lt;&#x2F;p&gt;
&lt;p&gt;The omission of the &lt;code&gt;Error&lt;&#x2F;code&gt; associated type to me actually makes things less ergonomic and things a little more fragmented (as evidenced by 3 &lt;code&gt;*StreamExt&lt;&#x2F;code&gt; traits..).  I was an advocate of this initially, but there probably needs to be a bit more work in making this nicer.&lt;&#x2F;p&gt;
&lt;p&gt;There are still a lot of libraries out there that will be required to be updated, a lot of old blogs that are no longer relevant, and a lot of exploration that needs to be done to see how the async ecosystem falls out.  But considering the friction of updating is quite small, I am quitely optimistic!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>My Wishes for Rust 2020</title>
          <pubDate>Wed, 30 Oct 2019 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/rust-2020/</link>
          <guid>https://cetra3.github.io/blog/rust-2020/</guid>
          <description xml:base="https://cetra3.github.io/blog/rust-2020/">&lt;p&gt;2019 was another huge year for rust, but instead of implementing the shiny new thing, it&#x27;s been a focus on refining existing ideas.&lt;&#x2F;p&gt;
&lt;p&gt;Having being using rust professionally for over 3 years, I feel I will very soon be regailing new rust developers of the times before NLL &amp;amp; async, where we had to play &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;2094-nll.md#problem-case-3-conditional-control-flow-across-functions&quot;&gt;lexicon-fu&lt;&#x2F;a&gt; to get things like caches to work in a reasonable fashion, or using super dooper combinator chains and wrestling with futures types (&lt;code&gt;Either::A&#x2F;B&lt;&#x2F;code&gt; anyone?).&lt;&#x2F;p&gt;
&lt;p&gt;So I&#x27;d like to make clear my acknowledgement that I am happy with the direction that the rust language is heading in, and these requests are really nice to haves.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-future-of-futures&quot;&gt;The Future of Futures&lt;&#x2F;h2&gt;
&lt;p&gt;The async&#x2F;await is on track to be stabilised next month, which means it&#x27;s not a goal for 2020, but we have to look back to the futures-rs! There is a whole ecosystem that now needs to play catchup and I hope that it does within the year 2020.&lt;&#x2F;p&gt;
&lt;p&gt;I also really hope they start using the logo a bit more!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;futures-rs&#x2F;assets&#x2F;images&#x2F;futures-rs-logo.svg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tokio-version-1-0&quot;&gt;Tokio version &lt;code&gt;1.0&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I would like to see tokio version &lt;code&gt;1.0&lt;&#x2F;code&gt; in 2020.  I would also like the core of tokio to be trimmed down immensely for inclusion as a dependency.  Just a small wish I know!&lt;&#x2F;p&gt;
&lt;p&gt;I understand the reluctance to brand it as &lt;code&gt;1.0&lt;&#x2F;code&gt; but there is already a lot of churn from the move from &lt;code&gt;tokio-core&lt;&#x2F;code&gt; last year.  This would also signal to users that it is mostly stabilised, since async&#x2F;await is dropping soon. I haven&#x27;t been following development closely to know if there are any further blockers beyond this though.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;alternatives-to-tokio&quot;&gt;Alternatives to tokio&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;d also like to see more than one library for async reach wide use.  I&#x27;d like to be able to mix and match executors with library code, and choose an implementation.  The promise of async&#x2F;await should allow for this in theory, but we&#x27;ll have to see what it&#x27;s like in practice.&lt;&#x2F;p&gt;
&lt;p&gt;This will both add a bit of healthy competition to the ecosystem but will also prevent future design decisions from library bias.&lt;&#x2F;p&gt;
&lt;p&gt;I know that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;async-rs&#x2F;async-std&quot;&gt;async-std&lt;&#x2F;a&gt; is a great contender here and I hope that one day I could use this as a (mostly) drop in replacement for running my futures.&lt;&#x2F;p&gt;
&lt;p&gt;This might already be possible, but I&#x27;d have no idea how to integrate this to my existing libraries (i.e, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;tmq&quot;&gt;tmq&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;mpart-async&quot;&gt;mpart-async&lt;&#x2F;a&gt;) in an agnostic fashion.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;non-async-stuff&quot;&gt;Non-Async stuff&lt;&#x2F;h3&gt;
&lt;p&gt;Some more care needs to be put into the non-async world.  There was a great thread about an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;users.rust-lang.org&#x2F;t&#x2F;lightweight-alternative-for-reqwest&#x2F;33601&quot;&gt;alternative to reqwest&lt;&#x2F;a&gt; which doesn&#x27;t require the entire async stack to run.&lt;&#x2F;p&gt;
&lt;p&gt;I would also like to see the blending of async and sync code made easier. Sometimes you want to use a db pool such as diesel, and currently that is a very messy thing to do.&lt;&#x2F;p&gt;
&lt;p&gt;It would be great if that bridge was seamless and doesn&#x27;t shoot you in the foot (i.e, make it a compile time guarantee to ensure no blocking code in async).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;chat-and-community-channels&quot;&gt;Chat and Community Channels&lt;&#x2F;h2&gt;
&lt;p&gt;I really enjoyed the IRC chat room, but as &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;exple.tive.org&#x2F;blarg&#x2F;2019&#x2F;09&#x2F;06&#x2F;forward-motion&#x2F;&quot;&gt;Mozilla is decommissioning it&lt;&#x2F;a&gt;, it feels like there is now a massive empty hole where a good resource use to be.&lt;&#x2F;p&gt;
&lt;p&gt;This isn&#x27;t really something that the rust team themselves can do anything about, but I also don&#x27;t think fragmenting team discussions across a variety of chat platforms sets a good precedent for the greater rust community.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t have any direct qualms about using discord (which is currently recommended on the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20191006130756&#x2F;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;community&quot;&gt;community page&lt;&#x2F;a&gt;) but it would be preferable if whatever was chosen was both accessible and open.  I&#x27;d love it to be &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;matrix.org&#x2F;&quot;&gt;matrix&lt;&#x2F;a&gt;, but &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;about.riot.im&#x2F;&quot;&gt;riot&lt;&#x2F;a&gt; is a bit of a clunky client, and there isn&#x27;t really a better alternative client.  Discord has much more polish.&lt;&#x2F;p&gt;
&lt;p&gt;(As an aside the fediverse stuff is pretty cool! &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;joinmastodon.org&#x2F;&quot;&gt;mastodon&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pixelfed.org&#x2F;&quot;&gt;pixelfed&lt;&#x2F;a&gt; are great apps and I wish we saw more rusty stuff in this space)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reflecting-on-last-year-s-wishes&quot;&gt;Reflecting on Last Year&#x27;s Wishes&lt;&#x2F;h2&gt;
&lt;p&gt;My &lt;a href=&quot;..&#x2F;rust-2019&#x2F;&quot;&gt;last blog&lt;&#x2F;a&gt; I had 3 main areas of improvement that I would like to have seen a focus on.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;compiler-times-ide-support-and-rls&quot;&gt;Compiler Times, IDE Support and RLS&lt;&#x2F;h3&gt;
&lt;p&gt;This is still in flux but appears to be a step in the right direction.  move over &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rls&quot;&gt;rls&lt;&#x2F;a&gt; and welcome &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-analyzer&#x2F;rust-analyzer&quot;&gt;rust-analyzer&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It seems the IDE story is a lot better, but still a long way off.  Who knew it could be so hard!  IntelliJ has made strides this year in making their IDE much better.  Still though, every few months I load up some of my bigger rust projects, only to have some weirdness show up.&lt;&#x2F;p&gt;
&lt;p&gt;I feel like this is very much an aspirational goal though, IDEs for all languages continue and improve to get better with time.  It&#x27;s not ever going to be the ideal of an IDE, but it&#x27;s trending towards it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;async-await&quot;&gt;Async&#x2F;Await&lt;&#x2F;h3&gt;
&lt;p&gt;The Async&#x2F;Await story definitely improved with the imminent release (as of this blog) of &lt;code&gt;async&lt;&#x2F;code&gt; syntax landing on stable.&lt;&#x2F;p&gt;
&lt;p&gt;While there was a substantial amount of dogfooding around the syntax, I feel that the language team has settled on an appropriate solution.  It looks a bit weird at first, but the promise of having &lt;code&gt;match&lt;&#x2F;code&gt; or others use the same syntax style is intruiging.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;documentation-churn&quot;&gt;Documentation Churn&lt;&#x2F;h3&gt;
&lt;p&gt;This is still an area of concern, but has been addressed mostly in some of the frameworks I&#x27;ve seen.  I feel like this won&#x27;t be fixed until all the ecosystem has stabilised around new language features and we land a few more &lt;code&gt;1.0&lt;&#x2F;code&gt; crates.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s going to be a hassle redoing examples with async keywords!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I am happy with the way things have progressed throughout 2019 and I feel that 2020 is going to be a massively exciting time for rust.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t feel there is a need for another epoch just yet, considering we&#x27;re still working through the current one.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s work towards polishing the async ecosystem for this year, and hopefully we&#x27;ll have a very compelling story for everyone else to get involved.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Face Detection with Actix Web</title>
          <pubDate>Thu, 11 Apr 2019 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/face-detection-with-actix-web/</link>
          <guid>https://cetra3.github.io/blog/face-detection-with-actix-web/</guid>
          <description xml:base="https://cetra3.github.io/blog/face-detection-with-actix-web/">&lt;p&gt;Last article I wrote about how to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cetra3.github.io&#x2F;blog&#x2F;face-detection-with-tensorflow-rust&#x2F;&quot;&gt;use tensorflow with rust&lt;&#x2F;a&gt;.  This time we&#x27;re going to take what we&#x27;ve built on, and serve it as an HTTP API call.  As &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;actix&#x2F;actix-web&quot;&gt;Actix Web&lt;&#x2F;a&gt; is nearing its inevitable &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;actix&#x2F;actix-web&#x2F;issues&#x2F;722&quot;&gt;1.0 release&lt;&#x2F;a&gt;, I thought it would be a great time to build something with it.&lt;&#x2F;p&gt;
&lt;p&gt;This article assumes you have some knowledge about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang-nursery&#x2F;futures-rs&quot;&gt;Futures&lt;&#x2F;a&gt; and how they work. I will do my best to explain in simpler terms, but understanding the futures ecosystem would be quite handy to help work through this article. For this, I suggest you start with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tokio.rs&#x2F;&quot;&gt;tokio&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;(Some people have suggested waiting for async&#x2F;await and friends to land before diving into Futures.  I think you should get your hands dirty now: async programming will always be challenging and the changes being introduced only affect ergonomics, not fundamentals)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Once again for the impatient, you can find the reference code here on the &lt;code&gt;actix-web&lt;&#x2F;code&gt; branch:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;mtcnn&#x2F;tree&#x2F;actix-web&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;mtcnn&#x2F;tree&#x2F;actix-web&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;api-shape&quot;&gt;API Shape&lt;&#x2F;h2&gt;
&lt;p&gt;The API shape here is rather simple.  We want to emulate what we&#x27;ve done on the command line: Submit a picture, have a picture returned.  To make things interesting, we&#x27;ll provide a way to return the bounding boxes as a JSON array too.&lt;&#x2F;p&gt;
&lt;p&gt;For submitting binary data via HTTP, there are a few options off the top of my head:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Simply submit the raw data as it stands&lt;&#x2F;li&gt;
&lt;li&gt;Use &lt;code&gt;multipart&#x2F;form-data&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Encode it as a JSON submission&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I think the easiest would be just the raw data so let&#x27;s do that!  Multipart could possibly also work, but what about the case when you have to handle multiple images?  JSON Submission seems a bit wasteful, as you would inevitably have to convert binary data using base64 or similar.&lt;&#x2F;p&gt;
&lt;p&gt;So our API looks like this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Submit POST request as a raw file submission&lt;&#x2F;li&gt;
&lt;li&gt;Run a session against mtcnn to extract faces&lt;&#x2F;li&gt;
&lt;li&gt;Either return Bounding Boxes as JSON, or an Image Overlay as a JPEG like the command line example&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;mtcnn-as-a-struct&quot;&gt;MTCNN as a struct&lt;&#x2F;h2&gt;
&lt;p&gt;In our last blog we just simply used the &lt;code&gt;main&lt;&#x2F;code&gt; function to perform everything, but it&#x27;s not going to fly with actix until we do a bit of a refactor.  We want to encapsulate the mtcnn behaviour as a struct, something that can be passed around and moved.  The end goal is to use it in the application state.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;struct-shape&quot;&gt;Struct Shape&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s make our struct include everything we need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Graph&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;Session&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Some of the &lt;code&gt;Tensor&lt;&#x2F;code&gt; input params that don&#x27;t change from request to request.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We&#x27;ll start by creating a new file &lt;code&gt;mtcnn.rs&lt;&#x2F;code&gt; and adding in the struct definition.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tensorflow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Graph&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Session&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Mtcnn&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Graph&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    session&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Session&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    min_size&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    thresholds&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    factor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, now we&#x27;re just going to plop in the initiation stuff in a &lt;code&gt;new()&lt;&#x2F;code&gt; method.  As the creation of some of these values is not infallible, we&#x27;ll return a &lt;code&gt;Result&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; model&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; include_bytes!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;mtcnn.pb&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span&gt; graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;import_graph_def&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span&gt;model,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ImportGraphDefOptions&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; session&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Session&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;SessionOptions&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;graph)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; min_size&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_values&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;40&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; thresholds&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_values&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; factor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_values&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;709&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        graph,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        session,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        min_size,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        thresholds,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        factor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;the-run-function&quot;&gt;The Run Function&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;em&gt;(I&#x27;m going to race along here to get to the good parts, so if you get stuck or are unsure about what&#x27;s going on, have a look at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cetra3.github.io&#x2F;blog&#x2F;face-detection-with-tensorflow-rust&#x2F;&quot;&gt;original article&lt;&#x2F;a&gt; for an explanation of what&#x27;s happening here.)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ve added all the bits we need to run our session Let&#x27;s create a method that does what we&#x27;re asking the API to do: submit an image, return some bounding boxes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;BBoxes&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Status&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once again, we are returning a &lt;code&gt;Result&lt;&#x2F;code&gt; as the type, as there are some parts of the &lt;code&gt;run&lt;&#x2F;code&gt; that can fail.  We&#x27;re going to use the &lt;code&gt;Status&lt;&#x2F;code&gt; type as that is normally the error type returned&lt;&#x2F;p&gt;
&lt;p&gt;Like our previous main function, we&#x27;ll need to flatten the image input:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span&gt; flattened&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; (_x, _y, rgb)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;pixels&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        flattened&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(rgb[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        flattened&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(rgb[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        flattened&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(rgb[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Tensor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;height&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;, img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;width&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_values&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;flattened)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then we&#x27;ll feed in all the relevant inputs.  This is just the same as our previous &lt;code&gt;main&lt;&#x2F;code&gt; function, but we&#x27;re going to just borrow values from &lt;code&gt;self&lt;&#x2F;code&gt; rather than create them for each run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; SessionRunArgs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_feed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;operation_by_name_required&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;min_size&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;    0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;min_size,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_feed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;operation_by_name_required&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;thresholds&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;    0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;thresholds,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_feed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;operation_by_name_required&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;factor&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;    0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;factor,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_feed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;operation_by_name_required&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;input&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;input);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, let&#x27;s grab the outputs we want:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;request_fetch&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;operation_by_name_required&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;box&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; prob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;request_fetch&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;operation_by_name_required&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;prob&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;running-the-session&quot;&gt;Running The Session&lt;&#x2F;h3&gt;
&lt;p&gt;Now we have all our args set up, we can run the session:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;session&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; args)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Uh oh.  We&#x27;re getting a compiler error here...&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;error[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;E0596&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cannot borrow `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;session` &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;as&lt;&#x2F;span&gt;&lt;span&gt; mutable,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; it is behind a `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;` reference&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  --&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;68&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;36&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;     pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;   |                -----&lt;&#x2F;span&gt;&lt;span&gt; help&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; consider changing this to be a mutable reference&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;68&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |         &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;session&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; args)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;   |          ^^^^^^^^^^^^&lt;&#x2F;span&gt;&lt;span&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #5CCFE6;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;` is a `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;` reference, so the data it refers to cannot be borrowed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; mutable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Turns out that the &lt;code&gt;Session::run()&lt;&#x2F;code&gt; function takes &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;What can we do to resolve this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Make our &lt;code&gt;run&lt;&#x2F;code&gt; function take &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt; so we can mutate the field&lt;&#x2F;li&gt;
&lt;li&gt;Do some tricky interior mutability&lt;&#x2F;li&gt;
&lt;li&gt;Submit an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tensorflow&#x2F;rust&#x2F;issues&#x2F;192&quot;&gt;issue on the tensorflow-rust crate&lt;&#x2F;a&gt; to see whether &lt;code&gt;Session&lt;&#x2F;code&gt; &lt;em&gt;really&lt;&#x2F;em&gt; needs to take &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We&#x27;ll go with option 3!&lt;&#x2F;p&gt;
&lt;p&gt;Update your &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; to point to the git master, rather than the cargo version:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tensorflow = { git = &amp;quot;https:&#x2F;&#x2F;github.com&#x2F;tensorflow&#x2F;rust&amp;quot;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;getting-the-bounding-boxes&quot;&gt;Getting the Bounding Boxes&lt;&#x2F;h3&gt;
&lt;p&gt;This has not changed at all since our &lt;code&gt;main&lt;&#x2F;code&gt; method.  We grab the bounding boxes, put them in our handy dandy &lt;code&gt;BBox&lt;&#x2F;code&gt; struct:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;Our bounding box extents&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bbox_res&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;fetch&lt;&#x2F;span&gt;&lt;span&gt;(bbox)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;Our facial probability&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; prob_res&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;fetch&lt;&#x2F;span&gt;&lt;span&gt;(prob)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;Let&amp;#39;s store the results as a Vec&amp;lt;BBox&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; bboxes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; j&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;While we have responses, iterate through&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; bbox_res&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Add in the 4 floats from the `bbox_res` array.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Notice the y1, x1, etc.. is ordered differently to our struct definition.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    bboxes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;BBox&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; bbox_res[i],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        x1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; bbox_res[i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; bbox_res[i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        x2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; bbox_res[i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        prob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; prob_res[j],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; Add in the facial probability&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Step `i` ahead by 4.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Step `i` ahead by 1.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    j&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;debug!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;BBox Length: {}, BBoxes:{:#?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, bboxes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(), bboxes);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(bboxes)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And that&#x27;s our &lt;code&gt;run&lt;&#x2F;code&gt; function finished.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bbox-struct-as-json&quot;&gt;BBox Struct as JSON&lt;&#x2F;h3&gt;
&lt;p&gt;We&#x27;re gonna want to return a JSON representation of the BBox struct.  So let&#x27;s add in &lt;code&gt;serde_derive&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; serde_derive&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Serialize&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Copy&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Serialize&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BBox&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; x1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; y1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; x2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; y2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; prob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;drawing-the-output-image&quot;&gt;Drawing the Output Image&lt;&#x2F;h3&gt;
&lt;p&gt;We&#x27;ll create a function that will take a list of bounding boxes and an input image, returning the output image:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; overlay&lt;&#x2F;span&gt;&lt;span&gt;(img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;, bboxes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;BBox&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DynamicImage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This hasn&#x27;t changed much either, but we are returning the image, rather than saving it to a file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;Let&amp;#39;s clone the input image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; output_image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;Iterate through all bounding boxes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; bboxes {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Create a `Rect` from the bounding box.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; rect&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Rect&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x1 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;, bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y1 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;of_size&lt;&#x2F;span&gt;&lt;span&gt;((bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x1)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;, (bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y1)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Draw a green line around the bounding box&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    draw_hollow_rect_mut&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; output_image, rect,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; LINE_COLOUR&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;output_image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, we&#x27;re pretty much done with our &lt;code&gt;Mtcnn&lt;&#x2F;code&gt; struct and functions! Could we break this down even further? Yeah definitely! But for now, I think this is all we need.  We&#x27;ve encapsulated the behaviour and created a nice to use couple of functions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;our-new-main-function&quot;&gt;Our New Main Function&lt;&#x2F;h2&gt;
&lt;p&gt;Ok, so we&#x27;re no longer using it as a CLI, but as a self-hosted web app.  We&#x27;re going to need to change the arguments our application takes since we no longer have input and output files.&lt;&#x2F;p&gt;
&lt;p&gt;I think the only argument we should be taking initially is the listen address, and even then we should use a sensible default. So let&#x27;s use the help of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TeXitoi&#x2F;structopt&quot;&gt;structopt&lt;&#x2F;a&gt; to make this pretty minimal boilerplate:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;StructOpt&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Opt&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[structopt(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        short &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        long &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;listen&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        help &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;Listen Address&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        default_value &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;127.0.0.1:8000&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    listen&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;logging-framework&quot;&gt;Logging Framework&lt;&#x2F;h3&gt;
&lt;p&gt;Actix Web uses the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang-nursery&#x2F;log&quot;&gt;log&lt;&#x2F;a&gt; crate to display errors and debug messages.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s move on from using &lt;code&gt;println!&lt;&#x2F;code&gt; and instead use log.  I like using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;seanmonstar&#x2F;pretty-env-logger&quot;&gt;pretty_env_logger&lt;&#x2F;a&gt; as it prints different levels as a different colour, and we can have timestamps which is useful.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;pretty_env_logger&lt;&#x2F;code&gt; still uses environment vars.  Let&#x27;s cheat and set our &lt;code&gt;RUST_LOG&lt;&#x2F;code&gt; var if none is provided then initiate our logger&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;Set the `RUST_LOG` var if none is provided&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;RUST_LOG&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;is_err&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;set_var&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;RUST_LOG&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;mtcnn=DEBUG,actix_web=DEBUG&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;Create a timestamped logger&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;pretty_env_logger&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;init_timed&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This sets up &lt;code&gt;DEBUG&lt;&#x2F;code&gt; level logs for our app and actix web, but allows us to change the log levels via environment variables still.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;actix-and-state&quot;&gt;Actix and State&lt;&#x2F;h2&gt;
&lt;p&gt;We have some state we need to pass to actix to use: our &lt;code&gt;Mtcnn&lt;&#x2F;code&gt; struct and the run method.  There are a number of ways you can give State to actix, but probably the easiest way is the &lt;code&gt;App::data&lt;&#x2F;code&gt; method.  As we are now entering a multithreaded world, we&#x27;re going to have to think about what things are &lt;code&gt;Send&lt;&#x2F;code&gt; and &lt;code&gt;Sync&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Ok, so how do we share something between threads? Well, as a first step I would look to &lt;code&gt;std::sync&lt;&#x2F;code&gt; to see what we need.  Since we know that mtcnn&#x27;s &lt;code&gt;run&lt;&#x2F;code&gt; function does not need to mutate it, only requiring a reference to immutable &lt;code&gt;self&lt;&#x2F;code&gt;, we can probably wrap it in an &lt;code&gt;Arc&lt;&#x2F;code&gt;.  If we had to mutate it, then it would probably require a Mutex as well, but we can avoid this if we use the &lt;code&gt;master&lt;&#x2F;code&gt; branch of &lt;code&gt;tensorflow-rust&lt;&#x2F;code&gt; as above.&lt;&#x2F;p&gt;
&lt;p&gt;So let&#x27;s create our Arc:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Arc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, to instantiate the server:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;HttpServer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    App&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F;Add in our mtcnn struct, we clone the reference for each worker thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;(mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F;Add in a logger to see the requests coming through&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;wrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;middleware&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F; Add in some routes here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;bind&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;opt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;listen)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; Use the listener from the command arguments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, let&#x27;s step through what we&#x27;re doing:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We first build a &lt;code&gt;HttpServer&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;This takes a closure which should return an &lt;code&gt;App&lt;&#x2F;code&gt;.  This &lt;code&gt;App&lt;&#x2F;code&gt; is instantiated for each thread the http server is running&lt;&#x2F;li&gt;
&lt;li&gt;We add our &lt;code&gt;Arc&amp;lt;Mtcnn&amp;gt;&lt;&#x2F;code&gt; using the &lt;code&gt;data&lt;&#x2F;code&gt; method, and clone it for each thread listener.&lt;&#x2F;li&gt;
&lt;li&gt;We add a logger middleware.&lt;&#x2F;li&gt;
&lt;li&gt;We set up some routes with the &lt;code&gt;service&lt;&#x2F;code&gt; function&lt;&#x2F;li&gt;
&lt;li&gt;Then we bind to a listen address and run&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;handling-a-request&quot;&gt;Handling a Request&lt;&#x2F;h2&gt;
&lt;p&gt;Actix Web is an Async framework and uses tokio.  Our function is Synchronous and takes some time to complete.&lt;&#x2F;p&gt;
&lt;p&gt;In other words, our request is blocking.  Can we mix and match sync and async? Absolutely, but it is a little more cumbersome as you&#x27;ll see.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;function-signature-and-extractors&quot;&gt;Function Signature and Extractors&lt;&#x2F;h3&gt;
&lt;p&gt;Actix 1.0 makes heavy use of Extractors, which is a way of providing functions of quite different shapes.  You basically specify what you want your web function to receive, and actix will wire it up for you.  Take care though:  This does mean that some things won&#x27;t be discovered wrong until runtime.  A perfect example I had when I used the wrong type signature for the &lt;code&gt;web::Data&lt;&#x2F;code&gt; argument.&lt;&#x2F;p&gt;
&lt;p&gt;So what do we need to &lt;em&gt;extract&lt;&#x2F;em&gt; from our request? The bytes of the request body, and and also our &lt;code&gt;mtcnn&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; handle_request&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Payload&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Data&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Arc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Mtcnn&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HttpResponse&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We will use this type signature for &lt;code&gt;mtcnn&lt;&#x2F;code&gt; a fair bit, so let&#x27;s make a type alias for it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WebMtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Data&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Arc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Mtcnn&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;getting-the-image-from-a-payload&quot;&gt;Getting the Image from a Payload&lt;&#x2F;h2&gt;
&lt;p&gt;Ok, so we need a way of retrieving the image from a payload and returning a Future.  The &lt;code&gt;web::Payload&lt;&#x2F;code&gt; struct implements &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.1.26&#x2F;futures&#x2F;stream&#x2F;trait.Stream.html&quot;&gt;Stream&lt;&#x2F;a&gt; with &lt;code&gt;Item&lt;&#x2F;code&gt; set to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;bytes&#x2F;0.4.12&#x2F;bytes&#x2F;struct.Bytes.html&quot;&gt;Bytes&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Well, we don&#x27;t really care about the individual bytes we get from a stream, we want the whole lot to decode the image!  So let&#x27;s convert the &lt;code&gt;Stream&lt;&#x2F;code&gt; into a &lt;code&gt;Future&lt;&#x2F;code&gt;, and merge all the individual bytes we&#x27;ll be getting into one big bucket of bytes.  Sounds complicated, but luckily Stream has a method: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.1.26&#x2F;futures&#x2F;stream&#x2F;trait.Stream.html#method.concat2&quot;&gt;concat2&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is a pretty powerful combinator which allows us to join the results of individual Stream polls into one if the item implements &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;core&#x2F;iter&#x2F;trait.Extend.html&quot;&gt;Extend&lt;&#x2F;a&gt; (and some other traits) which &lt;code&gt;Bytes&lt;&#x2F;code&gt; happens to.&lt;&#x2F;p&gt;
&lt;p&gt;So this looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;concat2&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;....&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;image-decoding-and-web-block&quot;&gt;Image Decoding and &lt;code&gt;web::block&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Ok, second thing we need to sort out, if we&#x27;re going to be decoding an image, that is probably going to block the thread until it&#x27;s done.  How long? Well if it&#x27;s a huge image, it might take milliseconds!  So we want to ensure that we&#x27;re not blocking the http workers while this is happening.  Luckily, actix web has a way of taking a blocking portion of code, and wrapping that as a future.&lt;&#x2F;p&gt;
&lt;p&gt;Enter &lt;code&gt;web::block&lt;&#x2F;code&gt;.  We&#x27;ll do our decoding in a cpu pool, bridging sync and async together:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;concat2&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;load_from_memory&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bytes)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, that is pretty succint: we take a stream, convert it into a future and a bundle of bytes, then use &lt;code&gt;web::block&lt;&#x2F;code&gt; to decode the bytes into an image in a background thread and return the result.  the &lt;code&gt;load_from_memory&lt;&#x2F;code&gt; function already returns a Result, which means we can just use that as the return type.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;balancing-the-error-type&quot;&gt;Balancing the Error Type&lt;&#x2F;h3&gt;
&lt;p&gt;So, our Item is converted to &lt;code&gt;Bytes&lt;&#x2F;code&gt; to &lt;code&gt;DynamicImage&lt;&#x2F;code&gt;, but we still haven&#x27;t dealt with the error types yet and it won&#x27;t compile.  What should our error type be?  Let&#x27;s use &lt;code&gt;actix_web::Error&lt;&#x2F;code&gt; as &lt;code&gt;ActixError&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; actix_web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span&gt; get_image(stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Payload&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;concat2()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;and_then(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;block(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;load_from_memory(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bytes)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, that is giving us few really gnarly errors when we try and compile it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;error[E0271]: type mismatch resolving `&amp;lt;impl futures::future::Future as futures::future::IntoFuture&amp;gt;::Error == actix_http::error::PayloadError`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  --&amp;gt; src&#x2F;main.rs:67:22&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;67 |     stream.concat2().and_then(move |bytes| {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   |                      ^^^^^^^^ expected enum `actix_threadpool::BlockingError`, found enum `actix_http::error::PayloadError`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   = note: expected type `actix_threadpool::BlockingError&amp;lt;image::image::ImageError&amp;gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              found type `actix_http::error::PayloadError`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There&#x27;s a couple more that aren&#x27;t listed.&lt;&#x2F;p&gt;
&lt;p&gt;When you are combining streams, mapping them as futures, and otherwise trying to get some output from these combinators you are actually dealing with both the &lt;code&gt;Item&lt;&#x2F;code&gt; type, and the &lt;code&gt;Error&lt;&#x2F;code&gt; type.&lt;&#x2F;p&gt;
&lt;p&gt;The ergonomics of this are not as advanced as the &lt;code&gt;Result&lt;&#x2F;code&gt; type, where we can use the &lt;code&gt;?&lt;&#x2F;code&gt; operator to automatically adjust to the right error (if a conversion is available). When both &lt;code&gt;ops::Try&lt;&#x2F;code&gt; and &lt;code&gt;async&#x2F;await&lt;&#x2F;code&gt; syntax stabilises, this might be a different story, but for now, we need to deal with error types.&lt;&#x2F;p&gt;
&lt;p&gt;What we have instead is the magic™️ &lt;code&gt;from_err()&lt;&#x2F;code&gt; method.  This is basically the same as the &lt;code&gt;?&lt;&#x2F;code&gt; operator but for futures.  We have two futures we&#x27;re dealing with: our bundle of bytes from the stream, and the image from the blocking closure. We have 3 error types we&#x27;re dealing with: the Payload error, the Image load from memory error, and the blocking error.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start by putting &lt;code&gt;from_err()&lt;&#x2F;code&gt; on both of the futures:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_image&lt;&#x2F;span&gt;&lt;span&gt;(stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Payload&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;concat2&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_err&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;load_from_memory&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bytes)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_err&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That worked! There is enough conversions for our error types to get to where we need to get it.  The &lt;code&gt;ActixError&lt;&#x2F;code&gt; type has a few blanket conversions from common error types enough to be able to make this magic happen.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getting-the-bounding-boxes-from-the-image&quot;&gt;Getting the bounding boxes from the image&lt;&#x2F;h2&gt;
&lt;p&gt;At the core of it, we need to run the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;img)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But we want this to run in a threadpool too:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;||&lt;&#x2F;span&gt;&lt;span&gt; mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;img))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s work through the function signature we&#x27;ll need.  At a minimum we&#x27;re gonna need the image, and the mtcnn struct.  Then we want to return a &lt;code&gt;Vec&lt;&#x2F;code&gt; of BBoxes.  We should try and keep our error types the same, so we&#x27;ll use the ActixError type.&lt;&#x2F;p&gt;
&lt;p&gt;The function signature looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_bboxes&lt;&#x2F;span&gt;&lt;span&gt;(img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;, mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WebMtcnn&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;BBox&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We know that we&#x27;ll need a &lt;code&gt;from_err()&lt;&#x2F;code&gt; on the &lt;code&gt;web::block&lt;&#x2F;code&gt; to convert the error type, and we&#x27;ll have to use a &lt;code&gt;move&lt;&#x2F;code&gt; to give the image to the closure:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_bboxes&lt;&#x2F;span&gt;&lt;span&gt;(img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;, mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WebMtcnn&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;BBox&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;img))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_err&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But does this compile? Not yet:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;error[E0277]: `*mut tensorflow_sys::TF_Status` cannot be sent between threads safely&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  --&amp;gt; src&#x2F;main.rs:75:5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;75 |     web::block(move || mtcnn.run(&amp;amp;img)).from_err()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   |     ^^^^^^^^^^ `*mut tensorflow_sys::TF_Status` cannot be sent between threads safely&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   = help: within `tensorflow::Status`, the trait `std::marker::Send` is not implemented for `*mut tensorflow_sys::TF_Status`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   = note: required because it appears within the type `tensorflow::Status`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   = note: required by `actix_web::web::block`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;tensorflow::Status&lt;&#x2F;code&gt;, which is the error type, can&#x27;t be sent between threads.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s just shortcut here, and convert the error to a &lt;code&gt;String&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_bboxes&lt;&#x2F;span&gt;&lt;span&gt;(img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;, mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WebMtcnn&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;BBox&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;img)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;()))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_err&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This allows us to move the &lt;code&gt;Result&lt;&#x2F;code&gt; across thread boundaries, as &lt;code&gt;String&lt;&#x2F;code&gt; does implement &lt;code&gt;Send&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;returning-json-bboxes&quot;&gt;Returning JSON BBoxes&lt;&#x2F;h2&gt;
&lt;p&gt;Ok, so we have 2 functions, one to get the image from the request, and one to get the bounding boxes.  We&#x27;re gonna want to return json &lt;code&gt;HttpResponse&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; return_bboxes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Payload&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WebMtcnn&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HttpResponse&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Get the image from the input stream&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    get_image&lt;&#x2F;span&gt;&lt;span&gt;(stream) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F; Get the bounding boxes from the image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_bboxes&lt;&#x2F;span&gt;&lt;span&gt;(img, mtcnn)) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F; Map the bounding boxes to a json HttpResponse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;bboxes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HttpResponse&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;json&lt;&#x2F;span&gt;&lt;span&gt;(bboxes))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Cool! Let&#x27;s put this in our App definition:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;HttpServer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    App&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;(mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;()) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;wrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;middleware&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;()) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F; our new API service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;resource&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;api&#x2F;v1&#x2F;bboxes&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_async&lt;&#x2F;span&gt;&lt;span&gt;(return_bboxes))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;bind&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;opt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;listen)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And let&#x27;s run it, using &lt;code&gt;curl&lt;&#x2F;code&gt; to submit a query to get some results back&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ curl --data-binary @rustfest.jpg  http:&#x2F;&#x2F;localhost:8000&#x2F;api&#x2F;v1&#x2F;bboxes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[{&amp;quot;x1&amp;quot;:471.4591,&amp;quot;y1&amp;quot;:287.59888,&amp;quot;x2&amp;quot;:495.3053,&amp;quot;y2&amp;quot;:317.25327,&amp;quot;prob&amp;quot;:0.9999908}....&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Awesome! Using &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;jmespath.org&#x2F;&quot;&gt;jmespath&lt;&#x2F;a&gt; to see we get our 120 faces back:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ curl -s --data-binary @rustfest.jpg  http:&#x2F;&#x2F;localhost:8000&#x2F;api&#x2F;v1&#x2F;bboxes | jp &amp;quot;length(@)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;120&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;returning-an-overlay-image&quot;&gt;Returning an Overlay Image&lt;&#x2F;h2&gt;
&lt;p&gt;The other API call we want is to return an image with the bounding boxes overlayed.  This is not much of a stretch, but the act of drawing boxes on an image is definitely a blocking action, so we&#x27;ll need to do the same thing and send it to a thread pool.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s wrap our overlay function, converting it into a Future:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_overlay&lt;&#x2F;span&gt;&lt;span&gt;(img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;, bboxes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;BBox&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;   -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; output_img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; overlay&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;img,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bboxes);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_err&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;re going to want to return a &lt;code&gt;Vec&lt;&#x2F;code&gt; of &lt;code&gt;u8&lt;&#x2F;code&gt; bytes so we can use this in the return body. So we&#x27;ll need to allocate some buffer and instruct &lt;code&gt;image&lt;&#x2F;code&gt; to write out a JPEG from the image:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;output_img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;write_to&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buffer,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; JPEG&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; write out our buffer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(buffer)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, so let&#x27;s put our little function together and see if it compiles:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_overlay&lt;&#x2F;span&gt;&lt;span&gt;(img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;, bboxes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;BBox&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;  -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; output_img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; overlay&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;img,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bboxes);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let mut&lt;&#x2F;span&gt;&lt;span&gt; buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        output_img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;write_to&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buffer,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; JPEG&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; write out our buffer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(buffer)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_err&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Not quite yet: we&#x27;re missing a type annotation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;error[E0282]: type annotations needed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  --&amp;gt; src&#x2F;main.rs:82:5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;82 |     web::block(move || {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   |     ^^^^^^^^^^ cannot infer type for `E`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Why is there an issue with the type? Well, it relates to this line here:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Ok(buffer) &#x2F;&#x2F; What&amp;#39;s the `Error` type here?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At the moment, the only error type is from the &lt;code&gt;write_to&lt;&#x2F;code&gt; method which is &lt;code&gt;ImageError&lt;&#x2F;code&gt;.  But this line here doesn&#x27;t have an error type, and could be anything.&lt;&#x2F;p&gt;
&lt;p&gt;There are 3 ways I can immediately think to handle this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Way Number 1&lt;&#x2F;strong&gt;: Declare the error type in &lt;code&gt;web::block&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;_,_,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ImageError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This looks more like a turbosubmarine than a turbofish! But it compiles!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Way Number 2&lt;&#x2F;strong&gt;: Declare the Result type with &lt;code&gt;as&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(buffer)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;_,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ImageError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Way Number 3&lt;&#x2F;strong&gt;: Use &lt;code&gt;map&lt;&#x2F;code&gt; to return the buffer on success:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;output_img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;write_to&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buffer,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; JPEG&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; buffer)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I think for readability, #2 is probably easiest.  The &lt;code&gt;web::block&lt;&#x2F;code&gt; function takes 3 type arguments which can be confusing on first read of the code.  #3 is good too but I think it looks a bit strange.&lt;&#x2F;p&gt;
&lt;p&gt;Our final method looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_overlay&lt;&#x2F;span&gt;&lt;span&gt;(img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;, bboxes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;BBox&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;   -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; output_img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; overlay&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;img,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bboxes);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let mut&lt;&#x2F;span&gt;&lt;span&gt; buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        output_img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;write_to&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buffer,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; JPEG&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F; Type annotations required for the `web::block`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(buffer)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;_,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ImageError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_err&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;the-api-call&quot;&gt;The API call&lt;&#x2F;h3&gt;
&lt;p&gt;Ok, we have our little futures that we need to return bounding boxes and image overlays.  Let&#x27;s stitch this together and return a &lt;code&gt;HttpResponse&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; return_overlay&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Payload&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WebMtcnn&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HttpResponse&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;... magic happens here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, first step is to get the image from the stream:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;get_image&lt;&#x2F;span&gt;&lt;span&gt;(stream)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And Then once the future has resolved, we want to get the bounding boxes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;get_image&lt;&#x2F;span&gt;&lt;span&gt;(stream)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    get_bboxes&lt;&#x2F;span&gt;&lt;span&gt;(img, mtcnn)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;moving-images-around&quot;&gt;Moving Images Around&lt;&#x2F;h3&gt;
&lt;p&gt;Now we want to get the image overlay.  We have an issue though! we give the &lt;code&gt;get_bboxes&lt;&#x2F;code&gt; future our image, and it returns a Vec of bboxes, consuming the image.  There are a couple of options here.  We could &lt;code&gt;clone()&lt;&#x2F;code&gt; the image when we give it to bboxes, but that is duplicating memory.  We could wait for &lt;code&gt;Pin&lt;&#x2F;code&gt; and &lt;code&gt;async&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;await&lt;&#x2F;code&gt; to be finished and probably deal with it in an easier way then.&lt;&#x2F;p&gt;
&lt;p&gt;Or we could adjust our &lt;code&gt;get_bboxes&lt;&#x2F;code&gt; method to return a tuple of both the image and bounding boxes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_bboxes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WebMtcnn&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;DynamicImage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;BBox&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        mtcnn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;img)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;            &#x2F;&#x2F;Return both the image and the bounding boxes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;bboxes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; (img, bboxes))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_err&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Making sure to update our &lt;code&gt;return_bboxes&lt;&#x2F;code&gt; function too:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; return_bboxes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Payload&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WebMtcnn&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HttpResponse&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    get_image&lt;&#x2F;span&gt;&lt;span&gt;(stream)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_bboxes&lt;&#x2F;span&gt;&lt;span&gt;(img, mtcnn))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;(_img, bboxes)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HttpResponse&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;json&lt;&#x2F;span&gt;&lt;span&gt;(bboxes))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;getting-the-overlay&quot;&gt;Getting the Overlay&lt;&#x2F;h3&gt;
&lt;p&gt;It would be great if rust could desugar a tuple into command arguments.  Unfortunately not for us, so we will need to create a small closure:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;Create our image overlay&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;(img, bbox)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_overlay&lt;&#x2F;span&gt;&lt;span&gt;(img, bbox))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F; Return a `HttpResponse` here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;generating-the-response&quot;&gt;Generating the Response&lt;&#x2F;h3&gt;
&lt;p&gt;Our &lt;code&gt;HttpResponse&lt;&#x2F;code&gt; needs to wrap the buffer into a Http Request with the buffer as the body:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;HttpResponse&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_body&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;OK&lt;&#x2F;span&gt;&lt;span&gt;, buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Is that it? Well no, we have to set the content type header to be a jpeg:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; response&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HttpResponse&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_body&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;OK&lt;&#x2F;span&gt;&lt;span&gt;, buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;response&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;headers_mut&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;CONTENT_TYPE&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HeaderValue&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_static&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;image&#x2F;jpeg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok now we can return the result:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; return_overlay&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    stream&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Payload&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; WebMtcnn&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Future&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HttpResponse&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; ActixError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;    get_image&lt;&#x2F;span&gt;&lt;span&gt;(stream)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            get_bboxes&lt;&#x2F;span&gt;&lt;span&gt;(img, mtcnn)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;(img, bbox)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; get_overlay&lt;&#x2F;span&gt;&lt;span&gt;(img, bbox))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;            let mut&lt;&#x2F;span&gt;&lt;span&gt; response&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HttpResponse&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_body&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;OK&lt;&#x2F;span&gt;&lt;span&gt;, buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            response&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;headers_mut&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;CONTENT_TYPE&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; HeaderValue&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_static&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;image&#x2F;jpeg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            response&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And add that to our &lt;code&gt;App&lt;&#x2F;code&gt; builder:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;HttpServer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    App&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;(mtcnn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F;Add in our data handler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F;Add in a logger to see the requets coming through&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;wrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;middleware&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;()) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F;JSON bounding boxes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;resource&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;api&#x2F;v1&#x2F;bboxes&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_async&lt;&#x2F;span&gt;&lt;span&gt;(return_bboxes))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;        &#x2F;&#x2F;Image overlay&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;web&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;resource&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&#x2F;api&#x2F;v1&#x2F;overlay&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;to_async&lt;&#x2F;span&gt;&lt;span&gt;(return_overlay))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Great! Let&#x27;s run it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ curl --data-binary @rustfest.jpg  http:&#x2F;&#x2F;localhost:8000&#x2F;api&#x2F;v1&#x2F;bboxes &amp;gt; output.jpg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And we have our original overlay!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;photos&#x2F;rustfest_faces.jpg&quot;&gt;&lt;img src=&quot;&#x2F;photos&#x2F;rustfest_faces.jpg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;&#x2F;h2&gt;
&lt;p&gt;We stepped through converting a CLI app into a HTTP service, dipping our toes into the brave new async world.&lt;&#x2F;p&gt;
&lt;p&gt;As you can see, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;actix&#x2F;actix-web&#x2F;&quot;&gt;actix web&lt;&#x2F;a&gt; is a very versatile web framework.  My interest in it was borne out of having all the features I need to build up web apps: multipart, thread pools, great efficiency.&lt;&#x2F;p&gt;
&lt;p&gt;While it is hard to bridge the sync and async gap, it&#x27;s not impossible.  It would be great if there were some more ergonomic ways to do so, as I think a lot of developers struggle with this: I have seen a lot of questions around integrating with diesel and friends.&lt;&#x2F;p&gt;
&lt;p&gt;If you are looking for more actix web examples, the evergrowing examples repo is your best bet:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;actix&#x2F;examples&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;actix&#x2F;examples&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I look forward to seeing what the community builds in the future!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Face Detection with Tensorflow Rust</title>
          <pubDate>Thu, 28 Mar 2019 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/face-detection-with-tensorflow-rust/</link>
          <guid>https://cetra3.github.io/blog/face-detection-with-tensorflow-rust/</guid>
          <description xml:base="https://cetra3.github.io/blog/face-detection-with-tensorflow-rust/">&lt;p&gt;One of the promises of machine learning is to be able to use it for object recognition in photos.  This includes being able to pick out features such as animals, buildings and even faces.&lt;&#x2F;p&gt;
&lt;p&gt;This article will step you through using some existing models to accomplish face detection using rust and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tensorflow.org&#x2F;&quot;&gt;tensorflow&lt;&#x2F;a&gt;.  For the impatient among you, you can find the source code here: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;mtcnn&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;mtcnn&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We will be using a pre-trained model called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kpzhang93.github.io&#x2F;MTCNN_face_detection_alignment&#x2F;index.html&quot;&gt;mtcnn&lt;&#x2F;a&gt; for face detection (&lt;em&gt;Note: training a new model is not something we&#x27;ll be concerned with in this article&lt;&#x2F;em&gt;).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-challenge&quot;&gt;The Challenge&lt;&#x2F;h2&gt;
&lt;p&gt;We want to read the photo, have the faces detected, and then return an image with the bounding boxes drawn in.&lt;&#x2F;p&gt;
&lt;p&gt;In other words, we want to convert this (Image used with permission of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rustfest.eu&quot;&gt;RustFest&lt;&#x2F;a&gt;, taken by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fionacastineira.com&#x2F;&quot;&gt;Fiona Castiñeira&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;photos&#x2F;rustfest.jpg&quot;&gt;&lt;img src=&quot;&#x2F;photos&#x2F;rustfest.jpg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Into this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;photos&#x2F;rustfest_faces.jpg&quot;&gt;&lt;img src=&quot;&#x2F;photos&#x2F;rustfest_faces.jpg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tensorflow-and-mtcnn&quot;&gt;Tensorflow and MTCNN&lt;&#x2F;h2&gt;
&lt;p&gt;The original MTCNN model was written using &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;caffe.berkeleyvision.org&#x2F;&quot;&gt;Caffe&lt;&#x2F;a&gt;, but luckily there is a number of tensorflow python implementations for mtcnn.  I&#x27;m going to pick the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;blaueck&#x2F;tf-mtcnn&quot;&gt;following&lt;&#x2F;a&gt; as it is a straight conversion into a single graph model file.&lt;&#x2F;p&gt;
&lt;p&gt;Firstly we want to add &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tensorflow&#x2F;rust&quot;&gt;tensorflow rust&lt;&#x2F;a&gt; as a dependency.  Here&#x27;s a Cargo.toml to start:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;package&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;mtcnn&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;version&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;0.1.0&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;edition&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;2018&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;dependencies&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tensorflow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;0.12.0&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What we&#x27;re going to do is load a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tensorflow.github.io&#x2F;rust&#x2F;tensorflow&#x2F;struct.Graph.html&quot;&gt;Graph&lt;&#x2F;a&gt; which is the pre-trained MTCNN, and run a session.  The gist is that a Graph is the model used for computation, and a Session is one &lt;code&gt;run&lt;&#x2F;code&gt; of the Graph.  A lot more information about these concepts can be found &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tensorflow.org&#x2F;guide&#x2F;graphs&quot;&gt;here&lt;&#x2F;a&gt;.  I like to think of the Graph as an artificial brain in a vat, just to get some great imagery when you start plugging in inputs and outputs.&lt;&#x2F;p&gt;
&lt;p&gt;So let&#x27;s start by grabbing the existing &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;blaueck&#x2F;tf-mtcnn&#x2F;raw&#x2F;master&#x2F;mtcnn.pb&quot;&gt;mtcnn.pb&lt;&#x2F;a&gt; model and trying to load it up.  Tensorflow graphs are serialised out in protobuf format and can be loaded in using &lt;code&gt;Graph::import_graph_def&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tensorflow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Graph&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tensorflow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ImportGraphDefOptions&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;First, we load up the graph as a byte array&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; model&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; include_bytes!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;mtcnn.pb&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Then we create a tensorflow graph from the model&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span&gt; graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;import_graph_def&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span&gt;model,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;ImportGraphDefOptions&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Running &lt;code&gt;cargo run&lt;&#x2F;code&gt; we should see no errors:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cargo run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   Compiling mtcnn v0.1.0 (~&#x2F;mtcnn)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Finished dev [unoptimized + debuginfo] target(s) in 0.89s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     Running `target&#x2F;debug&#x2F;mtcnn`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Great! Looks like we can load the graph!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;structopt-and-the-command-line&quot;&gt;StructOpt and the Command Line&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;re going to want to test out image generation, so let&#x27;s use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TeXitoi&#x2F;structopt&quot;&gt;structopt&lt;&#x2F;a&gt; to take two arguments: &lt;code&gt;input&lt;&#x2F;code&gt; and &lt;code&gt;output&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you haven&#x27;t used structopt before: structopt is like combining &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;clap-rs&#x2F;clap&quot;&gt;clap&lt;&#x2F;a&gt; with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;serde-rs&#x2F;serde&quot;&gt;serde&lt;&#x2F;a&gt;.  The &lt;code&gt;input&lt;&#x2F;code&gt; argument will be the path of an image file.  The &lt;code&gt;output&lt;&#x2F;code&gt; will be where we save the output image.&lt;&#x2F;p&gt;
&lt;p&gt;So our struct looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;PathBuf&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; structopt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;StructOpt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;StructOpt&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Opt&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[structopt(parse(from_os_str))]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; PathBuf&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[structopt(parse(from_os_str))]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    output&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; PathBuf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;parse(from_os_str)&lt;&#x2F;code&gt; attribute will convert a string argument directly into a &lt;code&gt;PathBuf&lt;&#x2F;code&gt; to save us some boiler plate&lt;&#x2F;p&gt;
&lt;p&gt;We can then use this to get a struct with our command line arguments&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; opt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Opt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;from_args&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    ....&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;loading-image-data&quot;&gt;Loading Image Data&lt;&#x2F;h2&gt;
&lt;p&gt;We need to provide the tensorflow graph with our image data.  So how do we do that? We use a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tensorflow.github.io&#x2F;rust&#x2F;tensorflow&#x2F;struct.Tensor.html&quot;&gt;Tensor&lt;&#x2F;a&gt;!  Tensors represent data within our graph, it sort of reminds me of sending vertices to a GPU.  You have a big slice of data, and send it in a format that tensorflow is expecting.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;input&lt;&#x2F;code&gt; tensor in this graph is an array of floats, with dimensions: &lt;code&gt;height&lt;&#x2F;code&gt; x &lt;code&gt;width&lt;&#x2F;code&gt; x &lt;code&gt;3&lt;&#x2F;code&gt; (for 3 colour channels).&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PistonDevelopers&#x2F;image&quot;&gt;image&lt;&#x2F;a&gt; crate to load the image:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; input_image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;opt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;input)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next we want to convert this image into its raw pixels by using the &lt;code&gt;GenericImage::pixels&lt;&#x2F;code&gt; function and send that to our graph. All multi-dimensional Tensor arrays are flat, and stored in row major order.  The model uses &lt;code&gt;BGR&lt;&#x2F;code&gt; instead of the traditional &lt;code&gt;RGB&lt;&#x2F;code&gt; for colours, so we&#x27;ll need to reverse the pixel values when we iterate through.&lt;&#x2F;p&gt;
&lt;p&gt;Putting it all together:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; flattened&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (_x, _y, rgb)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; input_image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;pixels&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    flattened&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(rgb[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    flattened&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(rgb[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    flattened&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(rgb[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This simply iterates through the pixels, adding them to a flattened Vec.&lt;&#x2F;p&gt;
&lt;p&gt;We can then load this into a tensor, specifying the image height and width as arguments:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[input_image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;height&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;, input_image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;width&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_values&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;flattened)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Great! we have loaded our image into a format that the graph understands.  Let&#x27;s run a session!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;creating-a-tensorflow-session&quot;&gt;Creating a tensorflow session&lt;&#x2F;h3&gt;
&lt;p&gt;Ok, we have a graph, the input image, but now we need a session for the graph.  We&#x27;ll just use the defaults for this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; session&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Session&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;SessionOptions&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;graph)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;running-a-session&quot;&gt;Running a session&lt;&#x2F;h2&gt;
&lt;p&gt;Before we run a session, we have a few other inputs the mtcnn model is expecting.  We&#x27;re gonna use the same defaults the mtcnn library for these values:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; min_size&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_values&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;40&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; thresholds&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_values&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; factor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with_values&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CCCAC2B3;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;709&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The graph can define multiple inputs&#x2F;outputs that are required before running and it depends on the specific neural net as to what these are.  For MTCNN, these are all described in the original implementation.  Probably the most important one is the &lt;code&gt;min_size&lt;&#x2F;code&gt; which describes the minimum size to find faces.&lt;&#x2F;p&gt;
&lt;p&gt;Now we build the session arguments for the inputs:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; SessionRunArgs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;Load our parameters for the model&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_feed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;operation_by_name_required&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;min_size&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;min_size);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_feed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;operation_by_name_required&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;thresholds&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;thresholds);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_feed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;operation_by_name_required&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;factor&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;factor);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;Load our input image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;add_feed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;operation_by_name_required&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;input&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;input);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, what about outputs? There are two that we are going to request when the session is finished: bounding boxes and probabilities:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;request_fetch&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;operation_by_name_required&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;box&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; prob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;request_fetch&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;graph&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;operation_by_name_required&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;prob&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok cool, we have our inputs, and our outputs, let&#x27;s run it!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;session&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; args)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;the-bbox-struct&quot;&gt;The BBox struct&lt;&#x2F;h3&gt;
&lt;p&gt;The model outputs the following values:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Bounding box of the faces&lt;&#x2F;li&gt;
&lt;li&gt;Landmarks of the faces&lt;&#x2F;li&gt;
&lt;li&gt;Probability that it&#x27;s a face from &lt;code&gt;0&lt;&#x2F;code&gt; to &lt;code&gt;1&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In order to make it a bit more easy to work with, we&#x27;ll define a bounding box struct which encodes those values back in a more easy to read fashion:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Copy&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BBox&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; x1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; y1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; x2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; y2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; prob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;ll omit landmarks for simplicity, but can always add them back if we need.  Our job is to convert the arrays we get back from the tensorflow session into this struct so it&#x27;s more meaningful.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;saving-the-output&quot;&gt;Saving the Output&lt;&#x2F;h3&gt;
&lt;p&gt;Right, now let&#x27;s grab back the outputs.  Just like inputs, outputs are &lt;code&gt;Tensors&lt;&#x2F;code&gt; too:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bbox_res&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;fetch&lt;&#x2F;span&gt;&lt;span&gt;(bbox)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; prob_res&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Tensor&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;fetch&lt;&#x2F;span&gt;&lt;span&gt;(prob)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What is the shape of &lt;code&gt;bbox&lt;&#x2F;code&gt;? Well, it&#x27;s a multi-dimensional flattened array that includes 4 floats per bounding box representing the bounding box extents.  The &lt;code&gt;prob&lt;&#x2F;code&gt; is an array with a single float value per face: the probability from &lt;code&gt;0&lt;&#x2F;code&gt; to &lt;code&gt;1&lt;&#x2F;code&gt;.  So we should expect the &lt;code&gt;bbox_res&lt;&#x2F;code&gt; length to be the &lt;code&gt;number of faces&lt;&#x2F;code&gt; x &lt;code&gt;4&lt;&#x2F;code&gt;, and &lt;code&gt;prob_res&lt;&#x2F;code&gt; to be equal to the number of faces.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s do some basic iteration and store our results into a &lt;code&gt;Vec&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;Let&amp;#39;s store the results as a Vec&amp;lt;BBox&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; bboxes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; j&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;&#x2F;&#x2F;While we have responses, iterate through&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; bbox_res&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Add in the 4 floats from the `bbox_res` array. &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Notice the y1, x1, etc.. is ordered differently to our struct definition.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    bboxes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;BBox&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; bbox_res[i],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        x1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; bbox_res[i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; bbox_res[i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        x2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; bbox_res[i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        prob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; prob_res[j],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; Add in the facial probability&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Step `i` ahead by 4. &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Step `i` ahead by 1. &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    j&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h5 id=&quot;combinators&quot;&gt;Combinators&lt;&#x2F;h5&gt;
&lt;p&gt;Alternatively, we could use combinators to replace the one above.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bboxes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;_&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; bbox_res&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;chunks_exact&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; Split into chunks of 4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;zip&lt;&#x2F;span&gt;&lt;span&gt;(prob_res&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt; &#x2F;&#x2F; Combine it with prob_res&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;(bbox,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;prob)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; BBox&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; bbox[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        x1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; bbox[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; bbox[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        x2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; bbox[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        prob,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;printing-out-the-bounding-boxes&quot;&gt;Printing out the bounding boxes&lt;&#x2F;h3&gt;
&lt;p&gt;Ok, we haven&#x27;t encoded the bounding boxes into an image, yet. but let&#x27;s debug to make sure we&#x27;re getting back &lt;em&gt;something&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;BBox Length: {}, Bboxes:{:#?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, bboxes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(), bboxes);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Running this, what do we get back:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;BBox Length: 120, BBoxes:[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    BBox {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        x1: 471.4591,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y1: 287.59888,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        x2: 495.3053,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y2: 317.25327,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        prob: 0.9999908&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ....&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Whoa! 120 faces! Awesome!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;drawing-the-bounding-boxes&quot;&gt;Drawing the Bounding Boxes&lt;&#x2F;h2&gt;
&lt;p&gt;Great, we have some bounding boxes.  Let&#x27;s draw them on the image, and save the output into a file.&lt;&#x2F;p&gt;
&lt;p&gt;To draw bounding boxes, we can use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PistonDevelopers&#x2F;imageproc&quot;&gt;imageproc&lt;&#x2F;a&gt; library to draw simple borders around the bounding boxes.&lt;&#x2F;p&gt;
&lt;p&gt;Firstly, we&#x27;ll make the line colour constant green outside of our &lt;code&gt;main()&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; LINE_COLOUR&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Rgba&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Rgba&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 255&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now stepping back into it.  We are feeding in the input image read only, so let&#x27;s use the first image to draw onto:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; output_image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; input_image;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then we iterate through our bounding boxes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; bboxes {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6E7C8F;font-style: italic;&quot;&gt;    &#x2F;&#x2F;Drawing Happens Here!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we use the &lt;code&gt;draw_hollow_rect_mut&lt;&#x2F;code&gt; function.  This will take a mutable image reference, and draw a hollow rectangle (outline) specified by the input &lt;code&gt;Rect&lt;&#x2F;code&gt;, overwriting any existing pixels.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;Rect&lt;&#x2F;code&gt; takes an x and y coordinate with the &lt;code&gt;at&lt;&#x2F;code&gt; function, and then a width and height with the &lt;code&gt;of_size&lt;&#x2F;code&gt; function.  We use a bit of geometry to convert our bounding box to this format:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; rect&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Rect&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x1 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;, bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y1 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;of_size&lt;&#x2F;span&gt;&lt;span&gt;((bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x1)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;, (bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; bbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y1)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then draw the rect:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;draw_hollow_rect_mut&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; output_image, rect,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; LINE_COLOUR&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once the for loop is done, we save it in the output file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;output_image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;save&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;opt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;output)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And we&#x27;re done. Let&#x27;s run it!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cargo run rustfest.jpg output.jpg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   Compiling mtcnn v0.1.0 (~&#x2F;mtcnn)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Finished dev [unoptimized + debuginfo] target(s) in 5.12s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     Running `target&#x2F;debug&#x2F;mtcnn rustfest.jpg output.jpg`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2019-03-28 16:15:48.194933: I tensorflow&#x2F;core&#x2F;platform&#x2F;cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.2 AVX AVX2 FMA&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;BBox Length: 154, BBoxes:[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    BBox {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        x1: 951.46875,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y1: 274.00577,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        x2: 973.68304,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y2: 301.93915,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        prob: 0.9999999&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;....&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Looks good, no errors!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s step through what we&#x27;ve done in this little application:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Loaded a pre-trained tensorflow graph&lt;&#x2F;li&gt;
&lt;li&gt;Parse the command line arguments&lt;&#x2F;li&gt;
&lt;li&gt;Read in image data&lt;&#x2F;li&gt;
&lt;li&gt;Extracted faces by running a tensorflow session&lt;&#x2F;li&gt;
&lt;li&gt;Saved the results of that session back to the image&lt;&#x2F;li&gt;
&lt;li&gt;Wrote out the file&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you got stuck at any point, have a look at the repository here: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;mtcnn&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;mtcnn&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Hopefully this gives you a good introduction to using tensorflow in rust&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>TMQ 0.1.0 Release: ZeroMQ bindings for Tokio</title>
          <pubDate>Thu, 07 Feb 2019 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/tmq-0-1-0/</link>
          <guid>https://cetra3.github.io/blog/tmq-0-1-0/</guid>
          <description xml:base="https://cetra3.github.io/blog/tmq-0-1-0/">&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;tmq&quot;&gt;TMQ&lt;&#x2F;a&gt; is a rust library to use &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;zeromq.org&#x2F;&quot;&gt;ZeroMQ&lt;&#x2F;a&gt; within the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tokio.rs&#x2F;&quot;&gt;Tokio&lt;&#x2F;a&gt; ecosystem.  ZeroMQ is a distributed messaging queue written in C supporting a number of different messaging patterns.  While there are other options out there (including gRPC, etc..), I settled on ZeroMQ due to its cross-language support, great documentation and battle-tested nature.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;tmq&#x2F;0.1.0&quot;&gt;Version &lt;code&gt;0.1.0&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is an alpha release which implements &lt;code&gt;request&lt;&#x2F;code&gt;, &lt;code&gt;response&lt;&#x2F;code&gt;, &lt;code&gt;publish&lt;&#x2F;code&gt; and &lt;code&gt;subscribe&lt;&#x2F;code&gt; style sockets.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;usage-example&quot;&gt;Usage Example&lt;&#x2F;h2&gt;
&lt;p&gt;This example uses &lt;code&gt;tmq&lt;&#x2F;code&gt; to subscribe to messages, and then prints them out via &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;seanmonstar&#x2F;pretty-env-logger&quot;&gt;pretty-env-logger&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;extern crate&lt;&#x2F;span&gt;&lt;span&gt; failure;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;extern crate&lt;&#x2F;span&gt;&lt;span&gt; futures;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[macro_use]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;extern crate&lt;&#x2F;span&gt;&lt;span&gt; log;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;extern crate&lt;&#x2F;span&gt;&lt;span&gt; pretty_env_logger;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;extern crate&lt;&#x2F;span&gt;&lt;span&gt; tmq;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;extern crate&lt;&#x2F;span&gt;&lt;span&gt; tokio;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; futures&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Future&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Stream&lt;&#x2F;span&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; tmq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::*&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;env;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(_)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;RUST_LOG&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;set_var&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;RUST_LOG&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt; &amp;quot;subscribe=DEBUG&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    pretty_env_logger&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;init&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; request&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; subscribe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;connect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;tcp:&#x2F;&#x2F;127.0.0.1:7899&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Couldn&amp;#39;t connect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;subscribe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            info!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Subscribe: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;as_str&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;unwrap_or&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;            Ok&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;            error!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Error Subscribing: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;    tokio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(request);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Other examples of usage can be found in the project itself: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;tmq&#x2F;tree&#x2F;master&#x2F;examples&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;tmq&#x2F;tree&#x2F;master&#x2F;examples&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;existing-rust-crates&quot;&gt;Existing Rust Crates&lt;&#x2F;h2&gt;
&lt;p&gt;To find out where &lt;code&gt;tmq&lt;&#x2F;code&gt; sits within the rust ecosystem, it makes sense to discuss this in terms of other ZeroMQ crates.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zmq-rust-zeromq-bindings&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;zmq&quot;&gt;zmq&lt;&#x2F;a&gt; - Rust ZeroMQ Bindings&lt;&#x2F;h3&gt;
&lt;p&gt;This library has bindings to the C API and provides a great way to use ZeroMQ within rust.  You still need a copy of ZeroMQ on your system and need it compiled in, but that difficulty is pretty much on par with using OpenSSL.  I have managed to use this library in OSX, CentOS and Ubuntu with not many issues.&lt;&#x2F;p&gt;
&lt;p&gt;The only downside of this library is the lack of bindings to tokio, and is one of the primary motivators for creating &lt;code&gt;tmq&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zmq-rs-a-native-implementation-of-zeromq-in-rust&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zeromq&#x2F;zmq.rs&quot;&gt;zmq.rs&lt;&#x2F;a&gt; - A Native Implementation of ZeroMQ in Rust&lt;&#x2F;h3&gt;
&lt;p&gt;This library was a Rewrite in Rust attempt at a full ZeroMQ reimplementation, which hasn&#x27;t seen any changes &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zeromq&#x2F;zmq.rs&#x2F;commits&#x2F;master&quot;&gt;since 2015&lt;&#x2F;a&gt; and can probably be considered abandoned.  Regardless: this API is still the old blocking style, which would still predicate a need for &lt;code&gt;tmq&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zmq-tokio-run-omq-sockets-using-tokio-reactors-futures-etc&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rotty&#x2F;zmq-tokio&quot;&gt;zmq-tokio&lt;&#x2F;a&gt; - Run ØMQ sockets using tokio reactors, futures, etc.&lt;&#x2F;h3&gt;
&lt;p&gt;Not even published on crates.io but a great initial attempt at bridging the async gap.  This crate used the historic &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;tokio-core&quot;&gt;tokio-core&lt;&#x2F;a&gt; library which is a bit of a pain to adapt to the new &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;tokio&quot;&gt;tokio&lt;&#x2F;a&gt; crate.  Unfortunately it looks like it&#x27;s since &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rotty&#x2F;zmq-tokio&#x2F;pull&#x2F;7&quot;&gt;been abandoned&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tokio-zmq-zeromq-concepts-with-futures-on-tokio-s-runtime&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;tokio-zmq&quot;&gt;tokio-zmq&lt;&#x2F;a&gt; - ZeroMQ Concepts with futures on Tokio&#x27;s runtime&lt;&#x2F;h3&gt;
&lt;p&gt;This library is probably the most polished version for &lt;code&gt;tokio&lt;&#x2F;code&gt; and one that would be compared mostly to &lt;code&gt;tmq&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I would have chosen this library, but the one major roadblock is the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;licenses&#x2F;gpl-3.0.en.html&quot;&gt;GPL&lt;&#x2F;a&gt; license.  The GPL within a rust project is viral.  You can&#x27;t use this library without making the rest of your project GPL or GPL Compatible. If this doesn&#x27;t concern you, then I would consider using this library.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;comparison-between-tmq&quot;&gt;Comparison between tmq&lt;&#x2F;h3&gt;
&lt;p&gt;In comparison to &lt;code&gt;tokio-zmq&lt;&#x2F;code&gt;, &lt;code&gt;tmq&lt;&#x2F;code&gt; has less boilerplate to acheive the same thing, but does use a couple of custom traits to speed things along.  This makes &lt;code&gt;tmq&lt;&#x2F;code&gt; a bit more opinionated, but less verbose.&lt;&#x2F;p&gt;
&lt;p&gt;Both styles have their merits, &lt;code&gt;tokio-zmq&lt;&#x2F;code&gt; does give you more control over things wheras &lt;code&gt;tmq&lt;&#x2F;code&gt; is, in my opinion, easier to write and reason about, but more restrictive in how you use it.&lt;&#x2F;p&gt;
&lt;p&gt;To do a direct comparison of both libraries we&#x27;re using the &lt;code&gt;response&lt;&#x2F;code&gt; example.  This example is a simple echo response, which when it receives a message, it echos it back verbatim to the requester.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;tokio-zmq&quot;&gt;tokio-zmq&lt;&#x2F;h4&gt;
&lt;p&gt;Here is the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.asonix.dog&#x2F;asonix&#x2F;async-zmq&#x2F;src&#x2F;branch&#x2F;development&#x2F;tokio-zmq&#x2F;examples&quot;&gt;excerpt&lt;&#x2F;a&gt; from &lt;code&gt;tokio-zmq&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ctx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Arc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;zmq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; req_fut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Req&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;builder&lt;&#x2F;span&gt;&lt;span&gt;(ctx)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;connect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;tcp:&#x2F;&#x2F;localhost:5560&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; runner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; req_fut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;req&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    req&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;build_multipart&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;req&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; (sink, stream)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; req&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;sink_stream&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;25&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        stream&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;zip&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;iter_ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DFBFFF;&quot;&gt;10_000&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;(multipart, i)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;                for&lt;&#x2F;span&gt;&lt;span&gt; msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; multipart {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;                    if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(msg)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;as_str&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;                        println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Received: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, msg);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;                build_multipart&lt;&#x2F;span&gt;&lt;span&gt;(i)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;forward&lt;&#x2F;span&gt;&lt;span&gt;(sink)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;});&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On of the things you will notice is there is a lot of standard &lt;code&gt;futures&lt;&#x2F;code&gt; and &lt;code&gt;tokio&lt;&#x2F;code&gt; types used here: &lt;code&gt;sink&lt;&#x2F;code&gt;, &lt;code&gt;stream&lt;&#x2F;code&gt;, etc..  While this does make it more verbose, you are using constructs that you are familiar with in the futures style.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tmq&quot;&gt;tmq&lt;&#x2F;h3&gt;
&lt;p&gt;Here&#x27;s a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;tmq&#x2F;blob&#x2F;master&#x2F;examples&#x2F;response.rs&quot;&gt;similar example&lt;&#x2F;a&gt; (although not using &lt;code&gt;multipart&lt;&#x2F;code&gt; messages) from &lt;code&gt;tmq&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CCCAC2; background-color: #1F2430;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA659;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; responder&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt; respond&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;bind&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;tcp:&#x2F;&#x2F;127.0.0.1:7899&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt; Message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;        info!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;Request: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;as_str&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F29E74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFCD66;&quot;&gt;unwrap_or&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D5FF80;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #73D0FF;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(msg)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You&#x27;ll notice that the library has a bit less boilerplate, but is more opinionated on how you structure a response.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of a &lt;code&gt;sink&#x2F;stream&lt;&#x2F;code&gt; approach, the responder is a stream but has a &lt;code&gt;with&lt;&#x2F;code&gt; method.  The &lt;code&gt;with&lt;&#x2F;code&gt; method takes anything that implements the &lt;code&gt;Responder&lt;&#x2F;code&gt; trait, of which there is a blanket implemenation for closures and functions that take a message and return a message.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-changes&quot;&gt;Future Changes&lt;&#x2F;h2&gt;
&lt;p&gt;While currently usable, the &lt;code&gt;tmq&lt;&#x2F;code&gt; library is far from finished and requires some work to bring it out of an alpha state.  In no particular order here are the plans for the library:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;testing&quot;&gt;Testing&lt;&#x2F;h4&gt;
&lt;p&gt;Unit tests and integration tests need to be added in order to confirm and wire up connections.  As the library is rather lightweight now the need for integration tests hasn&#x27;t really arisen, but this will become more complicated in the future as more socket types are added.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;benchmarking&quot;&gt;Benchmarking&lt;&#x2F;h4&gt;
&lt;p&gt;Benchmarks need to be added to the library in order to show the performance of using this over standard &lt;code&gt;zmq&lt;&#x2F;code&gt;.  Running up some dummy benchmarks show that it is perfomant enough for my current use case, and provides less overhead than your standard REST API calls.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;windows-support&quot;&gt;Windows Support&lt;&#x2F;h4&gt;
&lt;p&gt;I &lt;em&gt;cheated&lt;&#x2F;em&gt; a little by using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;mio&#x2F;0.6.16&#x2F;mio&#x2F;event&#x2F;trait.Evented.html&quot;&gt;Evented&lt;&#x2F;a&gt; trait for mio, which makes it dead easy to use in tokio via &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;0.1.15&#x2F;tokio&#x2F;reactor&#x2F;struct.PollEvented2.html&quot;&gt;PollEvented2&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately the async story on windows is a bit different, and I haven&#x27;t had a need to deploy on windows just yet.  But it is something that has been considered.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;documentation&quot;&gt;Documentation&lt;&#x2F;h4&gt;
&lt;p&gt;The library is mostly undocumented besides from the examples.  Documentation should be pretty easy to do at this stage and won&#x27;t take too long.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;more-socket-types&quot;&gt;More Socket Types&lt;&#x2F;h4&gt;
&lt;p&gt;Implementing more socket types, to make this feature complete with the standard &lt;code&gt;zmq&lt;&#x2F;code&gt; library.  There a plethora of different socket types for different use cases that give different guarantees.  The 4 standard ones implemented are enough for me to start using this library today, but could easily be expanded.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;multipart-messages&quot;&gt;Multipart messages&lt;&#x2F;h4&gt;
&lt;p&gt;Multipart support for messages.  Currently this is not supported, but should be mostly easy to implement&lt;&#x2F;p&gt;
&lt;h2 id=&quot;further-thoughts&quot;&gt;Further thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;m currently using &lt;code&gt;tmq&lt;&#x2F;code&gt; within an &lt;code&gt;actix-web&lt;&#x2F;code&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.schoolbench.com.au&#x2F;&quot;&gt;application&lt;&#x2F;a&gt; to bridge some messages and audit logs between a polyglot backend (including Java &amp;amp; Python).  It has been quite solid so far, and I have plans to remove an existing ActiveMQ service to be replaced with &lt;code&gt;tmq&lt;&#x2F;code&gt; where appropriate.&lt;&#x2F;p&gt;
&lt;p&gt;Version &lt;code&gt;0.1.0&lt;&#x2F;code&gt; is the first real release, with previous releases having to vendor in the &lt;code&gt;zmq&lt;&#x2F;code&gt; library in order to publish.   While it is alpha, I don&#x27;t plan to change what is there currently unless there is a compelling reason to do so.&lt;&#x2F;p&gt;
&lt;p&gt;Please give &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;tmq&quot;&gt;tmq&lt;&#x2F;a&gt; a try and let me know your thoughts!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>My Wishes for Rust 2019</title>
          <pubDate>Fri, 14 Dec 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://cetra3.github.io/blog/rust-2019/</link>
          <guid>https://cetra3.github.io/blog/rust-2019/</guid>
          <description xml:base="https://cetra3.github.io/blog/rust-2019/">&lt;p&gt;2018 was a massive year for rust, and it&#x27;s great to reflect back on how far we&#x27;ve all come.  My main wish for the new year is to put on the breaks a little bit, and finish off what has been started without taking on anything majorly new.&lt;&#x2F;p&gt;
&lt;p&gt;There are a couple of areas that I feel need more attention than most (purely for selfish reasons of course!):&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compiler-times-ide-support-and-rls&quot;&gt;Compiler Times, IDE Support and RLS&lt;&#x2F;h2&gt;
&lt;p&gt;I think RLS is great.  I think &lt;code&gt;cargo check&lt;&#x2F;code&gt; is great too.  Sometimes when I am waiting for RLS to finish in VSCode, I run &lt;code&gt;cargo check&lt;&#x2F;code&gt; in a terminal to see who wins the race.  Sometimes I get results faster from the &lt;code&gt;cargo check&lt;&#x2F;code&gt; than I do in RLS.  I&#x27;m not sure why that is, it might be that I&#x27;m making a lot of small edits, and RLS is constantly restarting. I am assuming that the plumbing for both methods is rather similar.  On average, if I just adjust whitespace on one of my projects, it takes at least 10 seconds to recompile.  If I change any trivial bit of code, this doubles to 20 seconds.&lt;&#x2F;p&gt;
&lt;p&gt;I would love to have dynamic loading in rust as a first class citizen, but I fear the ABI stabilisation is a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;issues&#x2F;600&quot;&gt;far way off&lt;&#x2F;a&gt; (I know you can &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;michael-f-bryan.github.io&#x2F;rust-ffi-guide&#x2F;dynamic_loading.html&quot;&gt;cheat&lt;&#x2F;a&gt; by using the C ABI and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nagisa&#x2F;rust_libloading&quot;&gt;libloading&lt;&#x2F;a&gt; but there is a fair amount of &lt;code&gt;unsafe&lt;&#x2F;code&gt; code, which I&#x27;m not comfortable with).  This would alleviate some of the issues around compilation times, by allowing compilation to be broken up into smaller chunks.&lt;&#x2F;p&gt;
&lt;p&gt;For instance: I implemented a WebDAV handler with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;actix&#x2F;actix-web&quot;&gt;actix-web&lt;&#x2F;a&gt;.  This added a significant portion of time to compilation after the implementation was finished, and the code is mostly decoupled from the rest of the app and sits in its own little route (XML instead of JSON, etc..).  I&#x27;d love to be able to just hot-load this as a module, rather than compile it in each time if I&#x27;m not even touching this part.  Incremental compilation does help a little bit here.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;better-ide-support&quot;&gt;Better IDE Support&lt;&#x2F;h3&gt;
&lt;p&gt;I have been using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;code.visualstudio.com&#x2F;&quot;&gt;VSCode&lt;&#x2F;a&gt; as my primary rust IDE for a while now, which is great, but I&#x27;d love to be able to use IntelliJ as well.  Each time there is an update, I do give it another shot, and find that there are a couple of problems with it:&lt;&#x2F;p&gt;
&lt;div style=&#x27;position:relative; padding-bottom:53.68%&#x27;&gt;&lt;iframe src=&#x27;https:&#x2F;&#x2F;gfycat.com&#x2F;ifr&#x2F;SmallCarefulDiamondbackrattlesnake&#x27; frameborder=&#x27;0&#x27; scrolling=&#x27;no&#x27; width=&#x27;100%&#x27; height=&#x27;100%&#x27; style=&#x27;position:absolute;top:0;left:0;&#x27; allowfullscreen&gt;&lt;&#x2F;iframe&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;Weeeeeeeeeeeeeeeeeeeeeee&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Admittedly, each release of the IntelliJ rust plugin is better than the last, but it is not even close to the support that Java has.  I am hoping that this changes in the future.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d also love to be able to give &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.onivim.io&#x2F;&quot;&gt;Oni&lt;&#x2F;a&gt; a go, but currently it&#x27;s in limbo until I, or someone else, has enough time to work out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;onivim&#x2F;oni&#x2F;issues&#x2F;1926&quot;&gt;what is wrong&lt;&#x2F;a&gt; with the Language Server Integration.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;async-await&quot;&gt;Async&#x2F;Await&lt;&#x2F;h2&gt;
&lt;p&gt;I would really love to see the async&#x2F;await story come to a close in 2019.  The rust team has laid the groundwork with the 2018 edition, and together with the new &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;boats.gitlab.io&#x2F;blog&#x2F;post&#x2F;2018-04-06-async-await-final&#x2F;&quot;&gt;pinning API&lt;&#x2F;a&gt; I feel like it&#x27;s &lt;em&gt;just&lt;&#x2F;em&gt; around the corner.  This has the opportunity to really change the landscape and make rust a much more productive language.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve had a crack at writing both a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;mpart-async&#x2F;&quot;&gt;multipart client&lt;&#x2F;a&gt; &amp;amp; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cetra3&#x2F;tmq&quot;&gt;ZeroMQ library&lt;&#x2F;a&gt;, but I can see that when the async stuff reaches stable, it&#x27;s going to make life a lot easier.   Kudos to the team for moving this forward (I also happen to think the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;rust-lang-nursery.github.io&#x2F;futures-rs&#x2F;assets&#x2F;images&#x2F;futures-rs-logo.svg&quot;&gt;logo&lt;&#x2F;a&gt; for &lt;code&gt;futures-rs&lt;&#x2F;code&gt; is pretty rad!)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;documentation-churn&quot;&gt;Documentation Churn&lt;&#x2F;h3&gt;
&lt;p&gt;With these changes to async, there is going to be some challenges around documentation.  I feel in tokio-land there is a high degree of tribal knowledge that, if you don&#x27;t keep up with things, you are left behind.&lt;&#x2F;p&gt;
&lt;p&gt;There is the new &lt;code&gt;futures 0.3&lt;&#x2F;code&gt; crate, which is not currently in use by tokio crate, you have to use futures &lt;code&gt;0.1&lt;&#x2F;code&gt;.  No-one knows what happened to &lt;code&gt;0.2&lt;&#x2F;code&gt;, it&#x27;s a mystery left for future rust historians, and &lt;code&gt;0.3&lt;&#x2F;code&gt; is still very much in &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;rust-lang-nursery.github.io&#x2F;futures-rs&#x2F;blog&#x2F;2018&#x2F;09&#x2F;02&#x2F;futures-0.3.0-alpha.4.html&quot;&gt;alpha&lt;&#x2F;a&gt;. Earlier on in the year if you went straight to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;&quot;&gt;docs.rs page&lt;&#x2F;a&gt; for futures, this would direct you to the &lt;code&gt;0.3&lt;&#x2F;code&gt; version, which isn&#x27;t helpful if you are using this in conjunction with tokio (this appears to be resolved now, by some clever use of yanking).&lt;&#x2F;p&gt;
&lt;p&gt;Another example is the move away from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;tokio-core&quot;&gt;tokio-core&lt;&#x2F;a&gt; into the standard &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;tokio&quot;&gt;tokio&lt;&#x2F;a&gt; crate.  This is something that is a great evolution for tokio, but has left a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;tokio-core&#x2F;reverse_dependencies&quot;&gt;number of libraries&lt;&#x2F;a&gt; outdated.  A lot of the great blogs by pioneering devs have also become outdated when dealing with this, which increases the frustration for any newcomers.  I am hoping that now things are more &lt;em&gt;settled&lt;&#x2F;em&gt; that this won&#x27;t be much of an issue.&lt;&#x2F;p&gt;
&lt;p&gt;All of these changes adds to a high level of fatigue for developers.  If you&#x27;re not lucky enough to be working in this space day-to-day, coming back after 6 months would be daunting.  There is a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;doc-push&quot;&gt;push to help modernise the documentation&lt;&#x2F;a&gt;, but this hasn&#x27;t seen much activity in a couple of months.  I&#x27;m hoping to find some time in the new year to help out with this, as I think there is a lot of work to be done.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I think rust has come a long way and still has a long way to go.  I focused a lot of energy on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.schoolbench.com.au&#x2F;&quot;&gt;writing apps&lt;&#x2F;a&gt; in rust this year, and will undoubtably accelerate the usage as time goes on.&lt;&#x2F;p&gt;
&lt;p&gt;I hope that the rust team has time to put on the breaks, and apply a bit of polish before doing anything major.  I also hope I have more time to contribute some bits and pieces here and there to make the community better.&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
