<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Domain Specific Language</title>
    <link rel="self" type="application/atom+xml" href="https://zkc.se/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://zkc.se"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-03-13T00:00:00+00:00</updated>
    <id>https://zkc.se/atom.xml</id>
    <entry xml:lang="en">
        <title>Being STOMP Agnostic</title>
        <published>2026-03-13T00:00:00+00:00</published>
        <updated>2026-03-13T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/stomp-agnostic/"/>
        <id>https://zkc.se/blog/stomp-agnostic/</id>
        <content type="html" xml:base="https://zkc.se/blog/stomp-agnostic/">&lt;p&gt;I needed a STOMP library, and my search for one written in Rust ended up with
a fork and a library that I&#x27;m happy with!&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;In this blog post I will try to do the following things&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Introduce you to STOMP&lt;&#x2F;li&gt;
&lt;li&gt;Go through the current landscape of Rust STOMP libraries and explain why none of them scratch my itch&lt;&#x2F;li&gt;
&lt;li&gt;Find a suitable library to fork, so that we may stand on the shoulders of others&lt;&#x2F;li&gt;
&lt;li&gt;Propose a runtime and transport agnostic design for a STOMP library and implement it as &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bes&#x2F;stomp-agnostic&quot;&gt;stomp-agnostic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;what-is-stomp&quot;&gt;What is STOMP&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;strong&gt;STOMP&lt;&#x2F;strong&gt; stands for Simple Text Oriented Messaging Protocol. If you have a need
for sending and receiving text messages in real time using a client-server model,
and you don&#x27;t have fancy needs, this is the protocol for you. STOMP has been
around for a long time; the latest version,
&lt;a href=&quot;https:&#x2F;&#x2F;stomp.github.io&#x2F;stomp-specification-1.2.html&quot;&gt;STOMP 1.2&lt;&#x2F;a&gt;, was published
in 2012.&lt;&#x2F;p&gt;
&lt;p&gt;The protocol itself is simple and easy-to-understand, and is usually
used together with the WebSocket communication protocol in browsers, but can
be used over TCP or any other protocol as the transport layer.
STOMP is supported by a lot of software: RabbitMQ,
Spring Framework, and is also commonly used to support real-time updates
in web applications.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Transport layer&lt;&#x2F;em&gt; is used a bit lax in the previous section; in the OSI model,
TCP is at the Transport layer (layer 4), while HTTP and WebSocket are at the
Application layer (layer 7), the same as STOMP. However, when we are in a browser
we don&#x27;t have direct access to TCP&#x2F;layer 4, so we &lt;em&gt;transport&lt;&#x2F;em&gt; the STOMP data
using a WebSocket connection.&lt;&#x2F;p&gt;
&lt;p&gt;Communicating using STOMP is done using &lt;em&gt;Frames&lt;&#x2F;em&gt;. A frame is a verb plus some
data; similar to HTTP verbs, but with a broader vocabulary.
There are two connection frames: &lt;code&gt;CONNECT&lt;&#x2F;code&gt; and &lt;code&gt;CONNECTED&lt;&#x2F;code&gt;, nine standard client
frames: &lt;code&gt;SEND&lt;&#x2F;code&gt;, &lt;code&gt;SUBSCRIBE&lt;&#x2F;code&gt;, &lt;code&gt;UNSUBSCRIBE&lt;&#x2F;code&gt;, &lt;code&gt;ACK&lt;&#x2F;code&gt;, &lt;code&gt;NACK&lt;&#x2F;code&gt;, &lt;code&gt;BEGIN&lt;&#x2F;code&gt;, &lt;code&gt;COMMIT&lt;&#x2F;code&gt;, &lt;code&gt;ABORT&lt;&#x2F;code&gt; and
&lt;code&gt;DISCONNECT&lt;&#x2F;code&gt;, and three standard server frames: &lt;code&gt;MESSAGE&lt;&#x2F;code&gt;, &lt;code&gt;RECEIPT&lt;&#x2F;code&gt;, and &lt;code&gt;ERROR&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;quote&quot;&gt;
    &lt;p&gt;&lt;em&gt;Three Rings for the Elven-kings under the sky,&lt;&#x2F;em&gt;&lt;br &#x2F;&gt;
&lt;em&gt;Seven for the Dwarf-lords in their halls of stone,&lt;&#x2F;em&gt;&lt;br &#x2F;&gt;
&lt;em&gt;Nine for Mortal Men doomed to die&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

    &lt;div class=&quot;quote-title&quot;&gt;(sorry)&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Using the client and server frames, it&#x27;s possible to build a robust communication
channel between a client and a server. A simple conversation would go something
like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; class=&quot;language-text z-code&quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Client                                                          Server     
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                  
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  │  CONNECT (accept-version=1.1,1.2, host:stomp.zkc.se, ...)      │ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  ├───────────────────────────────────────────────────────────────►│ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  │  CONNECTED (version=1.2, session=xyz, ... )                    │ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  │◄───────────────────────────────────────────────────────────────┤
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  |                                                                | 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  |                             ...                                | 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  |                                                                | 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  |                                                                | 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  │  SUBSCRIBE (id=sub-0, destination=&#x2F;dest, ...)                  │ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  ├───────────────────────────────────────────────────────────────►│ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  |                                                                | 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  |                             ...                                | 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  |                                                                | 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  |                                                                | 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  │  MESSAGE (subscription=sub-0, message-id=0, destination=&#x2F;dest, │ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  │           data=JSON {...})                                     │ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  │◄───────────────────────────────────────────────────────────────┤ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  │  MESSAGE (subscription=sub-0, message-id=1, destination=&#x2F;dest, │ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  │           data=JSON {...})                                     │ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  │◄───────────────────────────────────────────────────────────────┤ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  |                                                                | 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  |                             ...                                | 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  │                                                                │ 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since the protocol is so simple and each frame type typically only requires a
few pieces of data (e.g. SUBSCRIBE only needs an id and a destination) it&#x27;s
very easy to wrap your head around the whole thing in a very short time. Just
click the link above and start reading. It&#x27;s not harder than that, really.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-search-for-a-rust-stomp-crate-that-fits-the-bill&quot;&gt;The search for a Rust STOMP crate that fits the bill&lt;&#x2F;h1&gt;
&lt;p&gt;What I need: A library, written in Rust, that I can use to implement several
clients using WebSocket as the transport layer, but with wildly different
platforms: Desktop &amp;amp; Mobile applications have access to real operating systems
and have good support for Tokio, but I also need support for Web&#x2F;WASM that has a
hard time running Tokio. Web browsers have their own APIs for opening WebSockets.
I also need to implement at least one server that uses WebSocket as the transport
layer.&lt;&#x2F;p&gt;
&lt;p&gt;A quick survey of the STOMP landscape in Rust shows that there
are plenty of STOMP libraries, around 20 on &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;search?q=stomp&quot;&gt;lib.rs&lt;&#x2F;a&gt;
at the time of writing.
I had a quick look at many of them, but they all have something that make them not
a great fit for what I need.&lt;&#x2F;p&gt;
&lt;div class=&quot;hscroll&quot;&gt;
    &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;crate&lt;&#x2F;th&gt;&lt;th&gt;notes&lt;&#x2F;th&gt;&lt;th&gt;Runtime&lt;&#x2F;th&gt;&lt;th&gt;transport&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;async-stomp&lt;&#x2F;td&gt;&lt;td&gt;Has its own client and server types.&lt;&#x2F;td&gt;&lt;td&gt;Tokio&lt;&#x2F;td&gt;&lt;td&gt;TCP&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;stomp&lt;&#x2F;td&gt;&lt;td&gt;Callback API (not async)&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;td&gt;TCP&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;wstomp&lt;&#x2F;td&gt;&lt;td&gt;Somehow uses both actix and Tokio...&lt;&#x2F;td&gt;&lt;td&gt;awc &#x2F; actix&lt;&#x2F;td&gt;&lt;td&gt;WebSocket&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;stomp-parser&lt;&#x2F;td&gt;&lt;td&gt;&quot;Just a parser&quot;&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;iridium-stomp&lt;&#x2F;td&gt;&lt;td&gt;Has its own client type&lt;&#x2F;td&gt;&lt;td&gt;Tokio&lt;&#x2F;td&gt;&lt;td&gt;TCP&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;There is a trend here: Almost every library except for &lt;code&gt;wstomp&lt;&#x2F;code&gt; and
&lt;code&gt;stomp-parser&lt;&#x2F;code&gt; use TCP transport, and I need to use WebSocket as the transport
layer.
The crate for WebSocket communication I want to use is
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;snapview&#x2F;tokio-tungstenite&quot;&gt;tokio-tungstenite&lt;&#x2F;a&gt; but no
existing STOMP library I found offers that.&lt;&#x2F;p&gt;
&lt;p&gt;Furthermore, every library except for &lt;code&gt;stomp-parser&lt;&#x2F;code&gt; and &lt;code&gt;stomp&lt;&#x2F;code&gt; are tied to a
specific async runtime. At Spiideo we are building more and more cross-platform
functionality in Rust that is supposed to work across iOS, Web, Desktop, Backend,
and Android. Using Tokio or other async runtimes in the browser is not worth it
in my experience; &lt;code&gt;wasm-bindgen-futures&lt;&#x2F;code&gt; is enough if you design your software
to be async without using runtime specific functionality.&lt;&#x2F;p&gt;
&lt;p&gt;Of the existing choices, none fit the bill.&lt;&#x2F;p&gt;
&lt;p&gt;It would be great to have a STOMP library that is pluggable. Since
STOMP is such a simple protocol (it really is very simple), it should be possible
to build a library that is more than a parser, but also doesn&#x27;t go all the way
to mandate a specific transport protocol.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;finding-a-fork&quot;&gt;Finding a fork&lt;&#x2F;h1&gt;
&lt;p&gt;Out of the available choices, &lt;code&gt;async-stomp&lt;&#x2F;code&gt; seems the best fit for what I want
to do. &lt;code&gt;async-stomp&lt;&#x2F;code&gt; was relicensed to use the &lt;a href=&quot;https:&#x2F;&#x2F;eupl.eu&#x2F;&quot;&gt;EUPL&lt;&#x2F;a&gt; license
in addition to the original MIT license. I&#x27;m very much not a license expert, but
the EUPL seems like a reasonable license. I am actually a fan of the EU&#x27;s work
in this field, especially the &lt;a href=&quot;https:&#x2F;&#x2F;zkc.se&#x2F;blog&#x2F;fosdem-2026&#x2F;#interoperability-regulation-in-the-eu-opening-ios-and-android-for-free-software&quot;&gt;DMA Enforcement Team&lt;&#x2F;a&gt;,
so I&#x27;m not even going to try to do anything about the license.&lt;&#x2F;p&gt;
&lt;p&gt;Comically, &lt;code&gt;async-stomp&lt;&#x2F;code&gt; is a fork of &lt;code&gt;tokio-stomp-2&lt;&#x2F;code&gt;, which is a fork of
&lt;code&gt;tokio-stomp&lt;&#x2F;code&gt;. I don&#x27;t think it is out of character to fork it once more.&lt;&#x2F;p&gt;
&lt;div class=&quot;quote&quot;&gt;
    &lt;p&gt;If you don&#x27;t know what you are doing, use the original tokio-stomp&lt;&#x2F;p&gt;

    &lt;div class=&quot;quote-title&quot;&gt;Caveat Emptor: tokio-stomp-2&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Fun quote I found in the &lt;code&gt;tokio-stomp-2&lt;&#x2F;code&gt; repository while researching 👆.
At what point am I expected to know what I am doing?&lt;&#x2F;p&gt;
&lt;h1 id=&quot;how-do-we-fork&quot;&gt;How do we fork?&lt;&#x2F;h1&gt;
&lt;p&gt;There are some juicy parts that we are going to need and some parts that we are
going to rip right out of &lt;code&gt;async-stomp&lt;&#x2F;code&gt;. The main things to keep are the &lt;code&gt;Frame&lt;&#x2F;code&gt;
and &lt;code&gt;Message&lt;&#x2F;code&gt; types, both of which represent a STOMP frame: A &lt;code&gt;Message&lt;&#x2F;code&gt; is the
high-level variety and &lt;code&gt;Frame&lt;&#x2F;code&gt; contains the bytes received or to-be-sent. The
throwing away part is easy: anything that has to do with TCP transport or Tokio.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;Message&lt;&#x2F;code&gt; type comes in two flavors: &lt;code&gt;Message&amp;lt;FromServer&amp;gt;&lt;&#x2F;code&gt; and
&lt;code&gt;Message&amp;lt;ToServer&amp;gt;&lt;&#x2F;code&gt;. The nomenclature is client centric, but I don&#x27;t think
renaming &lt;code&gt;Message&amp;lt;FromServer&amp;gt;&lt;&#x2F;code&gt; to &lt;code&gt;Message&amp;lt;ToClient&amp;gt;&lt;&#x2F;code&gt; would help. Either way
you are doing some sort of purpose inversion in your head when implementing
either the client or server parts. Adding type aliases might help, but I don&#x27;t
think it would help much.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;designing-an-agnostic-interface&quot;&gt;Designing an agnostic interface&lt;&#x2F;h1&gt;
&lt;p&gt;The two axes I want to design along are freedom to choose whatever transport
you want and the madness to use whatever async runtime you want.&lt;&#x2F;p&gt;
&lt;p&gt;We are going to need two simple-to-implement traits for the transport layer, one
for the client transport and one for the server transport. On top of that we are
going to have handles for the client and server parts of STOMP.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;ClientTransport&lt;&#x2F;code&gt; and &lt;code&gt;ServerTransport&lt;&#x2F;code&gt; traits are similar from a design
point-of-view so there is no use exploring the design of more than one; for
convenience we will look at the client side of things.&lt;&#x2F;p&gt;
&lt;p&gt;The implementation can be found at &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bes&#x2F;stomp-agnostic&quot;&gt;github.com&#x2F;bes&#x2F;stomp-agnostic&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;clienttransport&quot;&gt;ClientTransport&lt;&#x2F;h2&gt;
&lt;p&gt;An important detail for the transport layer is going to be an escape hatch for
dealing with protocol-specific communication. For example, a WebSocket connection
has Ping and Pong messages, which are not part of STOMP but need to be handled
if they come down the wire.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the trait for &lt;code&gt;ClientTransport&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-annotation z-rust&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-annotation z-rust&quot;&gt;async_trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-trait z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-trait z-rust&quot;&gt;trait&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-trait z-rust&quot;&gt;ClientTransport&lt;&#x2F;span&gt;: Send + Sync &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-trait z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-documentation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt; A side channel to shuffle arbitrary data that is not part of the STOMP communication,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-trait z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-documentation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt; e.g. WebSocket Ping&#x2F;Pong.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-trait z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-type z-type z-rust&quot;&gt;type&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-rust&quot;&gt;ProtocolSideChannel&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-trait z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-trait z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    async &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;write&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;, &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Message&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;ToServer&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;, WriteError&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-trait z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    async &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;read&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;ReadData&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;ProtocolSideChannel&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;, ReadError&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-trait z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Reading is a matter of getting bytes from some source and then buffering until
we have a full &lt;code&gt;Message&amp;lt;FromServer&amp;gt;&lt;&#x2F;code&gt;. Writing similarly is a matter of
converting the given &lt;code&gt;Message&amp;lt;ToServer&amp;gt;&lt;&#x2F;code&gt; to bytes using the &lt;code&gt;.into_bytes&lt;&#x2F;code&gt; method and sending
them down the wire. Taking a &lt;code&gt;Message&amp;lt;ToServer&amp;gt;&lt;&#x2F;code&gt; instead of just raw bytes for
&lt;code&gt;.write&lt;&#x2F;code&gt; makes it impossible (or at least very hard) to misuse the transport trait.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;ReadData&lt;&#x2F;code&gt; is a simple enum; either bytes (STOMP data) or some special type
&lt;code&gt;T&lt;&#x2F;code&gt; (&lt;code&gt;Self::ProtocolSideChannel&lt;&#x2F;code&gt; in our case) that belongs to the transport
protocol.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-documentation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt; Data coming down the line from the transport layer. When the transport layer is
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-documentation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt; e.g. WebSocket, custom data such as Ping&#x2F;Pong can be handled separately from STOMP data
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-documentation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt; by using the `Custom` variant.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-annotation z-rust&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-annotation z-rust&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-enum z-rust&quot;&gt;enum&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-enum z-rust&quot;&gt;ReadData&lt;&#x2F;span&gt;&amp;lt;T&amp;gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    Binary&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;Bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    Custom&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;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;ProtocolSideChannel&lt;&#x2F;code&gt; can be as simple as &lt;code&gt;()&lt;&#x2F;code&gt; but for WebSocket it will need
to be an enum for the special cases.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-enum z-rust&quot;&gt;enum&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-enum z-rust&quot;&gt;WebsocketProto&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    Ping&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;Bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    Pong&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;Bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice that to keep the trait simplish, I decided not to be able to send
&lt;code&gt;ProtocolSideChannel&lt;&#x2F;code&gt; data through the &lt;code&gt;ClientTransport&lt;&#x2F;code&gt; trait, only to receive
it through read. This doesn&#x27;t stop us from sending a WebSocket Ping though,
since the design of the handle allows us to temporarily (or permanently) drop
down to transport level and get a hold of the original type.&lt;&#x2F;p&gt;
&lt;p&gt;The magic, if you will, is in &lt;code&gt;transport::client::BufferedTransport&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-rust&quot;&gt;crate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-struct z-rust&quot;&gt;struct&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-entity z-name z-struct z-rust&quot;&gt;BufferedTransport&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;T&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;where
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;    T: ClientTransport,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;    T::ProtocolSideChannel: Debug,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-variable z-other z-member z-rust&quot;&gt;transport&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-type z-rust&quot;&gt;:&lt;&#x2F;span&gt; T,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-variable z-other z-member z-rust&quot;&gt;buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-type z-rust&quot;&gt;:&lt;&#x2F;span&gt; BytesMut,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;BufferedTransport&lt;&#x2F;code&gt; holds on to an implementation of &lt;code&gt;ClientTransport&lt;&#x2F;code&gt;. As we
receive data from the transport, it&#x27;s buffered in a &lt;code&gt;BytesMut&lt;&#x2F;code&gt; until we can
read a whole &lt;code&gt;Frame&lt;&#x2F;code&gt;. When we are not waiting on a &lt;code&gt;.read&lt;&#x2F;code&gt; or &lt;code&gt;.write&lt;&#x2F;code&gt; we can
get a hold of the underlying transport through &lt;code&gt;BufferedTransport&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-rust&quot;&gt;crate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;into_transport&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; T&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;transport
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-rust&quot;&gt;crate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;as_mut_inner&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; T&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;transport
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unfortunately &lt;code&gt;BufferedTransport&lt;&#x2F;code&gt; is crate-private, but the methods are proxied
through &lt;code&gt;ClientStompHandle&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;clientstomphandle&quot;&gt;ClientStompHandle&lt;&#x2F;h2&gt;
&lt;p&gt;The handle type is really just a very thin wrapper around the &lt;code&gt;BufferedTransport&lt;&#x2F;code&gt;,
but you can only get a &lt;code&gt;ClientStompHandle&lt;&#x2F;code&gt; using the &lt;code&gt;ClientStompHandle::connect&lt;&#x2F;code&gt;
associated function, which makes sure to do a successful STOMP client handshake.&lt;&#x2F;p&gt;
&lt;p&gt;Once you have a &lt;code&gt;ClientStompHandle&lt;&#x2F;code&gt; it&#x27;s time to rock&#x27;n&#x27;roll&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-impl z-rust&quot;&gt;impl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;T&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt; &lt;span class=&quot;z-entity z-name z-impl z-rust&quot;&gt;ClientStompHandle&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;T&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-keyword z-other z-rust&quot;&gt;where&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;    T&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; ClientTransport,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;ProtocolSideChannel&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; Debug,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-documentation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt; Send a STOMP message through the underlying transport
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; async &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;send_message&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;, &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Message&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;ToServer&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;, WriteError&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;transport&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;send&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;await
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-documentation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt; Read a STOMP message from the underlying transport
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; async &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;read_response&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;        &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;ServerResponse&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;ProtocolSideChannel&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;, ReadError&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;transport&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;next&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;await
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;implementing-a-websocket-client-transport&quot;&gt;Implementing a WebSocket client transport&lt;&#x2F;h1&gt;
&lt;p&gt;There are simple and functional, but not fully fleshed out, examples in the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bes&#x2F;stomp-agnostic&#x2F;tree&#x2F;main&#x2F;examples&quot;&gt;stomp-agnostic repository&lt;&#x2F;a&gt;.
The client example code uses &lt;code&gt;tokio-tungstenite&lt;&#x2F;code&gt; to create a WebSocket client
and the server example uses &lt;code&gt;axum&lt;&#x2F;code&gt; to expose an endpoint that can be turned into
a WebSocket connection.&lt;&#x2F;p&gt;
&lt;p&gt;Since there are only three server frames to consider, plus the underlying WebSocket protocol,
it doesn&#x27;t take much to implement the full &lt;code&gt;ClientTransport&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-annotation z-rust&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-annotation z-rust&quot;&gt;async_trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-impl z-rust&quot;&gt;impl&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;ClientTransport &lt;span class=&quot;z-keyword z-other z-rust&quot;&gt;for&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt; &lt;span class=&quot;z-entity z-name z-impl z-rust&quot;&gt;WsTransport&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-type z-type z-rust&quot;&gt;type&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-rust&quot;&gt;ProtocolSideChannel&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; WebsocketProto&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    async &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;write&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;        &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;        &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;stomp_agnostic&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Message&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;ToServer&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;, WriteError&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; bytes &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; message&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;into_bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Check that bytes is valid UTF-8!
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; NOTE: This is part of the safety, do not remove!
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;_&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;from_utf8&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; ws_message &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Message&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Text&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;            &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Safety: We checked that bytes are valid UTF-8 above
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;            &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;unsafe&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Utf8Bytes&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;from_bytes_unchecked&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;ws_stream
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;send&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;ws_message&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;await
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-closure z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-closure z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-closure z-rust&quot;&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;WriteError&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Other&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-macro z-rust&quot;&gt;anyhow!&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    async &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;read&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;ReadData&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;ProtocolSideChannel&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;, ReadError&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;loop&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; message &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;ws_stream
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;next&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;await
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;transpose&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-closure z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-closure z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-closure z-rust&quot;&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;ReadError&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Other&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-macro z-rust&quot;&gt;anyhow!&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-rust&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; message &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;match&lt;&#x2F;span&gt; message &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Message&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Text&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;utf8_bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                        &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-rust&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;ReadData&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Binary&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Bytes&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;copy_from_slice&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;                            utf8_bytes&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;as_bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;                        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Message&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Binary&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                        &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-rust&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;ReadData&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Binary&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Message&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Ping&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                        &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-rust&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;ReadData&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Custom&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;WebsocketProto&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Ping&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Message&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Pong&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                        &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-rust&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;ReadData&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Custom&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;WebsocketProto&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Pong&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Message&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Close&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;_&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                        &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-rust&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;ReadError&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;ConnectionClosed&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Message&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Frame&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;_&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                        &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-rust&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;ReadError&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;UnexpectedMessage&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Fifty-seven lines, including a lot of curly braces.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-note-on-cancel-safety&quot;&gt;A note on cancel safety&lt;&#x2F;h2&gt;
&lt;p&gt;Rust cancel safety can be tricky, so be sure to understand the details before
implementing &lt;code&gt;ClientTransport&lt;&#x2F;code&gt; or &lt;code&gt;ServerTransport&lt;&#x2F;code&gt;.
&lt;a href=&quot;https:&#x2F;&#x2F;rfd.shared.oxide.computer&#x2F;rfd&#x2F;400&quot;&gt;RFD-400 Dealing with cancel safety in async Rust&lt;&#x2F;a&gt;
is fantastic and is a very good resource on the subject.&lt;&#x2F;p&gt;
&lt;p&gt;In short, If a function isn&#x27;t cancel safe there is a risk of leaving the
system (your program, your customer&#x27;s program) in a broken state, a state where
some property of the system has been violated.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s take a quick look at &lt;code&gt;ClientTransport&lt;&#x2F;code&gt; as an example again:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;async &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;write&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;, &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Message&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;ToServer&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;, WriteError&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;async &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;read&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;ReadData&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;ProtocolSideChannel&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;, ReadError&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The implementor&#x27;s responsibility is to make sure that &lt;code&gt;.write&lt;&#x2F;code&gt; and &lt;code&gt;.read&lt;&#x2F;code&gt; are
cancel safe. It&#x27;s a matter of being careful: You are probably going to use some
other library (I used &lt;code&gt;tokio-tungstenite&lt;&#x2F;code&gt; and &lt;code&gt;axum&lt;&#x2F;code&gt; in the example code in the
repo) to implement the functions. It&#x27;s your responsibility to figure out their
cancel safety properties.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;sending-and-receiving-messages&quot;&gt;Sending and receiving messages&lt;&#x2F;h1&gt;
&lt;p&gt;The best part of &lt;code&gt;stomp-agnostic&lt;&#x2F;code&gt; is how easy it is to use once the transport
has been implemented.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m hand-waving a bit here, but it doesn&#x27;t need to be more complicated than this
to handle sending and receiving messages as a STOMP-over-WebSocket client&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; stomp &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;ClientStompHandle&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;connect&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-comment z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;*&lt;&#x2F;span&gt; ... &lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;await&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;?&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;loop&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-support z-macro z-rust&quot;&gt;select!&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;_&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; cancellation&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;cancelled&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;break&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        message_to_send &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; internal_message_channel&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;recv&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;match&lt;&#x2F;span&gt; message_to_send &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                &lt;span class=&quot;z-support z-type z-rust&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; stomp&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;send_message&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;await&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                &lt;span class=&quot;z-support z-type z-rust&quot;&gt;None&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;break&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        response_result &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; stomp&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;read_response&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; response &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; response_result&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;match&lt;&#x2F;span&gt; response &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Response&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Message&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;match&lt;&#x2F;span&gt; message&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;content &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                        &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;FromServer&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Message &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt; body&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-range z-rust&quot;&gt;..&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                            &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; ...
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;what-now&quot;&gt;What now?&lt;&#x2F;h1&gt;
&lt;p&gt;Having this library enabled me to replace our very old iOS STOMP client library by
writing a few glue functions using UniFFI. All the lovely Rust async cancellation,
and a simple library that I am familiar with that can be reused for many other
cases.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m currently also working on a desktop application for Spiideo that has a
STOMP-over-WebSocket server, obviously powered by &lt;code&gt;stomp-agnostic&lt;&#x2F;code&gt;. The magic of
&lt;code&gt;loop&lt;&#x2F;code&gt;, &lt;code&gt;select!&lt;&#x2F;code&gt;, &lt;code&gt;CancellationToken&lt;&#x2F;code&gt;, and channels makes it easy to build
robust software that is easy to understand. Certainly a far cry from callback
based concurrent programming. Rust manages to beat any other programming language
I&#x27;ve tried, including async Swift and async TypeScript.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m hoping that &lt;code&gt;stomp-agnostic&lt;&#x2F;code&gt; will not only be a tool for me to keep building
a variety of Rust STOMP clients and servers, but also for others that have needs
that stray from the available STOMP Rust libraries.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>FOSDEM 2026</title>
        <published>2026-01-31T00:00:00+00:00</published>
        <updated>2026-01-31T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/fosdem-2026/"/>
        <id>https://zkc.se/blog/fosdem-2026/</id>
        <content type="html" xml:base="https://zkc.se/blog/fosdem-2026/">&lt;p&gt;I had the opportunity to go to FOSDEM 2026!&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h1 id=&quot;chaos-on-the-rails&quot;&gt;Chaos on the rails&lt;&#x2F;h1&gt;
&lt;p&gt;The trip to Brussels by train was a bit of a disappointment since all the
departures between Hamburg and Köln were canceled while I was on the train,
making it hard to reschedule (even though I had bought cancellable tickets!). I
had to take a detour through Münster where I had to spend 1.5 hours because my
train there was delayed, which made me miss my connection, and the following
trains kept getting canceled.&lt;&#x2F;p&gt;
&lt;p&gt;I finally made it to Köln, but by that time my Eurostar to Brussels had departed
and I had to spend the night in Köln. I finally made it to Brussels on Saturday
morning and made it to the campus an hour before lunch.&lt;&#x2F;p&gt;
&lt;p&gt;In short, Germany tried to break me, but I am still here and more powerful than
ever.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;ulb-campus&quot;&gt;ULB Campus&lt;&#x2F;h1&gt;
&lt;p&gt;The ULB campus where FOSDEM takes place is filled to the brim with people! The
atmosphere is very chill and there are talks, dev rooms, food trucks, and a lot
of energy everywhere.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Smoke&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    &lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;smoke.png&quot;&gt;
        &lt;img src=&quot;.&amp;#x2F;smoke.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    
    
    &lt;p&gt;Not a fire, that&#x27;s just smoke from &lt;em&gt;a lot&lt;&#x2F;em&gt; of fries.&lt;&#x2F;p&gt;

    
&lt;&#x2F;div&gt;
&lt;h1 id=&quot;day-1-saturday&quot;&gt;Day 1 - Saturday&lt;&#x2F;h1&gt;
&lt;p&gt;Note - the rest of the sections were written while I was listening to the talks
and are not edited. They may contain factual errors and other horrors.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rosa-finding-backdoors-with-fuzzing&quot;&gt;ROSA: Finding backdoors with fuzzing&lt;&#x2F;h2&gt;
&lt;p&gt;(Security) –
&lt;a href=&quot;https:&#x2F;&#x2F;fosdem.org&#x2F;2026&#x2F;schedule&#x2F;event&#x2F;BHNWLN-rosa-backdoor-detector&#x2F;&quot;&gt;event page&lt;&#x2F;a&gt; –
Michaël Marcozzi and Dimitri Kokkonis.&lt;&#x2F;p&gt;
&lt;p&gt;A backdoor can mean many things to many people; weak server config, ML training
data poisoning, or weaknesses in cryptographical algorithms.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Backdoors can be anything&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;This talk focused on code-level backdoors, code embedded in your software that
gives an attacker access to a computer. They call this &quot;hidden access&quot;, and it
is not an exclusively academic problem: xz-utils, php, and proprietary firmware
are just some examples where real-world backdoors were founds.&lt;&#x2F;p&gt;
&lt;p&gt;xz-utils was a supply chain attack, because it was a piece of software that many
linux systems relied on, and if the attack were to be successful it could have
caused a lot of problems.&lt;&#x2F;p&gt;
&lt;p&gt;Fuzzers are a class of software used to find memory errors, exploring errors by
randomized testing in both source code and binaries.&lt;&#x2F;p&gt;
&lt;p&gt;The goal of the project is to prevent backdoors in CI for open-source projects.
After investigating what options existed for finding backdoors, it was mainly
based on manual engineering efforts. The idea is to automate parts of the
reverse engineering process. A hurdle was that there was not a large corpus of
examples for software backdoors available. Fuzzers are good at finding crashes,
but are not really good at finding backdoors.&lt;&#x2F;p&gt;
&lt;p&gt;The idea of &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;binsec&#x2F;rosa&quot;&gt;ROSA&lt;&#x2F;a&gt;. is to take an out-of-the box
Graybox Fuzzer and add a &quot;novel metamorphic oracle&quot; to find backdoor triggering
inputs that cause diverging behavior. The team created ROSARUM which is a
standardized backdoor benchmark with 17 examples of backdoors to benchmark
against.&lt;&#x2F;p&gt;
&lt;p&gt;ROSA can be used to find a backdoor in Boa HTTP server found in some Belkin
devices. Phase 1 for the fuzzer is to find representative input and spends some
time doing that. Phase 2 is to &quot;intensively explore the input space&quot;. ROSA then
monitors the syscall interface to see if some inputs trigger diverging system
calls. The divergent system calls can then be manually vetted.&lt;&#x2F;p&gt;
&lt;p&gt;Demonstration! Disclaimer: The fuzzer has been biased for the demo not to take 4
hours. The demonstration begins by showing some decompiled PHP server code,
which contains a backdoor; &quot;but we don&#x27;t know that yet&quot;. ROSA then starts to
run; ROSA is written in Rust and the CLI&#x2F;TUI is Ratatui a popular Rust TUI
framework.&lt;&#x2F;p&gt;
&lt;p&gt;Backdoor found!&lt;&#x2F;p&gt;
&lt;p&gt;The output from ROSA can now be inspected. We see the &lt;code&gt;rosa-explain&lt;&#x2F;code&gt; command in
action: ROSA explains &quot;why this is a backdoor&quot;. We then run the application
through &lt;code&gt;strace&lt;&#x2F;code&gt; and after a little bit of scrolling we see a very strange
system call that should not be there; an &lt;code&gt;execv&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If we now run the server program with just the right parameters we get ROOT. A
very polite applause from the audience was heard.&lt;&#x2F;p&gt;
&lt;p&gt;Fuzzing is not deterministic! It takes 1.5 hours for a run, and it has a 87%
success rate. ROSA is the first fuzzer-based generic backdoor detector and
ROSARUM is the first standardized backdoor benchmark.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;interoperability-regulation-in-the-eu-opening-ios-and-android-for-free-software&quot;&gt;Interoperability regulation in the EU: Opening iOS and Android for Free Software&lt;&#x2F;h2&gt;
&lt;p&gt;(Legacy &amp;amp; Policy) –
&lt;a href=&quot;https:&#x2F;&#x2F;fosdem.org&#x2F;2026&#x2F;schedule&#x2F;event&#x2F;TQS7LM-interoperability-dma-apple-google&#x2F;&quot;&gt;event page&lt;&#x2F;a&gt; –
Alexander Matern, Victor Le Pochat, Lori Roussey, Gabriel Kobus, and Lucas Lasota.&lt;&#x2F;p&gt;
&lt;p&gt;The exciting topic of the EU Digital Markets Act!&lt;&#x2F;p&gt;
&lt;p&gt;Interoperability is important because it gives people the opportunity to
communicate between different pieces of hardware and software.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Interoperability regulation panel&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    &lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;dma.png&quot;&gt;
        &lt;img src=&quot;.&amp;#x2F;dma.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    
    
    &lt;p&gt;Alexander Matern, European Commission&#x27;s DMA enforcement team.
Victor Le Pochat, European Commission&#x27;s DMA enforcement team.
Lori Roussey, Data Rights.
Gabriel Kobus, European Commission&#x27;s DMA enforcement team.
Panel moderation: Lucas Lasota, Legal Researcher and Lecturer at the Halle-Wittenberg University.&lt;&#x2F;p&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;The biggest companies on the planet do not want to interoperate. Less than 1% of
the room uses a mobile phone that does not run iOS or Android (I saw one hand
raised).&lt;&#x2F;p&gt;
&lt;p&gt;The DMA puts an obligation on the biggest companies on the planet: it gives open
software access to the largest markets on the planet. We have members of the EU
DMA enforcement team on stage, and they are fighting &quot;an uphill battle&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;It is a simple law: You shall get interoperability by design. Google, Apple, and
Microsoft do what they can to avoid providing interoperability. As developers we
can go these companies&#x27; portals to request interoperability which will add more
pressure on them to do the right thing.&lt;&#x2F;p&gt;
&lt;p&gt;Vendors use Security and Integrity as ways to argue that their users will be at
risk if their systems were more open. The security of a system may be that when
I put a password in place to protect a certain piece of data, and the integrity
of the operating system is what makes sure those protections can not be
circumvented. The DMA requires that the integrity of a system is not diminished
when interoperability is provided, and vendors use that to argue that they can
not make their systems more interoperable. Some things that were possible in the
past have been cut by way of app stores, even if it did not make the systems
inherently more secure.&lt;&#x2F;p&gt;
&lt;p&gt;Apple has always had an adversarial role in the interoperability world, making
the relationship with the open source community very simple: we know where they
stand. Google on the other hand has a more nuanced relationship; recently the
Android OS has taken steps to make it more difficult to run third party app
stores. Android devices are relatively easy to modify and run custom operating
systems, but recently some changes has made that harder as well. In short,
Google&#x27;s approach to Android governance has changed over the last few years.&lt;&#x2F;p&gt;
&lt;p&gt;Something for the kids: Article 6-7 mentioned a few times; a few smiles seen in
the panel.&lt;&#x2F;p&gt;
&lt;p&gt;Data interoperability and portability: Portability is different from
interoperability in that portability generally means data flowing one-way where
interoperability is defined as (at least) two-way.&lt;&#x2F;p&gt;
&lt;p&gt;The DMA is designed to prevent Gatekeeping: Data access through APIs,
documentation for accessing data, and a lot of other things are now required to
be provided free of charge and in machine-readable formats.&lt;&#x2F;p&gt;
&lt;p&gt;A small joke from the moderator: In the modern world we are not allowed to do
sideloading, but we are expected to do &quot;side-listening&quot; (playing Spotify but not
paying attention), and &quot;side-thinking&quot; (using AI to write for us).&lt;&#x2F;p&gt;
&lt;p&gt;The DMA enforcement team have weekly and monthly interactions with the large
companies: the enforcement team listen to our complaints w.r.t interoperability
and they first ask the vendors nicely, and often they comply, but they also have
other regulatory tools in their toolbox (including, ultimately, fines).&lt;&#x2F;p&gt;
&lt;p&gt;A few examples of what has been achieved by the DMA: On iOS you can now set
default applications other than Apple&#x27;s own and iOS now supports alternative app
stores, and browser vendors can distribute their own engines for their browsers
(at least in the EU).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;adversarial-interoperability-writing-a-microsoft-bob-application&quot;&gt;Adversarial interoperability - Writing a Microsoft Bob application&lt;&#x2F;h2&gt;
&lt;p&gt;(Main track) –
&lt;a href=&quot;https:&#x2F;&#x2F;fosdem.org&#x2F;2026&#x2F;schedule&#x2F;event&#x2F;XHSRAF-microsoft-bob-adversarial-interoperability&#x2F;&quot;&gt;event page&lt;&#x2F;a&gt; –
HP van Braam&lt;&#x2F;p&gt;
&lt;div class=&quot;quote&quot;&gt;
    &lt;p&gt;&quot;I am HP van Braam from the Godot Foundation, and I like old computers&quot;&lt;&#x2F;p&gt;

    &lt;div class=&quot;quote-title&quot;&gt;Braam&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Bob – A project from Microsoft from 1994 that not many people have heard about.
Is there anything we can learn from this project? Braam came across a forum post
claiming that someone had a friend using a computer for only one thing: Writing
letters using Microsoft Bob (Letter writer). Her friends had lost her files, oh
no!&lt;&#x2F;p&gt;
&lt;p&gt;Bob is a workplace program manager. Basically your desktop, but at that time you
did everything from there, a replacement for the Windows 3.1 desktop. &quot;There is
an irresistible earnestness to it&quot;.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;bob.png&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;bob.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Bob does things that computers simply do not do anymore. You get a birthday
present on your birthday (if you enter your birthday in the Bob calendar). There
are flowers on your desktop. You can move them around. Scalable vector graphics.
Wonderful.&lt;&#x2F;p&gt;
&lt;p&gt;Bob has some slightly outdated skeumorphisms - full screen organizing desk, full
screen folder organizer, and so on.&lt;&#x2F;p&gt;
&lt;p&gt;Despite its quirky look, it was built with modern APIs (for the time) - COM,
MAPI, and MS JET (whatever that is). Some of those are still used in some form
today.&lt;&#x2F;p&gt;
&lt;p&gt;Braam was able to use a combination of a partial dump of the SDK found on the
internet, as well as Ghidra decompilation how to figure out how to program for
Microsoft Bob.&lt;&#x2F;p&gt;
&lt;p&gt;Back to Jean. Jean was able to get some files on a floppy, but was not able to
figure out how to get the letters back. This is because there are no files,
everything was saved in a single database (file). This is how the modern world
works: every SaaS company saves user data in a huge database.&lt;&#x2F;p&gt;
&lt;p&gt;You can play with Microsoft Bob at &lt;a href=&quot;https:&#x2F;&#x2F;bob.estate&#x2F;&quot;&gt;https:&#x2F;&#x2F;bob.estate&#x2F;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;raylib-a-12-year-adventure-as-a-solo-maintainer&quot;&gt;raylib: a 12-year adventure as a solo-maintainer&lt;&#x2F;h2&gt;
&lt;p&gt;(Main track) –
&lt;a href=&quot;https:&#x2F;&#x2F;fosdem.org&#x2F;2026&#x2F;schedule&#x2F;event&#x2F;883PBF-raylib-12-year-adventure&#x2F;&quot;&gt;event page&lt;&#x2F;a&gt; –
Ramon (Ray) Santamaria&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;raylib.png&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;raylib.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The basis is a simple and easy to use library to put graphics on the screen,
born from a need to teach beginner programmers &#x2F; students to do graphics
programming.&lt;&#x2F;p&gt;
&lt;p&gt;The keyword is &quot;enjoy&quot;. It was designed to be enjoyable to use.&lt;&#x2F;p&gt;
&lt;p&gt;The whole presentation today is built in &lt;a href=&quot;https:&#x2F;&#x2F;www.raylib.com&#x2F;&quot;&gt;raylib&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;With around 100 lines of code you can get a full 2D or 3D application, you can
load shaders, and you can also deploy raylib to embedded systems, such as UIs in
cars (e.g. openpilot).&lt;&#x2F;p&gt;
&lt;p&gt;A small library to teach graphics or video games programming has evolved over 12
years and just kept growing. In 2019 the library got a Google Open Source Award
and at that time it got a lot of attention. In 2020 Ray quit his job and worked
full-time on raylib for a while.&lt;&#x2F;p&gt;
&lt;p&gt;The three M&#x27;s: Maintenance, Motivation, Money – three hard things when working
as a solo developer. Asking yourself &quot;How long am I willing to work on my
project?&quot;. Best advice - Keep it simple! Raylib is &quot;only 50k lines of code&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;How long can motivation last? Your primary motivation must be that you enjoy
what you do. If you stop to enjoy what you do, it will be difficult to stay with
it. Ray stayed motivated by engaging with the community and working on side
project related to raylib. Receiving recognition for his work was highly
motivating. The last thing is self-care: &quot;no-screen hobbies&quot;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;day-2-sunday&quot;&gt;Day 2 - Sunday&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;webassembly-on-constrained-devices&quot;&gt;WebAssembly on Constrained Devices&lt;&#x2F;h2&gt;
&lt;p&gt;(Rust) –
&lt;a href=&quot;https:&#x2F;&#x2F;fosdem.org&#x2F;2026&#x2F;schedule&#x2F;event&#x2F;8TDKRT-rust-wasm-embedded&#x2F;&quot;&gt;event page&lt;&#x2F;a&gt; –
Fedor Smirnov&lt;&#x2F;p&gt;
&lt;p&gt;Running WebAssembly on microcontrollers!&lt;&#x2F;p&gt;
&lt;p&gt;Why would you want to do it in the first place?&lt;&#x2F;p&gt;
&lt;p&gt;At Myrmic they build a common middleware layer that manages application code
across devices. WASM is a good choice for OS-grade devices, because of strong
sandboxing and target-independent deployment. On microcontrollers it isn&#x27;t as
obvious. The things you get is that you can update device behavior without
reflashing, it isolates application logic from the firmware and it reduces the
risk of bricking; if the application crashes you don&#x27;t lose access to the
device.&lt;&#x2F;p&gt;
&lt;p&gt;What does it mean for your code?&lt;&#x2F;p&gt;
&lt;p&gt;There are a number of build targets for wasm on device; wasi targets which
assume things about the runtime and the unknown target that assumes almost
nothing. The downside of unknown is that you need to provide the functionality
you need yourself, but on the other hand you can avoid some bloat that might not
fit into your hardware of choice.&lt;&#x2F;p&gt;
&lt;p&gt;The wasm interface is constrained to integers and floats, but since the host can
access the wasm sandbox&#x27;s memory, you can communicate addresses to the host and
the host can then read the memory directly. To make nice interfaces you can wrap
all of this low-level stuff in safe Rust interfaces, mostly through macros that
implement the functionality for you.&lt;&#x2F;p&gt;
&lt;p&gt;What are the tradeoffs for the runtime and integration?&lt;&#x2F;p&gt;
&lt;p&gt;When you want to run your wasm program on embedded, you need to select a
runtime. Unfortunately the Rust runtimes are (currently) quite expensive
size-wise, i.e. they require much more memory than the smallest C runtime:
Almost 10 times more expensive ~60KiB (wamr) vs ~600KiB (wasmtime). There is
also a tradeoff around speed: interpreted mode vs AoT (Ahead-of-Time compiled),
the Rust runtimes run in interpreted mode, which is 10 times slower than AoT,
which is what wamr uses. There is certainly room for the Rust runtimes to
improve!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rust-boy-a-rust-journey-into-game-body-dev&quot;&gt;Rust-boy: A Rust journey into Game Body dev&lt;&#x2F;h2&gt;
&lt;p&gt;(Rust) –
&lt;a href=&quot;https:&#x2F;&#x2F;fosdem.org&#x2F;2026&#x2F;schedule&#x2F;event&#x2F;W3UFSK-rust-game-boy&#x2F;&quot;&gt;event page&lt;&#x2F;a&gt; –
Federico Bassini&lt;&#x2F;p&gt;
&lt;p&gt;Federico says &quot;The daily developer loop can be kind of boring&quot;.
But last year Federico discovered something at FOSDEM: A passion for making
retro games in Rust!&lt;&#x2F;p&gt;
&lt;div class=&quot;quote&quot;&gt;
    &lt;p&gt;&quot;The daily developer loop can be kind of boring&quot;&lt;&#x2F;p&gt;

    &lt;div class=&quot;quote-title&quot;&gt;Federico&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The first part of the talk is a walk-through of the Game Boy and Game Boy Color
hardware architecture: Surprisingly similar but with some differences for color
management (obviously...).&lt;&#x2F;p&gt;
&lt;p&gt;To make a game you need to be able to write code and compile it in the right
format! There are a bunch of tools and documentation online. There are also some
tools like GB Studio which is a no-code tool to make Game Boy games.&lt;&#x2F;p&gt;
&lt;p&gt;But Rust can&#x27;t be compiled directly to the original Game Boy hardware! But Game
Boy Advance has an ARM cpu; and there are few Rust projects to support it.&lt;&#x2F;p&gt;
&lt;p&gt;But there is a workaround for Rust on Game Boy! &quot;Rust-GB&quot;. It is a way to
compile to LLVM-IR and from there convert it to C and finally you can get
machine code for The Game Boy.&lt;&#x2F;p&gt;
&lt;p&gt;Can we develop a compiler for Rust to Game
Boy? &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ffex&#x2F;rust-boy&quot;&gt;Rust-boy&lt;&#x2F;a&gt; is a library that tries to go
all the way from Rust to assembly code that is compatible with the Game Boy
hardware. It is a modular codebase that contains &lt;code&gt;gb_asm&lt;&#x2F;code&gt; which emits assembly
code for the Sharp LR35902 processor, &lt;code&gt;gb_std&lt;&#x2F;code&gt; which is a &quot;standard library&quot;
for building Game Boy games, and finally &lt;code&gt;rust_boy&lt;&#x2F;code&gt; that exposes a bunch of
higher-level APIs that makes it easier to start building a Game Boy game.&lt;&#x2F;p&gt;
&lt;p&gt;This library isn&#x27;t about &quot;writing arbitrary Rust code&quot; and running it on the
Game Boy, it is more of an abstraction layer for the assembly code that needs to
be generated, so it is still low level.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Main game loop
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;    asm&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;label&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;MainLoop&lt;span class=&quot;z-punctuation z-definition z-string z-end z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;        &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;ld_bc&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;160&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;        &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;call&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;WaitVBlank&lt;span class=&quot;z-punctuation z-definition z-string z-end z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;        &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;jp&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;MainLoop&lt;span class=&quot;z-punctuation z-definition z-string z-end z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; VBlank function
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;    asm&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;chunk&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Chunk&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Functions&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;        &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;label&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;WaitVBlank&lt;span class=&quot;z-punctuation z-definition z-string z-end z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;        &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;comment&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Wait for vertical blank&lt;span class=&quot;z-punctuation z-definition z-string z-end z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;        &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;ld_a_label&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;[$FF44]&lt;span class=&quot;z-punctuation z-definition z-string z-end z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;        &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;cp_imm&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;144&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;        &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;jr_cond&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Condition&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-rust&quot;&gt;NZ&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;WaitVBlank&lt;span class=&quot;z-punctuation z-definition z-string z-end z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;        &lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;ret&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Generate assembly
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;    &lt;span class=&quot;z-support z-macro z-rust&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder z-rust&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; asm&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;to_asm&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You still need to know a lot about the Game Boy to use it!&lt;&#x2F;p&gt;
&lt;p&gt;Something Federico sees in the future is a Rust parser which would make it
possible to write actual Rust code and it would be automatically translated to
use &lt;code&gt;gb_std&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gstreamer-1-28-and-beyond&quot;&gt;GStreamer 1.28 and beyond&lt;&#x2F;h2&gt;
&lt;p&gt;(Audio Video &amp;amp; Graphics Creation) –
&lt;a href=&quot;https:&#x2F;&#x2F;fosdem.org&#x2F;2026&#x2F;schedule&#x2F;event&#x2F;SVKGDR-gstreamer_1_28_and_beyond&#x2F;&quot;&gt;event page&lt;&#x2F;a&gt; –
Tim-Philipp Müller&lt;&#x2F;p&gt;
&lt;p&gt;GStreamer is an open source, cross-platform video framework. You can read,
write, stream, mix, cut, edit, and do many other things with media.&lt;&#x2F;p&gt;
&lt;p&gt;Major release 1.28! Released just a couple of days ago. TPM will give us a
high-level walk through today.&lt;&#x2F;p&gt;
&lt;p&gt;There are a bunch of new &lt;strong&gt;codec support&lt;&#x2F;strong&gt;: H.266, MPEG-H audio and some other
changes. &lt;strong&gt;SMPTE 2038 ancillary data&lt;&#x2F;strong&gt; that can be used to add metadata to a
stream like the game score of a football game.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Enhanced RTMP&lt;&#x2F;strong&gt; add support for modern video codecs like H.265 and AV1, also
multiple audio and&#x2F;or video tracks.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;HLS stream authoring&lt;&#x2F;strong&gt;: I-frame only playlists, and single media file output
for Video on Demand use cases.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Speech + Translations&lt;&#x2F;strong&gt; support for Speech-to-Text, voice cloning, deepgram
speech-to-text transcription, output compression for translated audio to &quot;catch
up&quot; if there is a delay in the automatic translation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Analytics&lt;&#x2F;strong&gt; ONNX support, more tensor decoders, and a few other things.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Vulkan&lt;&#x2F;strong&gt; AV1 and VP9 decoding support, H.264 encoding support, H.265 decoder
with 10-bit depth.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Wayland&lt;&#x2F;strong&gt; more support for a few different things for Linux desktop
environments.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;GNOME&lt;&#x2F;strong&gt; ShowTime replaces Totem media player, which uses all the &quot;cool new
stuff&quot; that have been added in the last few years.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;AMD HIP plugin&lt;&#x2F;strong&gt; AND GPU programming API for portable CUDA-like development on
AMD or NVIDIA.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Bidnings&lt;&#x2F;strong&gt; New C++ bindings, new-ish Go bindings, Python bindings
improvements, and Rust bindings improvements.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;fallbacksrc&lt;&#x2F;strong&gt; multi-stream support via the Streams API, supports encoded
output; not just raw audio&#x2F;video.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Misc&lt;&#x2F;strong&gt; VMAF element (perceptual video assessment score), Webkit gets a new
plugin for the &quot;WPE Platform API&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Tracing and debugging&lt;&#x2F;strong&gt; enhanced dots-viewer, GstLogContext to fine-tune
logging output to reduce log message spam.&lt;&#x2F;p&gt;
&lt;p&gt;Future stuff!&lt;&#x2F;p&gt;
&lt;p&gt;GStreamer will be adding more Rust, &quot;that is where the cool stuff happens&quot;.
Media over QUIC: a simpler replacement for WebRTC. WebRTC stack is going to be
converted to Rust, which will improve scalability. MPEG-TS will be converted to
Rust, complete rewrite which will give us more reliability and it will get a
more robust time domain. More speech &amp;amp; translation features; already support
cloud translation but new focus will be local translation e.g. Whisper. More
formats like AV2.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;clickhouse-s-c-and-rust-journey&quot;&gt;Clickhouse’s C++ and Rust journey&lt;&#x2F;h2&gt;
&lt;p&gt;(Rust) –
&lt;a href=&quot;https:&#x2F;&#x2F;fosdem.org&#x2F;2026&#x2F;schedule&#x2F;event&#x2F;NBLNRY-rust-clickhouse&#x2F;&quot;&gt;event page&lt;&#x2F;a&gt; –
Alexey Milovidov&lt;&#x2F;p&gt;
&lt;p&gt;&quot;How to avoid a full rewrite&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;ClickHouse is an open source project, mostly C++ codebase which is about
1.5MLoC.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;C++ is not the nicest language&quot;, but it was a good choice in 2009 and it is
prominent in many domains like games development and database management
systems.&lt;&#x2F;p&gt;
&lt;p&gt;If we started today would we write ClickHouse in Rust? The pain of C++ is &quot;
soothed&quot;
by running a lot of tests and santizers (ASan, TSan, UBSan, and so on) in CI.
Lots and lots of tests: 10-30 million test invocations per day. They also run
Jepsen tests on their database.&lt;&#x2F;p&gt;
&lt;p&gt;Arguments against Rust: Full rewrite would take years. Combining two languauges
is sometimes worse than using just one or the other. &quot;Throwing away accumulated
knowledge&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;ClickHouse&#x27;s approach: Iterative Development. Take a non-essential library that
can easily be turned off, and use it as an example; added a new function to SQL
for BLAKE3 hashing. The second thing they did was to improve their command line
application; the result of this was &quot;Rust was worth it&quot;. Next they added a new
language dialect, PRQL, that existed as a Rust library.&lt;&#x2F;p&gt;
&lt;p&gt;ClickHouse added support for the Delta Lake format for Data Lakes, and it was
integrated using an existing Rust library.&lt;&#x2F;p&gt;
&lt;p&gt;What is wrong with Rust? To combine C++ with Rust you need to take some extra
care. To get reproducible builds you need to take care of a few things:
all dependencies must be pinned to to avoid supply-chain attacks, and
dependencies must be built from source.&lt;&#x2F;p&gt;
&lt;p&gt;When writing wrapper libraries for C++, you have to take extra care to make sure
the interface is safe to use and correct. C++ and Rust error handling works a
bit differently; C++ uses exceptions, and Rust libraries typically pass errors
upwards on the stack, or the code panics. You don&#x27;t want a third party library
with an internal panic to bring down your server or application. &quot;ClickHouse CI
found bugs (causing panics) in every Rust library we used&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;When it comes to sanitizers, for C++ all code must be checked with sanitizers.
For (safe) Rust you might think that sanitizers are not needed, but when
combining it with C++ it must be possible to run the sanitizers on the combined
code.&lt;&#x2F;p&gt;
&lt;p&gt;Takeaways: Rust is a great language. You can come and be ClickHouse contributor
by adding features using Rust!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;a-word-from-our-sponsor&quot;&gt;A word from our sponsor&lt;&#x2F;h1&gt;
&lt;p&gt;Now go watch this &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=v0JjG0Qfwi8&quot;&gt;talk&lt;&#x2F;a&gt; where
Bryan Cantrill references Swedish
physician &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Thermal_grill_illusion&quot;&gt;Torsten Thunberg&#x27;s &quot;Thermal Grill Illusion&quot;&lt;&#x2F;a&gt; (
two pipes, one slightly warm and the other slightly cool, are twisted together,
and when touched cause a strong reaction to want to pull your hand away as a
metaphor for Marc Andreesen&#x27;s writing on &quot;Software is eating the world&quot;.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>How two generations of internal indoor map apps created a new line of business at Sony</title>
        <published>2025-07-18T00:00:00+00:00</published>
        <updated>2025-07-18T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/two-generations-of-indoor-maps/"/>
        <id>https://zkc.se/blog/two-generations-of-indoor-maps/</id>
        <content type="html" xml:base="https://zkc.se/blog/two-generations-of-indoor-maps/">&lt;p&gt;In 2009, I was assigned to one of the Android teams at Sony Ericsson. To get
up to speed I experimented with the different Android APIs. At this time I had
been working at Sony Ericsson for 3 years already, and the massive footprint of the
company in Lund required office landscapes the size of small towns. But also
meeting rooms. Lots of meeting rooms.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;This is the story of how SEMCMap (SEMC being short for Sony Ericsson Mobile
Communications) was created, how SonyMap spawned from a completely different
project, how they were merged, how we managed to be the first project to be
accepted by the brand-new Research and Incubation initiative at Sony Mobile, how
it was the first project to &quot;exit&quot; Research and Incubation a few months before I
left Sony Mobile for Spiideo, and finally how it became a completely new line of
business&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#nimway&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; for Sony Europe.&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;div class=&quot;note-title&quot;&gt;&lt;&#x2F;div&gt;
    &lt;p&gt;I need to give Magnus Persson a big Thank You for helping me
remember details that would have otherwise been lost to time. You were
invaluable. Thank You!&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h1 id=&quot;smartphone-and-application-maturity-in-2009&quot;&gt;Smartphone and application maturity in 2009&lt;&#x2F;h1&gt;
&lt;p&gt;In 2009, there were very few smartphones: The iPhone 3Gs had just been released,
and Sony Ericsson was about to release the Xperia X10&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#xperia_x10&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. There
weren&#x27;t many apps, and there definitely weren&#x27;t any popular indoor-navigation
apps.&lt;&#x2F;p&gt;
&lt;p&gt;Smartphone screens were tiny compared to the screens we have today, and the
phones weren&#x27;t exactly snappy, even if it maybe felt like they were then and
there. The Xperia X10&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#xperia_x10&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; had a 4-inch screen and the iPhone 3Gs had a
3.5-inch screen. Today it&#x27;s hard to find a smartphone with a screen that&#x27;s
smaller than 6 inches. Apps weren&#x27;t very pretty, especially on Android, which
honestly had a lot of catching up to do at the time.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;semcmap&quot;&gt;SEMCMap&lt;&#x2F;h1&gt;
&lt;p&gt;The first indoor map application I worked on was SEMCMap. I created it while
I was looking into the Android APIs. My first attempts were terrible:
performance-wise, design-wise, you name it. No compass, no auto-rotate,
and no indoor positioning.&lt;&#x2F;p&gt;
&lt;p&gt;It was rough being a user of SEMCMap, but it quickly gained in popularity,
since it filled a niche that people needed help with — finding their way
to the meeting room they were supposed to be in. If you&#x27;ve ever worked at a
large company, or in a building with a lot of meeting rooms, you probably have
some sense of how disorienting it can be when every floor looks the same and
there are hundreds of meeting rooms.&lt;&#x2F;p&gt;
&lt;p&gt;The main use-case was basically just typing a meeting room name into the search
box, selecting the meeting room and then trying to decipher where you were going
based on where you thought you were and where the map told you the meeting room
was.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;A lot of people were using SEMCMap at the time&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    &lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;usage.png&quot;&gt;
        &lt;img src=&quot;.&amp;#x2F;usage.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    
    
&lt;&#x2F;div&gt;
&lt;p&gt;SEMCMap had one redeeming feature though — the ability to send your
position to someone else through the app. You could use your Google account to
quickly sign in, and then use those credentials to send a message to another
signed-in user along with the location. The feature was popular and well-used.&lt;&#x2F;p&gt;
&lt;p&gt;So far so good. I maintained the application myself for a few years, and a lot
of people seemed to like it! Mostly I did other work: phone book, social media
integrations, and so on. I worked through a lot of tasks and a lot of teams.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;semcmap-and-indoor-finder-coexist-for-a-while&quot;&gt;SEMCMap and Indoor Finder coexist for a while&lt;&#x2F;h1&gt;
&lt;p&gt;Magnus Persson&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#magnus_persson&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; and I know each other from my early days at Sony
Ericsson. He was working in some of the same teams that I did. A cool cat, and
full of energy and great ideas. I think I met him the first time in 2006, I was
24 at the time feels like yesterday but almost 20 years have passed. Life comes
at you fast.&lt;&#x2F;p&gt;
&lt;p&gt;While I had been working on SEMCMap on-and-off for a couple of years, Magnus was
working in the Technology department. The Technology department was tasked with
keeping track of new technologies and making sure those ended up in Sony
Mobile&#x27;s devices.&lt;&#x2F;p&gt;
&lt;p&gt;Around 2011, Magnus ran a project called Indoor Finder together with Ericsson
Research, with Sony Mobile mainly contributing to the map interface and the
positioning functionality. At the time, he wrote a blog post, which can still
be found using The Internet Archive&#x27;s wayback machine! I did a little archiving
myself — have a look at the &lt;a href=&quot;https:&#x2F;&#x2F;zkc.se&#x2F;blog&#x2F;two-generations-of-indoor-maps&#x2F;.&#x2F;indoor_maps.pdf&quot;&gt;PDF&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Left is SEMCMap, right is Indoor Finder&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    &lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;indoor_maps.jpg&quot;&gt;
        &lt;img src=&quot;.&amp;#x2F;indoor_maps.jpg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    
    
&lt;&#x2F;div&gt;
&lt;p&gt;At the end of 2011 Sony Ericsson was being transformed into Sony Mobile, after
Sony bought out Ericsson to gain full ownership and control of the company.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;sonymap&quot;&gt;SonyMap&lt;&#x2F;h1&gt;
&lt;p&gt;Ericsson Research lost interest in the joint research project Indoor Finder at
some point, and Sony Mobile fully took over the project. Magnus and I both had a
lot of ideas and Magnus talked me into joining him to work full-time on SonyMap.
Roger Jansson&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#roger_jansson&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, was my manager&#x27;s manager at the time, and he was
happy to give the permission to go ahead, and we went ahead... full steam.&lt;&#x2F;p&gt;
&lt;p&gt;We both agreed that Indoor Finder was a better starting point than SEMCMap, but
a lot of the code and ideas from the internals of SEMCMap made it over to the
new SonyMap application. We brought on more people, and we were usually at least
two, but usually three, or even four people working on it at this time. One of
the good people got help from was Oskar Syrén&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#oskar_syren&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; who implemented an
improved fused indoor positioning engine that used a combination of GPS,
Bluetooth Low Energy beacons, and Dead Reckoning.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Bluetooth Low-Energy Beacon&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    &lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;beacon.png&quot;&gt;
        &lt;img src=&quot;.&amp;#x2F;beacon.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    
    
&lt;&#x2F;div&gt;
&lt;p&gt;Magnus dutifully ordered parts and assembled Franken-BTLE beacons and placed
them in &lt;em&gt;every single meeting room&lt;&#x2F;em&gt; — and there were a lot! Every BTLE
beacon was attached to a standard Sony Mobile USB charger. You would think
people would just leave them alone, but you&#x27;d be wrong.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;research-and-incubation&quot;&gt;Research and Incubation&lt;&#x2F;h1&gt;
&lt;p&gt;Around 2014 things were not going great for Sony Mobile. Actually, things had
not been going great for a while. Samsung and Apple are currently the biggest
smartphone manufacturers, and that was true in 2014 too. There was more
competition for sure: LG, Motorola, even Nokia, but they were all small too.&lt;&#x2F;p&gt;
&lt;p&gt;Patrik Olsson&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#patrik_olsson&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; kicked off the Research and Incubation (R&amp;amp;I)
department. Anyone that had an idea could apply, and SonyMap was the first
project to get accepted. Magnus and I were very happy about that, since it
showed that we had worked on something that was useful to people.&lt;&#x2F;p&gt;
&lt;p&gt;Getting accepted to R&amp;amp;I was great for us, but it also serves as an example of
what happens when a project gets the spotlight on it in an organization starved
for success. All of a sudden I wasn&#x27;t spending my days planning concrete things
to do with our application, or building cool features, I was in meetings with
people wanting a piece of the cake.&lt;&#x2F;p&gt;
&lt;p&gt;On the other hand, we now got to staff our development team with amazing
engineers and designers. It was a fun time, and the team built a lot of
interesting stuff, most of which was actually usable and shippable. One of the
engineers that joined at this time was Mattias Niklewski, who I consider to be a
good friend, and one of the finest engineers I have worked with.&lt;&#x2F;p&gt;
&lt;p&gt;We weren&#x27;t just the first project to get accepted to the R&amp;amp;I process. The goal
for an R&amp;amp;I project was to &quot;graduate&quot; a real product, and we did that too, as
the first graduate project from R&amp;amp;I no less.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;nimway&quot;&gt;Nimway&lt;&#x2F;h1&gt;
&lt;p&gt;But, I had done my time at Sony Mobile. I was ready for a new adventure. So
after a little courting I accepted an offer to join Spiideo. Magnus tried to
get me to stay on, but my mind was set on moving on.&lt;&#x2F;p&gt;
&lt;p&gt;Magnus stayed for another 8 years. Mattias, and Oskar are still there, and the
team did a great job acquiring clients under the Nimway&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#nimway&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; moniker. A few
years after I left, the project moved on from Sony Mobile and joined Sony
Europe, and is still going strong from what I can gather!&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s satisfying to see how something with small beginnings was able to evolve
and amalgamate, finally becoming a whole new business segment for a huge company
like Sony. I&#x27;m proud to be one of the parents of SonyMap, now part of Nimway,
and I&#x27;m glad to see that what started as our side project continues to employ
people.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;references&quot;&gt;References&lt;&#x2F;h1&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;nimway&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.sonynetworkcom.com&#x2F;nimway&quot;&gt;https:&#x2F;&#x2F;www.sonynetworkcom.com&#x2F;nimway&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;xperia_x10&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Sony_Ericsson_Xperia_X10&quot;&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Sony_Ericsson_Xperia_X10&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;magnus_persson&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;magnuspersson78&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;magnuspersson78&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;roger_jansson&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;brjansson&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;brjansson&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;oskar_syren&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;oskar-syr%C3%A9n-79023857&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;oskar-syr%C3%A9n-79023857&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;patrik_olsson&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;polsson&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;polsson&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>I remade a 20-year-old game to learn Bevy ECS</title>
        <published>2025-01-02T00:00:00+00:00</published>
        <updated>2025-01-02T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/remake-20yr-old-game/"/>
        <id>https://zkc.se/blog/remake-20yr-old-game/</id>
        <content type="html" xml:base="https://zkc.se/blog/remake-20yr-old-game/">&lt;p&gt;I got the fantastic idea to learn &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;bevy-ecs&quot;&gt;Bevy ECS&lt;&#x2F;a&gt;
by recreating a game I developed with a friend a long time ago. The main goal is
to remake the game, written in Java in the standard pointer soup programming
style, using an Entity Component System—a kind of type system driven in-memory
database geared towards game programming.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;In 2005 Stefan Li&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#stefan&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; and I did a game for Värnpliktsrådet&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#vplr&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
Värnpliksrådet is a council for and by conscripts from the different branches of
the Swedish Armed Forces. This year is the 20th anniversary of the game.
Unrelated to that, I have a plan to use an Entity Component System&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#ecs&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; for our
new rendering engine at work. Let&#x27;s see if I can transform a
20-year-old Java Applet into a Rust WebAssembly game with a Bevy&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#bevy&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; ECS
core.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;java&quot; class=&quot;language-java z-code&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;z-source z-java&quot;&gt; &lt;span class=&quot;z-comment z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-java&quot;&gt;&#x2F;*&lt;&#x2F;span&gt; Created on 2005-sep-07 &lt;span class=&quot;z-punctuation z-definition z-comment z-java&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Blog bless whoever came up with automatic headers with dates in new files.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;gameplay&quot;&gt;Gameplay&lt;&#x2F;h1&gt;
&lt;div class=&quot;aside&quot;&gt;
&lt;div id=&quot;vplgame&quot; class=&quot;vplgame&quot;&gt;
    &lt;script&gt;
      const enterFullscreen = () =&gt; {
        const canvas = document.getElementById(&quot;vplgame&quot;);
        if (document.fullscreenElement) {
          document.exitFullscreen();
        } else {
          canvas.requestFullscreen();
        }
      };
    &lt;&#x2F;script&gt;

    &lt;canvas class=&quot;canvas&quot; id=&quot;varnplikt&quot; width=&quot;700&quot; height=&quot;460&quot;&gt;
        This canvas should contain an instance of Värnpliktsspelet.
    &lt;&#x2F;canvas&gt;
    &lt;img
        class=&quot;fullscreen-button&quot;
        alt=&quot;Enter Fullscreen&quot;
        src=&quot;&#x2F;vplgame&#x2F;fullscreen.svg&quot;
        onclick=&quot;enterFullscreen();&quot;
    &#x2F;&gt;

    &lt;script type=&quot;module&quot;&gt;
      import init, { GameHandle } from &#x27;&#x2F;vplgame&#x2F;pkg&#x2F;wasm.js&#x27;;

      let animationFrameId = undefined;
      const canvas = document.getElementById(&quot;varnplikt&quot;);
      const ctx = canvas.getContext(&quot;2d&quot;);

      async function startGame() {
        const game = new GameHandle();

        const checkbox = document.getElementById(&quot;debug&quot;);
        checkbox.onclick = () =&gt; {
          if (checkbox instanceof HTMLInputElement) {
            game.debug(checkbox.checked)
          }
        };

        const scaleXy = (bounds, x, y) =&gt; {
          const scaleX = 700 &#x2F; bounds.width;
          const scaleY = 460 &#x2F; bounds.height;
          return [x * scaleX, y * scaleY];
        };

        canvas.addEventListener(&quot;mousemove&quot;, (e) =&gt; {
          const bounds = canvas.getBoundingClientRect();
          const [x, y] = scaleXy(bounds, e.offsetX, e.offsetY);
          game.mouse(x, y);
        });

        canvas.addEventListener(&quot;mousedown&quot;, (e) =&gt; {
          e.preventDefault();
          e.stopPropagation();
        });

        canvas.addEventListener(&quot;mouseup&quot;, (e) =&gt; {
          e.preventDefault();
          e.stopPropagation();
          const bounds = canvas.getBoundingClientRect();
          const [x, y] = scaleXy(bounds, e.offsetX, e.offsetY);
          game.mouseUp(x, y);
        });

        const touchMove = (e) =&gt; {
          e.preventDefault();
          e.stopPropagation();
          if (e instanceof TouchEvent) {
            if (e.changedTouches.length &gt; 0) {
              if (e) {
                const bounds = canvas.getBoundingClientRect();
                const [x, y] = scaleXy(bounds, e.changedTouches[0].clientX - bounds.left, e.changedTouches[0].clientY - bounds.top);
                game.mouse(x, y);
              }
            }
          }
        };

        canvas.addEventListener(&quot;touchmove&quot;, touchMove);
        canvas.addEventListener(&quot;touchstart&quot;, touchMove);
        canvas.addEventListener(&quot;touchend&quot;, (e) =&gt; {
          e.preventDefault();
          e.stopPropagation();
          if (e instanceof TouchEvent) {
            if (e.changedTouches.length &gt; 0) {
              if (e) {
                const bounds = canvas.getBoundingClientRect();
                const [x, y] = scaleXy(bounds, e.changedTouches[0].clientX - bounds.left, e.changedTouches[0].clientY - bounds.top);
                game.mouseUp(x, y);
              }
            }
          }
        });

        function loadImage(key, url) {
          const img = new Image();
          img.src = url;
          return new Promise((resolve, reject) =&gt; {
            img.onload = () =&gt; {
              game.addResource(key, img);
              resolve();
            }
            img.onerror = (error) =&gt; {
              reject(error);
            };
          });
        }

        const audioCtx = new AudioContext();

        function loadAudio(key, url) {
          return new Promise(async (resolve, reject) =&gt; {
            try {
              let resp = await fetch(url);
              let arrayBuffer = await resp.arrayBuffer();
              const audioBuffer = await audioCtx.decodeAudioData(arrayBuffer);
              game.addAudio(key, audioBuffer, playAudio);
              resolve();
            } catch (e) {
              reject(e);
            }
          });
        }

        &#x2F;&#x2F; Called from Rust
        function playAudio(audioBuffer) {
          audioCtx.resume();
          const source = audioCtx.createBufferSource();
          source.buffer = audioBuffer;
          source.connect(audioCtx.destination);
          source.start();
        }

        const promises = [];
        promises.push(loadImage(&quot;steffes&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;steffes.jpg&quot;));
        promises.push(loadImage(&quot;bamse_arm&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bamse_arm.png&quot;));
        promises.push(loadImage(&quot;bamse_base&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bamse_base.png&quot;));
        promises.push(loadImage(&quot;tanks&#x2F;missil_00&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;tanks&#x2F;missil_00.gif&quot;));
        promises.push(loadImage(&quot;tanks&#x2F;05_herka_stroke&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;tanks&#x2F;05_herka_stroke.gif&quot;));
        promises.push(loadImage(&quot;tanks&#x2F;r05_herka_stroke&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;tanks&#x2F;r05_herka_stroke.gif&quot;));
        promises.push(loadImage(&quot;tanks&#x2F;truck_ammo&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;tanks&#x2F;truck_ammo.gif&quot;));
        promises.push(loadImage(&quot;011_bomb&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;011_bomb.gif&quot;));

        promises.push(loadImage(&quot;smoke&#x2F;001&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;smoke&#x2F;001.png&quot;));
        promises.push(loadImage(&quot;smoke&#x2F;002&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;smoke&#x2F;002.png&quot;));
        promises.push(loadImage(&quot;smoke&#x2F;003&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;smoke&#x2F;003.png&quot;));
        promises.push(loadImage(&quot;smoke&#x2F;004&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;smoke&#x2F;004.png&quot;));
        promises.push(loadImage(&quot;smoke&#x2F;005&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;smoke&#x2F;005.png&quot;));
        promises.push(loadImage(&quot;smoke&#x2F;006&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;smoke&#x2F;006.png&quot;));
        promises.push(loadImage(&quot;smoke&#x2F;007&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;smoke&#x2F;007.png&quot;));

        promises.push(loadImage(&quot;explosion&#x2F;001&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;explosion&#x2F;001.gif&quot;));
        promises.push(loadImage(&quot;explosion&#x2F;002&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;explosion&#x2F;002.gif&quot;));
        promises.push(loadImage(&quot;explosion&#x2F;003&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;explosion&#x2F;003.gif&quot;));
        promises.push(loadImage(&quot;explosion&#x2F;004&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;explosion&#x2F;004.gif&quot;));
        promises.push(loadImage(&quot;explosion&#x2F;005&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;explosion&#x2F;005.gif&quot;));
        promises.push(loadImage(&quot;explosion&#x2F;006&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;explosion&#x2F;006.gif&quot;));
        promises.push(loadImage(&quot;explosion&#x2F;007&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;explosion&#x2F;007.gif&quot;));
        promises.push(loadImage(&quot;explosion&#x2F;008&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;explosion&#x2F;008.gif&quot;));

        promises.push(loadImage(&quot;bridge&#x2F;001&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;001.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;002&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;002.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;003&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;003.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;004&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;004.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;005&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;005.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;006&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;006.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;007&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;007.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;008&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;008.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;009&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;009.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;010&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;010.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;011&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;011.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;012&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;012.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;013&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;013.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;014&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;014.jpg&quot;));
        promises.push(loadImage(&quot;bridge&#x2F;015&quot;, &quot;&#x2F;vplgame&#x2F;gfx&#x2F;bridge&#x2F;015.jpg&quot;));

        promises.push(loadAudio(&quot;01_explosion&quot;, &quot;&#x2F;vplgame&#x2F;audio&#x2F;01_explosion.wav&quot;));
        promises.push(loadAudio(&quot;01_missile&quot;, &quot;&#x2F;vplgame&#x2F;audio&#x2F;01_missile.wav&quot;));

        try {
          await Promise.all(promises);
        } catch (e) {
          console.error(e);
        }

        function renderLoop() {
          game.update(ctx, window.performance.now(), 700, 460);
          animationFrameId = window.requestAnimationFrame(renderLoop);
        }

        renderLoop();
      }

      async function run() {
        await init();
        await startGame();
      }

      run();
    &lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;div&gt;
    &lt;input id=&quot;debug&quot; type=&quot;checkbox&quot;&#x2F;&gt;&lt;label for=&quot;debug&quot;&gt;Debug bounding boxes&lt;&#x2F;label&gt;
&lt;&#x2F;div&gt;
👆Play it yourself. For extra retro fun: try fullscreen 👾
&lt;&#x2F;div&gt;
&lt;p&gt;On the surface, Värnpliktsspelet is a simple game: Protect the trucks filled
with conscripts and ammo using your ground-to-air BAMSE&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#bamse&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; missile launcher
during a training exercise. The threat is airplanes of the type C-130
Hercules&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#hercules&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; that have been mistakenly loaded with real bombs!&lt;&#x2F;p&gt;
&lt;p&gt;There are several resource management and tactics dimensions to the game, which
has an intense action flavor. You have a limited amount of missiles, and you
need to use them to protect your BAMSE system, a bridge, and the ammo trucks.&lt;&#x2F;p&gt;
&lt;p&gt;You get upgrades on every level that is divisible by three: Level 3, 6, 9, and
so on: Faster missiles, capacity to store more missiles, and repairs for BAMSE
and the bridge.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;resource-management&quot;&gt;Resource management&lt;&#x2F;h2&gt;
&lt;p&gt;You can try to knock out an airplane using two missiles, or take out a bomb
using one missile. At first that equation seems simple: Each airplane can drop
three bombs, so it&#x27;s cheaper to take out an airplane; and the decision keeps
getting easier since the airplanes carry more bombs each round. The problem is
that there are a lot of planes, and a lot of bombs being dropped. Unless you
focus at least some of the missiles on cleaning up bombs, you will run out of
ammo.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;strategy&quot;&gt;Strategy&lt;&#x2F;h2&gt;
&lt;p&gt;The bridge can take some damage, but can get repaired if you survive long
enough, meaning you can let it take a few hits. BAMSE can also take a few hits,
but beware: As long as BAMSE is damaged, missiles will behave unpredictably!
Ammo trucks can take two hits, which means that they can act as a shield for the
bridge, and for BAMSE. You can even sacrifice a few trucks since the trucks
carry a lot more ammunition than you can use, at least in the beginning.&lt;&#x2F;p&gt;
&lt;p&gt;The firing arm can&#x27;t be rotated to fire straight up, so you have to have the
right timing and be frugal with missiles to defend the ramp from bombs coming
from straight above. Some bombs will be borderline impossible to defend.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;implementation-old-and-new&quot;&gt;Implementation—old and new&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;threads&quot;&gt;Threads&lt;&#x2F;h2&gt;
&lt;p&gt;The old Java implementation had code running across three threads:
&lt;code&gt;RenderThread&lt;&#x2F;code&gt;, &lt;code&gt;LevelThread&lt;&#x2F;code&gt;, and &lt;code&gt;MoveThread&lt;&#x2F;code&gt;. It incorrectly peppered the
&lt;code&gt;synchronized&lt;&#x2F;code&gt; keyword on member fields, but not a single &lt;code&gt;synchronized&lt;&#x2F;code&gt; block
which I&#x27;m sure wasn&#x27;t very correct. The new Rust implementation
uses one thread—the JavaScript main thread—and a few &lt;code&gt;Mutex&lt;&#x2F;code&gt;es to appease the
borrow checker. The Java implementation should have used just one thread too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;framerate&quot;&gt;Framerate&lt;&#x2F;h2&gt;
&lt;p&gt;To keep the framerate and other parts of the program consistent, the Java
implementation makes liberal use of &lt;code&gt;Thread.sleep&lt;&#x2F;code&gt;, opting for &lt;code&gt;sleep(40)&lt;&#x2F;code&gt; to
control the framerate. Using a 40-millisecond sleep is equivalent to 25 fps. The
render loop also handled spurious thread wakes by doing a bit of extra sleep in
a loop until the target sleep time was reached.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of interpolating the positions of the different moveable elements, there
was a 50 milliseconds sleep in the &lt;code&gt;MoveThread&lt;&#x2F;code&gt;. Why 50 millis in the
&lt;code&gt;MoveThread&lt;&#x2F;code&gt;, but 40 in the &lt;code&gt;RenderThread&lt;&#x2F;code&gt;? I wish I could tell you. I&#x27;m not proud.
Any hiccups in the &lt;code&gt;MoveThread&lt;&#x2F;code&gt; would have caused the graphics to stall. That
might have been an OK call for a single player game, but I think time based
interpolation is generally the correct way to handle animation so that&#x27;s
something that will change in the new implementation.&lt;&#x2F;p&gt;
&lt;p&gt;The new implementation uses time based interpolation for movement and
animations, and &lt;code&gt;requestAnimationFrame&lt;&#x2F;code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#raf&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; to drive the updates from JavaScript.
Using &lt;code&gt;requestAnimationFrame&lt;&#x2F;code&gt; gives the game a framerate that matches the
display refresh rate.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hilariously-bad-bounding-boxes&quot;&gt;Hilariously bad bounding boxes&lt;&#x2F;h2&gt;
&lt;p&gt;Missiles need to be rotated when fired, and the canvas API can do that just fine
with some calls to &lt;code&gt;save&lt;&#x2F;code&gt;, &lt;code&gt;translate&lt;&#x2F;code&gt;, &lt;code&gt;rotate&lt;&#x2F;code&gt;, and &lt;code&gt;restore&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Bounding boxes aren&#x27;t much trickier, but I wanted to stay true to the original
game, so no fancy matrix transforms, just this fabulous bounding box:&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;missile bounding box size&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;rotated_size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; Size&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Size&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;new&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;        &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;width &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;rotation&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;cos&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;height &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;rotation&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;sin&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;        &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;width &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;rotation&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;sin&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;height &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;rotation&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;cos&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;The bounding box is a bit larger than necessary, but that&#x27;s not a problem I care
about. This is a problem I care about:&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Terrible bounding box&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    &lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;bounding_box_1.png&quot;&gt;
        &lt;img src=&quot;.&amp;#x2F;bounding_box_1.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    
    
&lt;&#x2F;div&gt;
&lt;p&gt;Images are drawn from pixel &lt;code&gt;(0,0)&lt;&#x2F;code&gt;, not from the center of the image, which
needs to be adjusted for. The old game didn&#x27;t do this, but I felt leaving that
bug in was a bridge too far. So we need to draw from the middle of the image,
but we also need to adjust all the bounding box intersection calculations.
Here&#x27;s the code for adjusting the drawing of the missile:&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;missile image draw code&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;canvas&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;save&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;canvas&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;translate&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;position&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;x&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; position&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;canvas&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;rotate&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;angle&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Draw the image centered on (x, y)
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;canvas&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;draw_image&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;missile_img&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt;size&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;width &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;2.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt;size&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;height &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;2.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;canvas&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;restore&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;which is obviously better&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Much better&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    &lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;bounding_box_2.png&quot;&gt;
        &lt;img src=&quot;.&amp;#x2F;bounding_box_2.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    
    
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;javascript-fun-and-rust-separation-of-concerns&quot;&gt;JavaScript fun and Rust separation of concerns&lt;&#x2F;h2&gt;
&lt;p&gt;Input (&lt;code&gt;mousemove&lt;&#x2F;code&gt;, &lt;code&gt;touchmove&lt;&#x2F;code&gt;, &lt;code&gt;mouseup&lt;&#x2F;code&gt;, and so on), resources (images,
sounds), and audio playback are handled by JavaScript. You can read all the
JavaScript glue code by inspecting the source of this page in your browser.&lt;&#x2F;p&gt;
&lt;p&gt;The Rust code is split into two parts: A &lt;code&gt;wasm&lt;&#x2F;code&gt; package, that contains the
wasm-bindgen&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#bindgen&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; code and implementations of the JavaScript shims for the
&lt;code&gt;Canvas&lt;&#x2F;code&gt; and &lt;code&gt;PlayAudio&lt;&#x2F;code&gt; traits defined in the main &lt;code&gt;engine&lt;&#x2F;code&gt; package. Separating the
implementation from the host wasn&#x27;t really necessary since I&#x27;m not planning on
implementing the game for any other platform than the web, but it was useful
insofar that I got some confidence that such a split will work for my real
project at work.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;Audio&lt;&#x2F;code&gt; trait is very simple; it&#x27;s defined in the &lt;code&gt;engine&lt;&#x2F;code&gt; package&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;engine&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-trait z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-trait z-rust&quot;&gt;trait&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-trait z-rust&quot;&gt;Audio&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-trait z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;play&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-trait z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;and implemented in the &lt;code&gt;wasm&lt;&#x2F;code&gt; package&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;wasm&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-struct z-rust&quot;&gt;struct&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-entity z-name z-struct z-rust&quot;&gt;AudioWeb&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-variable z-other z-member z-rust&quot;&gt;audio&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-type z-rust&quot;&gt;:&lt;&#x2F;span&gt; AudioBuffer,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; A JavaScript function called playAudio that uses an AudioContext
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; to be able to play multiple sounds at the same time.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-variable z-other z-member z-rust&quot;&gt;play_fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-type z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;web_sys&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;js_sys&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Function,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-struct z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-impl z-rust&quot;&gt;impl&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-entity z-name z-impl z-rust&quot;&gt;AudioWeb&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;audio&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; AudioBuffer, &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;play_fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;web_sys&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;js_sys&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; AudioWeb&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        AudioWeb &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt; audio&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; play_fn &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-impl z-rust&quot;&gt;impl&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;Audio &lt;span class=&quot;z-keyword z-other z-rust&quot;&gt;for&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt; &lt;span class=&quot;z-entity z-name z-impl z-rust&quot;&gt;AudioWeb&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;play&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;play_fn&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;call1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;JsValue&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-rust&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;audio&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-impl z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;Similarly, but much more code, for the &lt;code&gt;Canvas&lt;&#x2F;code&gt; trait.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lines-of-code&quot;&gt;Lines of code&lt;&#x2F;h2&gt;
&lt;p&gt;This is mostly a feature-for-feature remake of the original game, with some
additional bug fixes and arguably better structured code, so I wanted to see how
that affected the line count. Lines counted by tokei&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#tokei&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Java Applet&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; class=&quot;language-text z-code&quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;===============================================================================
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; Language            Files        Lines         Code     Comments       Blanks
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;===============================================================================
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; HTML                    2           28           19            1            8
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; Java                   24         2963         2094          320          549
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;===============================================================================
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; Total                  26         2991         2113          321          557
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;==============================================================================
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Rust&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; class=&quot;language-text z-code&quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;===============================================================================
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; Language            Files        Lines         Code     Comments       Blanks
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;===============================================================================
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; Shell                   1           10            5            2            3
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; TOML                    3           90           62           17           11
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;-------------------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; HTML                    1           14           13            0            1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; |- JavaScript           1          176          152            1           23
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; (Total)                            190          165            1           24
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;-------------------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; Rust                   40         2317         2077            9          231
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; |- Markdown             2            3            0            3            0
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; (Total)                           2320         2077           12          231
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;===============================================================================
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; Total                  45         2431         2157           28          246
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;===============================================================================
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The Rust implementation has 44 more lines, but the Java repository doesn&#x27;t have
any shell scripts for building artifacts, and is missing at least a JAR
manifest. When I set out to do this I thought Rust would fare a bit better than
what it did, but maybe Rust code is a bit more verbose than I give it credit
for. Let&#x27;s call it a draw.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;entity-component-system&quot;&gt;Entity Component System&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s hear what Wikipedia has to say about ECS&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#ecs&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Entity–component–system (ECS) is a software architectural pattern mostly used
in video game development for the representation of game world objects.
An ECS comprises entities composed from components of data, with systems
which operate on the components.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&quot;A monad is a monoid in the category of endofunctors&quot;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#monad&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; what?&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll spend the following sections trying to explain what an Entity Component
System is, and how Bevy ECS&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#bevy-ecs&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; works. The TL;DR is &quot;a database that
makes it possible to avoid the pointer soup software architecture&quot;. I just made
that up.&lt;&#x2F;p&gt;
&lt;div id=&quot;bevy-pin&quot;&gt;&lt;&#x2F;div&gt;
&lt;p&gt;I feel like I&#x27;ve only scratched the surface of what Bevy ECS can do. Correctly
utilized it promises parallel execution of systems that don&#x27;t have overlapping
queries, which seems in line with the promises of Rust&#x27;s fearless concurrency
story. I&#x27;ve had a few runtime panics from &lt;em&gt;holding it wrong&lt;&#x2F;em&gt;, which mostly
isn&#x27;t a thing in Rust from my five odd years of experience, so we will need to
build an intuition around how to avoid those crashes.&lt;&#x2F;p&gt;
&lt;p&gt;Put a pin in that last sentence, we&#x27;ll revisit it a little later.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;entities-and-components&quot;&gt;Entities and components&lt;&#x2F;h2&gt;
&lt;p&gt;Entities are instantiated by combining one or more components, each component
being an attribute of the entity and often one or more pieces of data associated
with the component. A unit in a strategy game would have a &lt;code&gt;Weapon&lt;&#x2F;code&gt;, a
&lt;code&gt;Position&lt;&#x2F;code&gt;, a &lt;code&gt;Team&lt;&#x2F;code&gt;, a &lt;code&gt;Faction&lt;&#x2F;code&gt; etc. &lt;code&gt;Position&lt;&#x2F;code&gt; being a mutable &lt;code&gt;(x, y)&lt;&#x2F;code&gt;
tuple, &lt;code&gt;Faction&lt;&#x2F;code&gt; being &lt;code&gt;terran&lt;&#x2F;code&gt;, &lt;code&gt;protoss&lt;&#x2F;code&gt;, or &lt;code&gt;zerg&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Like a database&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    &lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;ecs.svg&quot;&gt;
        &lt;img src=&quot;.&amp;#x2F;ecs.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    
    
    &lt;p&gt;Image by &lt;a href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;w&#x2F;index.php?title=File:ECS_Simple_Layout.svg&amp;amp;oldid=868167885&quot;&gt;Guypeter4&lt;&#x2F;a&gt;
(&lt;a href=&quot;https:&#x2F;&#x2F;creativecommons.org&#x2F;publicdomain&#x2F;zero&#x2F;1.0&#x2F;deed.en&quot;&gt;CC0&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;I think I would have put the entities as the rows and the components as the
columns, probably. That&#x27;s the way I think about entities anyway; an entity is a
row in a database with a checkmark in every column for the different components
that entity has.&lt;&#x2F;p&gt;
&lt;p&gt;In Värnpliktsspelet there are missiles, enemies, friends, a bridge and so on. A
missile is instantiated every time a &lt;code&gt;mouseup&lt;&#x2F;code&gt; or &lt;code&gt;touchup&lt;&#x2F;code&gt; event is registered
by the web browser.&lt;&#x2F;p&gt;
&lt;div id=&quot;spawn-missile&quot;&gt;&lt;&#x2F;div&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Spawning a missile&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; angle &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; ramp&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;angle&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;mouse_position&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; random_factor &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;MissileRamp&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-rust&quot;&gt;MAX_HEALTH&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; health&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;health&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; missile_speed &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; ramp&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;missile_speed &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;as&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;f64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;commands&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Missile&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;new&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;        angle&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;        random_factor&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;        time&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;now &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;+&lt;&#x2F;span&gt; random&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;next_float&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;300.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;as&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Position&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;new&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;33.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;390.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Size&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;new_with_rotation&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;46.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;24.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; angle&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Speed&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;new&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;missile_speed &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; angle&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;cos&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; missile_speed &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; angle&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;sin&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Timestamp&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;new&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;time&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;now&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;    Bounded&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;

&lt;p&gt;The &quot;missile entity&quot;, when spawned, is given the components &lt;code&gt;Missile&lt;&#x2F;code&gt;,
&lt;code&gt;Position&lt;&#x2F;code&gt;, &lt;code&gt;Size&lt;&#x2F;code&gt;, &lt;code&gt;Speed&lt;&#x2F;code&gt;, &lt;code&gt;Timestamp&lt;&#x2F;code&gt; and &lt;code&gt;Bounded&lt;&#x2F;code&gt;. Most of those are
self-explanatory, but &lt;code&gt;Timestamp&lt;&#x2F;code&gt; and &lt;code&gt;Bounded&lt;&#x2F;code&gt; might need a few words:
&lt;code&gt;Timestamp&lt;&#x2F;code&gt; is used to track &lt;em&gt;when&lt;&#x2F;em&gt; an entity last moved—for
interpolation—and &lt;code&gt;Bounded&lt;&#x2F;code&gt; is a marker component that is used to query
any entity that should be despawned when going out-of-bounds.&lt;&#x2F;p&gt;
&lt;p&gt;Notice that we don&#x27;t give entities names, and entities don&#x27;t have a custom
type: every entity is a &lt;code&gt;bevy_ecs::entity::Entity&lt;&#x2F;code&gt;. Entities are automatically
given an id that you can save for later, but I didn&#x27;t need to do that once for
this game.&lt;&#x2F;p&gt;
&lt;p&gt;Every time an entity is spawned it is added to the &quot;database&quot; of rows
(or columns, whatever is more intuitive to you), and it can be queried out
of the database and manipulated by systems.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;systems&quot;&gt;Systems&lt;&#x2F;h2&gt;
&lt;p&gt;Systems interact with the &lt;code&gt;World&lt;&#x2F;code&gt; by implementing functions that &lt;code&gt;Query&lt;&#x2F;code&gt; the
world for entities. Systems also retrieve resources and events. All of that is
supported by some type system magic, making it possible to just declare
what you need as function parameters—in any order—and it mostly does what you
think it does.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;A fairly complex but readable system declaration&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-documentation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt; This system recieves MouseUpEvents and performs world actions based on those
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;mouse_up_system&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; New events
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;evts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;EventReader&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;MouseUpEvent&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; The current game state, clicking &amp;quot;Start&amp;quot; on the initial screen
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; will mutate the game state by changing it from `Init` to `Running`
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;state&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;ResMut&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;GameState&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Commands spawn and despwan entities
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;commands&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; Commands,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; We need access to the missile ramp to fire missiles
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;query_missile_ramp&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Query&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; MissileRamp, &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;MousePosition, &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; Health&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Current world time in milliseconds
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;time&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Res&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;Time&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Any respectable game has an RNG
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;random&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;NonSend&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Arc&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;dyn Random&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; ...
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;Värnpliktsspelet is a tiny game, but I feel it has &lt;em&gt;a lot&lt;&#x2F;em&gt; of systems. I&#x27;d
imagine a huge game having a lot more but even the modest amount of systems in
this game take some mental effort to keep track of. Having a &lt;em&gt;system&lt;&#x2F;em&gt; for
structuring the ECS systems across different modules is required for any game
even slightly larger than this one. Maintaining discipline by not putting too
many things into one system also seems important to be able to maintain and
understand them over time.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Lots of systems&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;schedule&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;add_systems&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;reset_system&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;schedule&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;add_systems&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;missile_ramp_mouse_system&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;schedule&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;add_systems&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;mouse_position_system&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;schedule&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;add_systems&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;mouse_up_system&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;schedule&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;add_systems&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;next_level_missile_ramp_system&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;schedule&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;add_systems&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;generator_system&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;run_if&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;run_if_game_state_running&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; And 21 more ...
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;27 systems by my count&lt;&#x2F;p&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;My biggest struggle with these systems is that I started out with very few
components for the entities—I think most programmers feel &lt;em&gt;smart&lt;&#x2F;em&gt; when
we reuse things, doing the whole DRY thing and whatnot. But my (somewhat small)
amount of ECS experience tells me that I need to keep component reuse &lt;em&gt;dumb&lt;&#x2F;em&gt;.
&lt;code&gt;Position&lt;&#x2F;code&gt; and &lt;code&gt;MousePosition&lt;&#x2F;code&gt; are &lt;em&gt;different things&lt;&#x2F;em&gt;. I felt smart reusing the
&lt;code&gt;Position&lt;&#x2F;code&gt; component for my mouse position entity: &lt;code&gt;Mouse&lt;&#x2F;code&gt; and &lt;code&gt;Position&lt;&#x2F;code&gt;
together. But any query for things with a &lt;code&gt;Position&lt;&#x2F;code&gt; would also bring in the
&lt;code&gt;Mouse&lt;&#x2F;code&gt; causing a few minutes of confusion when the mouse position started to
jitter.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s have a look at the smoke system. When missiles travel across the screen
they leave trails of smoke that animate and move.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Smoke system&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;spawn_smoke_system&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Commands let you spawn or despawn entities
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;commands&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; Commands,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; An iterable query with mutable missiles 
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;query&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Query&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; Missile, &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;Position, &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;Speed, &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;Size&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Time is a global, called a Resource in Bevy ECS
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;time&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Res&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;Time&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Another global, but this one is !Send
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Using Arc here is a bit nonsensical but whatever
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;random&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;NonSend&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Arc&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;dyn Random&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;for&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; missile&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; position&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; speed&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; size&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;in&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; query &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;if&lt;&#x2F;span&gt; missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;smoke_counter &lt;span class=&quot;z-keyword z-operator z-comparison z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;0&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-rust&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt; time&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;now &lt;span class=&quot;z-keyword z-operator z-comparison z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;next_smoke_time &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;smoke_counter &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;-=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;next_smoke_time &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; time&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;now &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;+&lt;&#x2F;span&gt; random&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;next_float&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;300.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;as&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; smoke_decrease_x &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; speed&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;x &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;5.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; smoke_decrease_y &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; speed&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;y &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;5.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; ang_x &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;10.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;angle&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;cos&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;10.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;angle&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;sin&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; ang_y &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;3.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;angle&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;cos&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;3.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;angle&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;sin&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; offset_x &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; size&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;width &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;2.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;+&lt;&#x2F;span&gt; ang_x&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; offset_y &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; size&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;height &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;2.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;+&lt;&#x2F;span&gt; ang_y&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; dx &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;smoke_counter &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;as&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;f64&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; smoke_decrease_x &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; offset_x&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; dy &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;smoke_counter &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;as&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;f64&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; smoke_decrease_y &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; offset_y&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            commands&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;                &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Smoke&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;new&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;time&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;now &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;200&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;                &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Position&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;new&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;position&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;x &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; dx&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; position&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;y &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; dy&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;                &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Size&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;new&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;16.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;16.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;                &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Smoke moves to the left with a random amount 0-10
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;                &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; and upwards -4 per time unit.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;                &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Speed&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;new&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;random&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;next_float&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;10.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;4.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;                &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Timestamp&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;new&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;time&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;now&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;                Moveable&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;                Bounded&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;            &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;Notice how when we spawn &lt;code&gt;Smoke&lt;&#x2F;code&gt;, we add a &lt;code&gt;Moveable&lt;&#x2F;code&gt; component. That&#x27;s because
almost everything that moves on screen is &lt;code&gt;Moveable&lt;&#x2F;code&gt; and is handled by this
simple system:&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Moving movables&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;move_moveables_system&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;time&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Res&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;Time&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Any Moveable that has a Position, a Speed, and a Timestamp
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;query&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Query&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; Position, &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;Speed, &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; Timestamp&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;, &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;With&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;Moveable&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;for&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; position&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; speed&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; timestamp&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;in&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; query &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; There might be rounding errors to take into account for
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; interpolation, but I Have Zero Fucks Left To Give
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; diff &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;time&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;now &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; timestamp&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;time&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;as&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;f64&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;120.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        position&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;x &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;+=&lt;&#x2F;span&gt; diff &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; speed&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;x&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        position&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;y &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;+=&lt;&#x2F;span&gt; diff &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; speed&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;y&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        timestamp&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;time &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; time&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;now&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;But missiles can have a bit of randomness to them if the missile ramp is
damaged, so we need a separate system for that. To make sure missiles aren&#x27;t
moved twice, missiles aren&#x27;t &lt;code&gt;Moveable&lt;&#x2F;code&gt;—we simply don&#x27;t add &lt;code&gt;Moveable&lt;&#x2F;code&gt; when we
&lt;a href=&quot;#spawn-missile&quot;&gt;spawn a &lt;code&gt;Missile&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Moving missiles&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;move_missiles_system&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;time&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Res&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;Time&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; All Missiles
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;query&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Query&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;Missile, &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; Position, &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;Speed, &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; Timestamp&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;random&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;NonSend&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Arc&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;dyn Random&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;for&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;missile&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; position&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; speed&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; timestamp&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;in&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; query &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Might even be a negative amount of fucks, actually
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; diff &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;time&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;now &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; timestamp&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;time&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;as&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;f64&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;120.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        position&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;x &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;+=&lt;&#x2F;span&gt; diff &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; speed&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;x&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        position&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;y &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;+=&lt;&#x2F;span&gt; diff &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; speed&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;y&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;if&lt;&#x2F;span&gt; missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;random_factor &lt;span class=&quot;z-keyword z-operator z-comparison z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;0&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            position&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;x &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;+=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;2.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; diff &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; random&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;next_float&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-rust&quot;&gt;MAX&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;%&lt;&#x2F;span&gt; missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;random_factor&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;as&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;f64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            position&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;y &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;+=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;2.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; diff &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt; random&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;next_float&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-rust&quot;&gt;MAX&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;%&lt;&#x2F;span&gt; missile&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;random_factor&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;as&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;f64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        timestamp&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;time &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; time&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;now&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;&#x2F;h2&gt;
&lt;p&gt;Resources in Bevy ECS are global values that can be read and mutated from systems.
There&#x27;s only one of each resource, and it&#x27;s identified by its type. In
Värnpliktsspelet the resources are &lt;code&gt;Time&lt;&#x2F;code&gt;, &lt;code&gt;Images&lt;&#x2F;code&gt;, &lt;code&gt;Sounds&lt;&#x2F;code&gt;, &lt;code&gt;GameState&lt;&#x2F;code&gt;,
&lt;code&gt;Random&lt;&#x2F;code&gt;, and &lt;code&gt;DebugBoundingBoxes&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;events&quot;&gt;Events&lt;&#x2F;h2&gt;
&lt;p&gt;This is the full list of events used by Värnpliktsspelet:&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Events&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;EventRegistry&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;register_event&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;MousePositionEvent&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; world&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;EventRegistry&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;register_event&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;MouseUpEvent&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; world&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;EventRegistry&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;register_event&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;NextLevelEvent&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; world&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;EventRegistry&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;register_event&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;InitEvent&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; world&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;Events are used as communication channels between systems or from the outside
world into systems. Whenever the JavaScript side of the game registers &lt;code&gt;mouseup&lt;&#x2F;code&gt;
or &lt;code&gt;touchup&lt;&#x2F;code&gt;, a &lt;code&gt;MouseUpEvent&lt;&#x2F;code&gt; is sent&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Mouse &#x2F; Touch up&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;mouse_up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;self&lt;&#x2F;span&gt;, &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;f64&lt;&#x2F;span&gt;, &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;f64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-variable z-language z-rust&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;world&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;send_event&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;MouseUpEvent &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt; x&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; y &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;h1 id=&quot;bevy-ecs-inconveniences&quot;&gt;Bevy ECS Inconveniences&lt;&#x2F;h1&gt;
&lt;p&gt;Remember when I said to &lt;a href=&quot;#bevy-pin&quot;&gt;put a pin in it&lt;&#x2F;a&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;This section will be grist to the mill for the people that love to dunk on the
&lt;em&gt;if it compiles it works&lt;&#x2F;em&gt; mantra that Rust evangelists love to profess. If you
want to keep dunking, there are plenty of places for that. I&#x27;m mostly siding
with the Rust truthers, but like everything in software engineering&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;div class=&quot;note-title&quot;&gt;&lt;&#x2F;div&gt;
    &lt;p&gt;IT&#x27;S 👏 A 👏 TRADE-OFF&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;I have two gripes: crashing due to concurrent exclusive access&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#exclusive&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and
despawning the same entity multiple times.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;concurrent-exclusive-access&quot;&gt;Concurrent exclusive access&lt;&#x2F;h2&gt;
&lt;p&gt;Rust promises safe and sound programs as long as we observe all the invariants
of any &lt;code&gt;unsafe&lt;&#x2F;code&gt; code we call, and as long as we don&#x27;t write any incorrect
&lt;code&gt;unsafe&lt;&#x2F;code&gt; code. Most Rust programs call &lt;code&gt;unsafe&lt;&#x2F;code&gt; code through safe interfaces,
but I rarely write any &lt;code&gt;unsafe&lt;&#x2F;code&gt; code myself. What Rust doesn&#x27;t do is promise
programs that don&#x27;t leak memory, that don&#x27;t have deadlocks, etc. etc. etc.&lt;&#x2F;p&gt;
&lt;p&gt;One thing that I&#x27;ve gotten used to is that the type system &lt;em&gt;mostly has my back&lt;&#x2F;em&gt;.
If I don&#x27;t hold it right, I will get a compiler error. If I try to have
exclusive access&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#exclusive&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; of a piece of data in two different parts of my
program at the same time, the Rust compiler will tell me that I did something
I&#x27;m not allowed to do. As an example, if I tried to loop over the same mutable
slice twice, Rust would be disappointed in me:&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Not a proud parent&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;double_mutable_loop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;positions&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; [Position]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;  error[E0499]: cannot borrow `*positions` as mutable more than once at a time
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;for&lt;&#x2F;span&gt; f_pos &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;in&lt;&#x2F;span&gt; positions&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;iter_mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;               --------------------
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;               |
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;               first mutable borrow occurs here
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;               first borrow later used here
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;for&lt;&#x2F;span&gt; e_pos &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;in&lt;&#x2F;span&gt; positions&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;iter_mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;                   ^^^^^^^^^ second mutable borrow occurs here
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;Bevy ECS &lt;code&gt;Query&lt;&#x2F;code&gt;—or any other memory management abstraction that bypasses the
borrow checker, like &lt;code&gt;RefCell&lt;&#x2F;code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#refcell&quot;&gt;13&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;—lets you write code that breaks the
rules but instead lead to runtime panics when used wrong. I&#x27;m writing code that
looks like it should work, it looks like the compiler should yell at me because
I&#x27;m looping mutably over the same slices of memory, but it can&#x27;t tell me because
it doesn&#x27;t have that information.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;OOPSIE WOOPSIE!! Uwu We made a fucky wucky!!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-documentation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt; This will trigger a runtime crash
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;double_mutable_loop_system&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; The list of mutable positions here
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;query_friends&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Query&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;Friend, &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; Position&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Can overlap wit the list of mutable positions here at runtime
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;query_enemies&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Query&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;Enemy, &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; Position&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;for&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;_friend&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; f_pos&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;in&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; query_friends &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;for&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;_enemy&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; e_pos&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;  &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;in&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; query_enemies &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;tracing&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;info&lt;span class=&quot;z-keyword z-operator z-logical z-rust&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;This code will never execute&lt;span class=&quot;z-punctuation z-definition z-string z-end z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            f_pos&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;y &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;100.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            e_pos&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;y &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;100.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-float z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;knowyourmeme.com&#x2F;memes&#x2F;oopsie-woopsie&quot;&gt;Know Your Meme&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;Which inevitably leads to a runtime crash&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;I am inevitable&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;text&quot; class=&quot;language-text z-code&quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;panicked at ~&#x2F;.cargo&#x2F;registry&#x2F;src&#x2F;index.crates.io-6f17d22bba15001f&#x2F;bevy_ecs-0.15.0-rc.2&#x2F;src&#x2F;system&#x2F;system_param.rs:356:5:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;error[B0001]: Query&amp;lt;(&amp;amp;engine::objects::enemy::Enemy, &amp;amp;mut engine::primitive::position::Position), ()&amp;gt; in system engine::double_mutable_loop_system accesses component(s) engine::primitive::position::Position in a way that conflicts with a previous system parameter. Consider using `Without&amp;lt;T&amp;gt;` to create disjoint Queries or merging conflicting Queries into a `ParamSet`. See: https:&#x2F;&#x2F;bevyengine.org&#x2F;learn&#x2F;errors&#x2F;b0001
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Stack:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Error
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    at imports.wbg.__wbg_new_8a6f238a6ece86ea (http:&#x2F;&#x2F;localhost:8000&#x2F;pkg&#x2F;wasm.js:408:21)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    at http:&#x2F;&#x2F;localhost:8000&#x2F;pkg&#x2F;wasm_bg.wasm:wasm-function[426]:0x49e5c
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    at http:&#x2F;&#x2F;localhost:8000&#x2F;pkg&#x2F;wasm_bg.wasm:wasm-function[1017]:0x56324
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    at http:&#x2F;&#x2F;localhost:8000&#x2F;pkg&#x2F;wasm_bg.wasm:wasm-function[167]:0x30cab
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    at http:&#x2F;&#x2F;localhost:8000&#x2F;pkg&#x2F;wasm_bg.wasm:wasm-function[127]:0x2a400
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    at http:&#x2F;&#x2F;localhost:8000&#x2F;pkg&#x2F;wasm_bg.wasm:wasm-function[62]:0x6367
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    at GameHandle.update (http:&#x2F;&#x2F;localhost:8000&#x2F;pkg&#x2F;wasm.js:261:14)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    at renderLoop (http:&#x2F;&#x2F;localhost:8000&#x2F;:175:12)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    at startGame (http:&#x2F;&#x2F;localhost:8000&#x2F;:179:5)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    at async run (http:&#x2F;&#x2F;localhost:8000&#x2F;:184:5)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;The correct intuition to have is that Bevy ECS&#x27; &lt;code&gt;Query&lt;&#x2F;code&gt; is analogous to
&lt;code&gt;RefCell&lt;&#x2F;code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#refcell&quot;&gt;13&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Avoid mutably &#x2F; exclusively accessing the same component in
the same system and everything will work out. Just Be Careful, is what I&#x27;m
trying to say. At least we get a runtime panic instead of memory corruption,
like it would in memory unsafe languages.&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;div class=&quot;note-title&quot;&gt;UPDATE!! 2025-01-07&lt;&#x2F;div&gt;
    &lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;tech.lgbt&#x2F;@laund&quot;&gt;@laund@tech.lgbt&lt;&#x2F;a&gt; replied
to &lt;a href=&quot;https:&#x2F;&#x2F;hachyderm.io&#x2F;@laund@tech.lgbt&#x2F;113787402663198634&quot;&gt;my post on mastodon&lt;&#x2F;a&gt;
to clarify that systems are checked on first execution of their schedule, so
there doesn&#x27;t need to be an actual memory violation for the panic to happen—Bevy
ECS will let us know much earlier.&lt;&#x2F;p&gt;
&lt;p&gt;I also visited &lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;learn&#x2F;errors&#x2F;b0001&#x2F;&quot;&gt;the link&lt;&#x2F;a&gt; in the
error message, which goes to a page that teaches us that there are two ways to
work around having exclusive access to the same component in two queries in a
system:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Using the &lt;code&gt;With&amp;lt;ComponentType&amp;gt;&lt;&#x2F;code&gt; filter on one query and
&lt;code&gt;Without&amp;lt;ComponentType&amp;gt;&lt;&#x2F;code&gt; filter on the other&lt;&#x2F;li&gt;
&lt;li&gt;Use a &lt;code&gt;ParamSet&lt;&#x2F;code&gt; which makes it possible to have at most eight queries with
overlapping exclusive access&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;To me this is a minor inconvenience. If you&#x27;re doing anything remotely serious
you will have unit tests, system tests, or integration tests, as well as manual
run-throughs of your code. If you don&#x27;t have any of those:
tough luck. I don&#x27;t want to start a language war here, but if I was coming from
literally any other programming language, this wouldn&#x27;t be the hill I&#x27;d die on.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;despawning-an-entity-multiple-times&quot;&gt;Despawning an entity multiple times&lt;&#x2F;h2&gt;
&lt;p&gt;In the end, I categorized the previous section as a &quot;minor inconvenience&quot;,
making this section a Microscopic Inconvenience at worst.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not uncommon for entities in Värnpliktsspelet to be despawned more than once.
Since systems run one after the other—I blame JavaScript—and Bevy ECS has a policy
of not removing despawned entities until after a full world update, for good reasons,
it&#x27;s possible to have multiple despawns of the same entity. For example, a bomb
could intersect with a missile in the same update as it intersects with a truck.&lt;&#x2F;p&gt;
&lt;p&gt;Multiple despawns of the same entity don&#x27;t lead to a runtime crash, it just
prints an error message:&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Multiple despawns&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ~&#x2F;.cargo&#x2F;registry&#x2F;src&#x2F;index.crates.io-6f17d22bba15001f&#x2F;bevy_ecs-0.15.0-rc.2&#x2F;src&#x2F;world&#x2F;mod.rs:1532 error[B0003]: crates&#x2F;engine&#x2F;src&#x2F;lib.rs:592:49: Could not despawn entity 25v32#137438953497 because it doesn&amp;#39;t exist in this World. See: https:&#x2F;&#x2F;bevyengine.org&#x2F;learn&#x2F;errors&#x2F;b0003
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;As far as I can tell, the policy is that this is something that each game should
handle somehow. One piece of advice is
to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bevyengine&#x2F;bevy&#x2F;discussions&#x2F;2658&quot;&gt;handle despawning in its own system&lt;&#x2F;a&gt;
by checking the hitpoints or some other piece of shared data. Another piece of
advice from that same thread is to send a despawn event. I imagine it could be
possible to add some sort of &lt;code&gt;IsDespawned&lt;&#x2F;code&gt; component too.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;final-notes&quot;&gt;Final notes&lt;&#x2F;h1&gt;
&lt;p&gt;I think the ECS pattern is an excellent tool to have in your software
development toolbox, and I think that it&#x27;s especially useful when you&#x27;re doing
computer game style software. I&#x27;m looking at adopting this pattern at work for
our cross-platform rendering stack. It&#x27;s not a game engine, but it&#x27;s also
not-not a game engine.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;references&quot;&gt;References&lt;&#x2F;h1&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;stefan&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;stefanli&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;stefanli&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;vplr&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sv.wikipedia.org&#x2F;wiki&#x2F;V%C3%A4rnpliktsr%C3%A5det&quot;&gt;https:&#x2F;&#x2F;sv.wikipedia.org&#x2F;wiki&#x2F;V%C3%A4rnpliktsr%C3%A5det&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;ecs&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Entity_component_system&quot;&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Entity_component_system&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;bevy&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;&quot;&gt;https:&#x2F;&#x2F;bevyengine.org&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;bamse&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;RBS_23&quot;&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;RBS_23&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;hercules&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Lockheed_C-130_Hercules&quot;&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Lockheed_C-130_Hercules&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;raf&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;Window&#x2F;requestAnimationFrame&quot;&gt;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;Window&#x2F;requestAnimationFrame&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;bindgen&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustwasm&#x2F;wasm-bindgen&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;rustwasm&#x2F;wasm-bindgen&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;tokei&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;XAMPPRocky&#x2F;tokei&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;XAMPPRocky&#x2F;tokei&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;monad&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;10&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;3870088&#x2F;a-monad-is-just-a-monoid-in-the-category-of-endofunctors-whats-the-problem&quot;&gt;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;3870088&#x2F;a-monad-is-just-a-monoid-in-the-category-of-endofunctors-whats-the-problem&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;bevy-ecs&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;11&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;bevy-ecs&quot;&gt;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;bevy-ecs&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;exclusive&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;12&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;dtolnay&#x2F;latest&#x2F;dtolnay&#x2F;macro._02__reference_types.html&quot;&gt;https:&#x2F;&#x2F;docs.rs&#x2F;dtolnay&#x2F;latest&#x2F;dtolnay&#x2F;macro._02__reference_types.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;refcell&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;13&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;cell&#x2F;index.html#refcellt&quot;&gt;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;cell&#x2F;index.html#refcellt&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Segmenting my home network for defence in depth</title>
        <published>2024-07-14T00:00:00+00:00</published>
        <updated>2024-07-14T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/segmenting-my-home-network-for-defence-in-depth/"/>
        <id>https://zkc.se/blog/segmenting-my-home-network-for-defence-in-depth/</id>
        <content type="html" xml:base="https://zkc.se/blog/segmenting-my-home-network-for-defence-in-depth/">&lt;p&gt;I generally know what&#x27;s installed and running on my home computers, but I don&#x27;t know
what&#x27;s running on managed devices like Zigbee temperature loggers, Sonos speakers,
or Chromecasts. I finally managed to segment my home network into multiple VLANs
to achieve defence in depth&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#defence_in_depth&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h1&gt;
&lt;p&gt;I use a
&lt;em&gt;Dream Machine Pro&lt;&#x2F;em&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#dream_machine_pro&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; as my router,
which is mounted in a 19&quot;&#x2F;37U rack. I&#x27;ve always dreamed of having my own rack (weird?),
and now I have one — which feels great. The next thing on my list of wants for my
homelab is a 1U or 2U RISC-V server. We&#x27;re probably a few years from being able to buy actually
good RISC-V commodity servers though.&lt;&#x2F;p&gt;
&lt;p&gt;When I got the Dream Machine Pro, I started out by creating a Guest network, but
I hesitated creating an IoT network since I thought it would be a pain to
move my devices over to the new network — and I was right, more on that later.
The latest OpenSSH vulnerability, nicknamed regreSSHion&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#regresshion&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;,
was the last nail in the coffin for me. RegreSSHion isn&#x27;t particularly related to
rogue IoT devices, rather an increasing feeling of dread about how much bad C-code is running
24&#x2F;7 in my home.&lt;&#x2F;p&gt;
&lt;p&gt;To get started, I needed some help, so I followed the steps in the excellent
YouTube tutorial&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#crosstalk_yt&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; by Crosstalk Solutions, but that
video is from July 2021 — almost 3 years ago. It was relatively simple
to follow along, it was just a matter of finding where Ubiquiti had moved things
in their UI since then.&lt;&#x2F;p&gt;
&lt;p&gt;When I told my friend Markus what I was doing, he joked that in 1999 his father
had been right about the evil printer in their house and how it would spread
viruses to their computer. After that I decided to move my printer into the IoT
network, too.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;legacy-network-topology&quot;&gt;Legacy network topology&lt;&#x2F;h1&gt;
&lt;p&gt;Before restructuring my network setup I had my Default network and one Guest
network, with them being segmented like this. The Guest network has access to
the internet, but can&#x27;t access anything in the Default network. The Default
network can&#x27;t access anything in the Guest network either. This is handled by
the Dream Machine Pro&#x27;s &quot;Guest network&quot; feature, that can be set as an option
when creating a network. No additional firewall configuration is necessary.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Initial network topology&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;txt&quot; class=&quot;language-txt z-code&quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ᯤ WiFi                  ᯤ WiFi-Guest
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;┌─────────────────┐     ┌─────────────────┐
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;│ Default         │     │ Guest (VLAN2)   │
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;│ 10.6.0.0&#x2F;24     │     │ 192.168.1.0&#x2F;24  │
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;└────────┬────────┘     └─────┬───────────┘
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;         │     ┌──────────┐   │
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;         └────►│ Internet │◄──┘
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;               └──────────┘
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;h1 id=&quot;new-network-layout&quot;&gt;New network layout&lt;&#x2F;h1&gt;
&lt;p&gt;After following the YouTube tutorial&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#crosstalk_yt&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, I ended up with the following
topology:&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;New network topology&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;txt&quot; class=&quot;language-txt z-code&quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ᯤ WiFi                  ᯤ WiFi-IoT              ᯤ WiFi-Guest
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;│ Default         ├────►│ IOT (VLAN3)     │     │ Guest (VLAN2)   │
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;│ 10.6.0.0&#x2F;24     │     │ 10.7.0.0&#x2F;24     │     │ 192.168.1.0&#x2F;24  │
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;└────────┬────────┘     └────────┬────────┘     └────────┬────────┘
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;         │                  ┌────▼─────┐                 │
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;         └─────────────────►│ Internet │◄────────────────┘
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                            └──────────┘
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;Which, honestly, doesn&#x27;t say much. I&#x27;ll try to give a few details.&lt;&#x2F;p&gt;
&lt;p&gt;The key thing is to not subnet yourself into a hole&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#jessfraz_subnet&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; while doing this —
in other words making sure that the VLAN you&#x27;re in doesn&#x27;t get firewalled in a
way that makes it impossible to get out of without doing a factory reset on the router.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;virtual-network-wifi&quot;&gt;Virtual Network &amp;amp; WiFi&lt;&#x2F;h2&gt;
&lt;p&gt;The first step is to add a new VLAN. It can be added under
Network &amp;gt; Settings &amp;gt; Networks. I called my network IOT and gave it the IP range
10.7.0.0&#x2F;24. My Default network already has 10.6.0.0&#x2F;24 and my Guest network has
192.168.1.0&#x2F;24.&lt;&#x2F;p&gt;
&lt;p&gt;Then I assigned a new WiFi SSID called WiFi-IoT and connected it to the IOT VLAN.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ip-groups&quot;&gt;IP Groups&lt;&#x2F;h2&gt;
&lt;p&gt;Time to create the following IP Groups, which can be done under
Network &amp;gt; Settings &amp;gt; Profiles &amp;gt; IP Groups.&lt;&#x2F;p&gt;
&lt;div class=&quot;hscroll&quot;&gt;
    &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Name&lt;&#x2F;th&gt;&lt;th&gt;Type&lt;&#x2F;th&gt;&lt;th&gt;Settings&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Local Network RFC1918&lt;&#x2F;td&gt;&lt;td&gt;IPv4 Address&#x2F;Subnet&lt;&#x2F;td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;10.0.0.0&#x2F;8&lt;&#x2F;li&gt;&lt;li&gt;192.168.0.0&#x2F;16&lt;&#x2F;li&gt;&lt;li&gt;172.16.0.0&#x2F;12&lt;&#x2F;li&gt;&lt;&#x2F;ul&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;IoT to Other GW block&lt;&#x2F;td&gt;&lt;td&gt;IPv4 Address&#x2F;Subnet&lt;&#x2F;td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;10.6.0.1&lt;&#x2F;li&gt;&lt;li&gt;192.168.1.1&lt;&#x2F;li&gt;&lt;&#x2F;ul&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;All GW Addresses&lt;&#x2F;td&gt;&lt;td&gt;IPv4 Address&#x2F;Subnet&lt;&#x2F;td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;10.6.0.1&lt;&#x2F;li&gt;&lt;li&gt;192.168.1.1&lt;&#x2F;li&gt;&lt;li&gt;10.7.0.1&lt;&#x2F;li&gt;&lt;&#x2F;ul&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;UDM-pro access ports&lt;&#x2F;td&gt;&lt;td&gt;Port Group&lt;&#x2F;td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;80&lt;&#x2F;li&gt;&lt;li&gt;443&lt;&#x2F;li&gt;&lt;li&gt;22&lt;&#x2F;li&gt;&lt;&#x2F;ul&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;

&lt;&#x2F;div&gt;
&lt;h2 id=&quot;firewall-rules&quot;&gt;Firewall rules&lt;&#x2F;h2&gt;
&lt;p&gt;And then, the all-important firewall rules, which are configured under
Network &amp;gt; Settings &amp;gt; Security &amp;gt; Traffic &amp;amp; Firewall Rules. All of these rules need to
be marked &quot;Before predefined&quot;.&lt;&#x2F;p&gt;
&lt;div class=&quot;hscroll&quot;&gt;
    &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Name&lt;&#x2F;th&gt;&lt;th&gt;Type&lt;&#x2F;th&gt;&lt;th&gt;Action&lt;&#x2F;th&gt;&lt;th&gt;Source&lt;&#x2F;th&gt;&lt;th&gt;Destination&lt;&#x2F;th&gt;&lt;th&gt;Match State&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Allow established &amp;amp; related&lt;&#x2F;td&gt;&lt;td&gt;LAN In&lt;&#x2F;td&gt;&lt;td&gt;Accept&lt;&#x2F;td&gt;&lt;td&gt;Any&lt;&#x2F;td&gt;&lt;td&gt;Any&lt;&#x2F;td&gt;&lt;td&gt;MANUAL: Established, Related&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Allow Default to anywhere&lt;&#x2F;td&gt;&lt;td&gt;LAN In&lt;&#x2F;td&gt;&lt;td&gt;Accept&lt;&#x2F;td&gt;&lt;td&gt;Network &amp;gt; Default&lt;&#x2F;td&gt;&lt;td&gt;Port&#x2F;IP Group &amp;gt; Local Network RFC1918&lt;&#x2F;td&gt;&lt;td&gt;AUTO&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Block inter-VLAN traffic&lt;&#x2F;td&gt;&lt;td&gt;LAN In&lt;&#x2F;td&gt;&lt;td&gt;Drop&lt;&#x2F;td&gt;&lt;td&gt;Port &#x2F; IP Group &amp;gt; Local Network RFC1918&lt;&#x2F;td&gt;&lt;td&gt;Port&#x2F;IP Group &amp;gt; Local Network RFC1918&lt;&#x2F;td&gt;&lt;td&gt;AUTO&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Block IoT To GW&lt;&#x2F;td&gt;&lt;td&gt;LAN Local&lt;&#x2F;td&gt;&lt;td&gt;Drop&lt;&#x2F;td&gt;&lt;td&gt;Network &amp;gt; IOT&lt;&#x2F;td&gt;&lt;td&gt;Port&#x2F;IP Group &amp;gt; IoT to Other GW block&lt;&#x2F;td&gt;&lt;td&gt;AUTO&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Block IoT from UDM-Pro access&lt;&#x2F;td&gt;&lt;td&gt;LAN Local&lt;&#x2F;td&gt;&lt;td&gt;Drop&lt;&#x2F;td&gt;&lt;td&gt;Network &amp;gt; IOT&lt;&#x2F;td&gt;&lt;td&gt;Port&#x2F;IP Group &amp;gt; [Address Group] All GW Addresses, [Port Group] UDM-pro access ports&lt;&#x2F;td&gt;&lt;td&gt;AUTO&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;The first rule, &lt;em&gt;Allow established &amp;amp; related&lt;&#x2F;em&gt;, has to be the top &#x2F; first one. It
allows network connections to be established between the networks, and importantly
it lets the IoT network connect back to the Default network once a device in the
Default network has initiated a connection.&lt;&#x2F;p&gt;
&lt;p&gt;The second rule, &lt;em&gt;Allow Default to anywhere&lt;&#x2F;em&gt;, lets the Default network talk to any
local network in the RFC1918 address space.&lt;&#x2F;p&gt;
&lt;p&gt;The third rule, &lt;em&gt;Block inter-VLAN traffic&lt;&#x2F;em&gt;, blocks all other inter-RFC1918 traffic.&lt;&#x2F;p&gt;
&lt;p&gt;The fourth rule, &lt;em&gt;Block IoT To GW&lt;&#x2F;em&gt;, blocks the IoT network from accessing the gateway
IP-addresses in the Default network and the Guest network.&lt;&#x2F;p&gt;
&lt;p&gt;And lastly, The fifth rule, &lt;em&gt;Block IoT from UDM-Pro access&lt;&#x2F;em&gt;, blocks the IoT network
from accessing the management interfaces on the router (ports 80, 443, and 22),
without blocking it from accessing the gateway functionality it needs.
The fourth rule already blocks the IoT network completely from the gateway interfaces on the
Default network and the Guest network, so this technically only blocks it from
the management ports on the IoT gateway, but the rule still prohibits the ports
on all the gateways. Doing it like that prevents future changes from introducing
mistakes — even though mistakes are still possible.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;The firewall rules, working together&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;pre data-lang=&quot;txt&quot; class=&quot;language-txt z-code&quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ┌─────────────────┐       Connect: Allow        ┌─────────────────┐ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; │ Default         ├────────────────────────────►│ IoT             │ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; │ 10.6.0.0&#x2F;24     │Response: Allow (Established)│ 10.7.0.0&#x2F;24     │ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; │                 │◄────────────────────────────┤                 │ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;---------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; │                 │        Connect: Deny        │                 │ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; │                 │◄────────────────────────────┤                 │ 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; └─────────────────┘                             └─────────────────┘ 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Established &amp;amp; related connections are allowed, but unestablished or unrelated
connections are denied. In the diagram we see communication between the Default
network and the IoT network when the Default network initiates the connection.
We also see that when the IoT network initiates a connection, and it is unestablished
or unrelated, it is denied.&lt;&#x2F;p&gt;

    
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;mdns-discovery&quot;&gt;mDNS discovery&lt;&#x2F;h2&gt;
&lt;p&gt;To get mDNS discovery working between the Default network and the IoT network,
you need to set up &quot;IoT Auto-Discovery&quot; under
Network &amp;gt; Settings &amp;gt; Networks &amp;gt; Multicast Settings &amp;gt; IoT Auto-Discovery, click
edit and make sure the Default and IOT networks are both in the list.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;moving-my-iot-devices-over-to-the-new-wifi-iot-ssid&quot;&gt;Moving my IoT devices over to the new WiFi-IoT SSID&lt;&#x2F;h1&gt;
&lt;p&gt;This was more painful than I had hoped it would be. More painful than it &lt;em&gt;needs&lt;&#x2F;em&gt; to be.
I thought moving the Chromecast would be the easiest, then the Sonos and I honestly
thought my Nedis Zigbee hub thing would be the most painful. Boy was I wrong!&lt;&#x2F;p&gt;
&lt;p&gt;The Sonos and the Chromecast were absolutely terrible to move over. Required a
total factory reset of both devices. Is this the level of configurability we
should expect from billion-dollar companies? I wasted a lot of time trying to
figure out how to move them over, but it seems like it simply isn&#x27;t possible
to change the SSID or password on those devices, once configured. Let me know
if I&#x27;m wrong.&lt;&#x2F;p&gt;
&lt;p&gt;The Nedis Zigbee thing was a breeze, took like 2 minutes. I guess that&#x27;s the difference
several billion dollars make.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;future-improvements&quot;&gt;Future improvements&lt;&#x2F;h1&gt;
&lt;p&gt;One big thing would be to let the Guest network be able to access the IoT network
to be able to use my Chromecasts, Sonos, etc. That would require me to stop
using the convenient &quot;Guest network&quot; feature, but it shouldn&#x27;t be too complicated
to add the necessary firewall rules manually.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;references&quot;&gt;References&lt;&#x2F;h1&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;defence_in_depth&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Defence in depth – &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Defense_in_depth_(computing)&quot;&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Defense_in_depth_(computing)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;dream_machine_pro&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Dream Machine Pro – &lt;a href=&quot;https:&#x2F;&#x2F;ubntwiki.com&#x2F;products&#x2F;unifi&#x2F;unifi_dream_machine_pro&quot;&gt;https:&#x2F;&#x2F;ubntwiki.com&#x2F;products&#x2F;unifi&#x2F;unifi_dream_machine_pro&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;regresshion&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;RegreSSHion – &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;RegreSSHion&quot;&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;RegreSSHion&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;crosstalk_yt&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;IoT Network Setup - UDM-Pro 2021 – &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;UGBobTInIBc&quot;&gt;https:&#x2F;&#x2F;youtu.be&#x2F;UGBobTInIBc&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;jessfraz_subnet&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Jessie Frazelle subnetting herself into a hole. This was fun at the time (2017) and I still remember it. The tweet is gone, though. &lt;a href=&quot;https:&#x2F;&#x2F;blog.jessfraz.com&#x2F;post&#x2F;home-lab-is-the-dopest-lab&#x2F;&quot;&gt;https:&#x2F;&#x2F;blog.jessfraz.com&#x2F;post&#x2F;home-lab-is-the-dopest-lab&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Supervising the Master&#x27;s Thesis &quot;Smoothing techniques for 3D animated human pose estimation data&quot;</title>
        <published>2024-06-13T00:00:00+00:00</published>
        <updated>2024-06-13T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/masters-thesis-smoothing-techniques/"/>
        <id>https://zkc.se/blog/masters-thesis-smoothing-techniques/</id>
        <content type="html" xml:base="https://zkc.se/blog/masters-thesis-smoothing-techniques/">&lt;p&gt;During the spring of 2024, August Bergöö and Oliver Lundgren have been working on their
Master&#x27;s Thesis titled &quot;Smoothing techniques for 3D animated human pose estimation data&quot;
at Lunds Tekniska Högskola. I have been one of their supervisors at
&lt;a href=&quot;https:&#x2F;&#x2F;www.spiideo.com&quot;&gt;Spiideo&lt;&#x2F;a&gt; during this time.
I want to take a moment and find out what their experience was like. I also
want to know if there is anything I could do better next time.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;It was a pleasure to supervise August and Oliver. They&#x27;re two competent
people, and they have complementary strengths which made them self going
to a large extent.&lt;&#x2F;p&gt;
&lt;p&gt;August and Oliver had two additional supervisors, &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;h%C3%A5kan-ard%C3%B6-3b38483&#x2F;&quot;&gt;Håkan Ardö&lt;&#x2F;a&gt; from Spiideo
and &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;magnus-oskarsson-a7873b1&#x2F;&quot;&gt;Magnus Oskarsson&lt;&#x2F;a&gt; from Lunds Tekniska Högskola.
They did a great job supervising the thesis, and their contributions were undoubtedly much more
important than mine.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;summary-of-the-thesis-and-results&quot;&gt;Summary of the thesis and results&lt;&#x2F;h1&gt;
&lt;p&gt;In their thesis,
&lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;august-berg%C3%B6%C3%B6-031bb3263&#x2F;&quot;&gt;August&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;oliver-lundgren-6a3798197&#x2F;&quot;&gt;Oliver&lt;&#x2F;a&gt;
study smoothing techniques for 3D models that contain jitter and unnatural movements.
They look at filters (B-splines, Savitzky-Golay, Double Exponential Smoothing),
and machine learning techniques and evaluate those against each other using
quantitative and qualitative analysis.&lt;&#x2F;p&gt;
&lt;p&gt;Human representations in 3D created by motion capture or AI&#x2F;ML models can contain
jitter and unnatural poses:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;  Often these estimations of human poses contain noise, either in the form of
small inaccuracies that result in jittering character models, or errors in the estimation
which lead to limbs of the player models being represented poorly. The latter can
cause phenomena which make the experience feel unrealistic, such as feet sliding
on the floor or arms clipping through the body in unnatural ways.&lt;&#x2F;p&gt;
&lt;p&gt;  The focus of this work will be to use different techniques to mitigate the effects
of this noise.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;To evaluate the different techniques the &lt;a href=&quot;https:&#x2F;&#x2F;bedlam.is.tue.mpg.de&#x2F;&quot;&gt;BEDLAM&lt;&#x2F;a&gt;
data set (A Synthetic Dataset of Bodies Exhibiting Detailed Lifelike Animated Motion)
was used. Noise was applied to the data, and finally different smoothing techniques
were used.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Jitterbugs&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    &lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;characters.png&quot;&gt;
        &lt;img src=&quot;.&amp;#x2F;characters.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    
    
    &lt;p&gt;These ladies were made to contort unnaturally, and to jitter. Then different
smoothing techniques were applied. Visualized in the thesis using
&lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;&quot;&gt;Bevy&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;To visualize the results, and to do various data manipulation tasks, the
&lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;&quot;&gt;Bevy&lt;&#x2F;a&gt; game engine was used. For the AI&#x2F;ML tasks,
&lt;a href=&quot;https:&#x2F;&#x2F;pytorch.org&#x2F;&quot;&gt;PyTorch&lt;&#x2F;a&gt; was used.&lt;&#x2F;p&gt;
&lt;p&gt;Two measurement methods, Mean Per Joint Position Error (MPJPE)
[Wang et al., 2021] and Absolute Acceleration Error (AAE) [Shao et al., 2023] were
selected for the quantitative study. For MPJPE B-Spline filtering worked best,
and for AAE Savitzky-Golay filtering worked best.&lt;&#x2F;p&gt;
&lt;p&gt;The LSTM (ML) model wasn&#x27;t without benefits though:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;  The LSTM predictions generally did a better job filtering out pose errors created by
our noise model, but worse in filtering out the high frequency noise like jitter. The
classic filters on the other hand, were much better at reducing these errors whilst
ignoring the pose errors. It would be of interest to combine the methods used in the
thesis, to see if there is a way to create a combined solution that the effective at
solving both types of issues.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;three-questions&quot;&gt;Three questions&lt;&#x2F;h1&gt;
&lt;p&gt;I asked August and Oliver three questions: Insights you had, improvements you
would do if you had to do it again, and finally I asked them to let me know what
I could do better in the form of advice.&lt;&#x2F;p&gt;
&lt;p&gt;Oliver graciously answered these questions on behalf of both of them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;insights&quot;&gt;Insights&lt;&#x2F;h2&gt;
&lt;p&gt;Other than getting the title of Master of Science, what are you taking with you
that you learned while doing the thesis work?&lt;&#x2F;p&gt;
&lt;div class=&quot;quote&quot;&gt;
    &lt;p&gt;This is the first time I have worked on a project of this size, so it was much more important
to have a clear structure and plan, documenting what we are doing and why.
This way, both partners had a clear idea of what needed to be done and what was in progress.
Learning to use BEVY’s Entity Component System was a lot of fun. Most of my programming
projects have been object-oriented, so the shift in how to think and build our program was incredibly
interesting.&lt;&#x2F;p&gt;

    &lt;div class=&quot;quote-title&quot;&gt;Oliver&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;improvements&quot;&gt;Improvements&lt;&#x2F;h2&gt;
&lt;p&gt;If you could do it again, what would you do differently?&lt;&#x2F;p&gt;
&lt;div class=&quot;quote&quot;&gt;
    &lt;p&gt;The first few weeks were the hardest. We felt like we didn’t have a clear direction
of what we wanted to do and what the subject of our thesis was going to be.
We thought we had a plan, but once we started, we soon realized that the initial
subject wasn’t right for us. If I could do it again, I would want to be much
more certain about our research focus to avoid having to switch directions after
starting. Now, after writing the actual thesis, we have a lot more knowledge of
the real issues in this field. If we were to redo the same thesis, our noise
estimations would be more precise and accurate, resulting in a more interesting outcome.&lt;&#x2F;p&gt;

    &lt;div class=&quot;quote-title&quot;&gt;Oliver&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;advice-to-the-supervisor&quot;&gt;Advice to the supervisor&lt;&#x2F;h2&gt;
&lt;p&gt;If you could give any advice to me as your supervisor, what would it be?&lt;&#x2F;p&gt;
&lt;div class=&quot;quote&quot;&gt;
    &lt;p&gt;I felt like we were very happy with both our supervisors. Especially after a
couple of months when it felt like we got to know you better outside of just
thesis meetings. At the start, at least for me, I was worried that I might not
live up to your expectations. It was difficult to gauge your thoughts and opinions
since our meetings were, as they should be, very serious and focused. But as you
occasionally came around to our part of the office and talked about things other
than the thesis, we started to get to know you better. This eventually led to me
understanding that my worries were mostly unfounded, and I really started to enjoy
this &quot;relationship.&quot; So, if there was one thing you could have done differently, it
would be to come by a bit more frequently. At least at the beginning, so we could have
gotten to know you faster. I know all the thesis workers really enjoyed those moments.&lt;&#x2F;p&gt;

    &lt;div class=&quot;quote-title&quot;&gt;Oliver&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;h1 id=&quot;closing-thoughts&quot;&gt;Closing thoughts&lt;&#x2F;h1&gt;
&lt;p&gt;Two years ago I supervised &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;gustav-sj%C3%B6lin-757a84162&#x2F;&quot;&gt;Gustav Sjölin&lt;&#x2F;a&gt;
and &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;daniel-pendse-a0699a15b&#x2F;&quot;&gt;Daniel Pendse&lt;&#x2F;a&gt; during
Covid lockdown, which was a lot of fun for me because lockdown was kind of depressing.&lt;br &#x2F;&gt;
Some day I might write a little about that experience, and ask them some questions
too.&lt;&#x2F;p&gt;
&lt;p&gt;I had a lot of fun supervising August and Oliver. It was quite different from
the time I spent online with Gustav and Daniel, and maybe because of that I neglected
my social responsibilities with August and Oliver. I appreciate the feedback, and I
promise that I&#x27;ll do better with the next batch of students.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m happy all of their anguish was put to an end when their thesis presentation
was over and their thesis was approved, which looked like this:&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;a_o.jpg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;a_o.jpg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Good luck in the future guys!&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>The nothing&#x2F;something dichotomy: nullish types in slotted lists</title>
        <published>2024-05-09T00:00:00+00:00</published>
        <updated>2024-05-09T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/undefined-is-nothing/"/>
        <id>https://zkc.se/blog/undefined-is-nothing/</id>
        <content type="html" xml:base="https://zkc.se/blog/undefined-is-nothing/">&lt;p&gt;In programming languages with nullish types: &lt;code&gt;null&lt;&#x2F;code&gt;, &lt;code&gt;nil&lt;&#x2F;code&gt;, &lt;code&gt;undefined&lt;&#x2F;code&gt;, and so
on, programmers will usually reach for one of the nullish tokens when
representing something that can be optional or clearable. Something interesting
happens when you combine that form of optionality with another form of
optionality: fixed-length lists that represent slots to be filled in.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;div class=&quot;note&quot;&gt;
    &lt;div class=&quot;note-title&quot;&gt;At work!&lt;&#x2F;div&gt;
    &lt;p&gt;The ideas in this post started at work — a discussion, a bug, an insight
— and made it all the way here.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h1 id=&quot;using-nothing-in-place-of-something&quot;&gt;Using nothing in place of something&lt;&#x2F;h1&gt;
&lt;p&gt;Given an array of &lt;code&gt;User&lt;&#x2F;code&gt; items, it is possible to represent a variable number of
users, to do amazing things such as loop over them, render them, print them, etc.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; class=&quot;language-typescript z-code&quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-interface z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-interface z-ts&quot;&gt;interface&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-interface z-ts&quot;&gt;User&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-interface z-ts&quot;&gt;&lt;span class=&quot;z-meta z-field z-declaration z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-definition z-property z-ts&quot;&gt;&lt;span class=&quot;z-variable z-object z-property z-ts&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-annotation z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-primitive z-ts&quot;&gt;string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-interface z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;users&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-annotation z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;User&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-tuple z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt; &lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;A&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;B&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;C&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;An additional requirement may be that it should be possible to display empty,
to-be-filled-in users. A naïve way might be to represent the nothing&#x2F;something
dichotomy as a union type where one member is &lt;code&gt;User&lt;&#x2F;code&gt; and the other is nullish;
&lt;code&gt;undefined&lt;&#x2F;code&gt; for example.&lt;&#x2F;p&gt;
&lt;p&gt;This is what I describe as using &lt;em&gt;nothing&lt;&#x2F;em&gt; in place of &lt;em&gt;something&lt;&#x2F;em&gt;. Let&#x27;s
declare an instance in the list of users as the union of &lt;code&gt;User&lt;&#x2F;code&gt; and &lt;code&gt;undefined&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; class=&quot;language-typescript z-code&quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;users&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-annotation z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-type z-paren z-cover z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;User&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-type z-ts&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-builtin z-ts&quot;&gt;undefined&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-tuple z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt; &lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;*&lt;&#x2F;span&gt; ... &lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is probably fine in many cases.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;slotted-list&quot;&gt;Slotted list&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s consider a slotted list. Imagine an array that has a fixed length: the
starting lineup for a football team or the number of slots in a toaster. Let
your imagination run free. You can have empty slots, and the slots are not
filled in any particular order.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; class=&quot;language-typescript z-code&quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;slots&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-annotation z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-type z-paren z-cover z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;User&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-type z-ts&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-builtin z-ts&quot;&gt;undefined&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-tuple z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt; &lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;    &lt;span class=&quot;z-constant z-language z-undefined z-ts&quot;&gt;undefined&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;    &lt;span class=&quot;z-constant z-language z-undefined z-ts&quot;&gt;undefined&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;A&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;    &lt;span class=&quot;z-constant z-language z-undefined z-ts&quot;&gt;undefined&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;B&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-whitespace z-comment z-leading z-ts&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; And so on&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A problem with this approach is that &lt;code&gt;(User | undefined)&lt;&#x2F;code&gt; can become contagious; a
programmer might ask &quot;Why is it necessary to handle &lt;code&gt;undefined&lt;&#x2F;code&gt; everywhere?&quot;,
and &quot;Should the array be passed as-is or could it be filtered to pass only
non-nullish values?&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;You will need to pass references to &lt;code&gt;(User | undefined)[]&lt;&#x2F;code&gt; around. At some point
the distance between the code that centers around &lt;code&gt;(User | undefined)[]&lt;&#x2F;code&gt;, which
motivates its existence, and other code — rendering, parsing, API calls
— will be large enough that the original meaning gets lost. It is not
clear from its type signature why it needs to be able to be &lt;code&gt;undefined&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;When an array like this is received and passed on, am I allowed to filter it?
The originator knows that it&#x27;s a slotted list, so it can&#x27;t be filtered —
lest we lose information — but not all clients know that.&lt;&#x2F;p&gt;
&lt;p&gt;What we needed is an approach that expresses something that is stronger than
just nullishability.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;borrowing-option&quot;&gt;Borrowing Option&lt;&#x2F;h1&gt;
&lt;p&gt;I would use a type like this instead, modelled after Rust&#x27;s &lt;code&gt;Option&lt;&#x2F;code&gt; type:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; class=&quot;language-typescript z-code&quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-enum z-declaration z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-control z-export z-ts&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-enum z-ts&quot;&gt;enum&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-enum z-ts&quot;&gt;OptionKind&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-enum z-declaration z-ts&quot;&gt;    &lt;span class=&quot;z-variable z-other z-enummember z-ts&quot;&gt;Some&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-enum z-declaration z-ts&quot;&gt;    &lt;span class=&quot;z-variable z-other z-enummember z-ts&quot;&gt;None&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-enum z-declaration z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-interface z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-control z-export z-ts&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-interface z-ts&quot;&gt;interface&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-interface z-ts&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-begin z-ts&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-end z-ts&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-interface z-ts&quot;&gt;&lt;span class=&quot;z-meta z-field z-declaration z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-definition z-property z-ts&quot;&gt;&lt;span class=&quot;z-variable z-object z-property z-ts&quot;&gt;kind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-annotation z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-module z-ts&quot;&gt;OptionKind&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;Some&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-interface z-ts&quot;&gt;&lt;span class=&quot;z-meta z-field z-declaration z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-definition z-property z-ts&quot;&gt;&lt;span class=&quot;z-variable z-object z-property z-ts&quot;&gt;value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-annotation z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;T&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-interface z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-interface z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-control z-export z-ts&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-interface z-ts&quot;&gt;interface&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-interface z-ts&quot;&gt;None&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-interface z-ts&quot;&gt;&lt;span class=&quot;z-meta z-field z-declaration z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-definition z-property z-ts&quot;&gt;&lt;span class=&quot;z-variable z-object z-property z-ts&quot;&gt;kind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-annotation z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-module z-ts&quot;&gt;OptionKind&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;None&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-interface z-ts&quot;&gt;&lt;span class=&quot;z-meta z-field z-declaration z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-definition z-property z-ts&quot;&gt;&lt;span class=&quot;z-variable z-object z-property z-ts&quot;&gt;value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-annotation z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-builtin z-ts&quot;&gt;undefined&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-interface z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-type z-declaration z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-control z-export z-ts&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-type z-ts&quot;&gt;type&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-alias z-ts&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-begin z-ts&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-end z-ts&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-begin z-ts&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;T&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-end z-ts&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-type z-ts&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;None&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A few trivial helper functions like &lt;code&gt;some&amp;lt;T&amp;gt;(t: T)&lt;&#x2F;code&gt; and &lt;code&gt;none()&lt;&#x2F;code&gt; are missing,
and are left as an exercise for the reader.&lt;&#x2F;p&gt;
&lt;p&gt;The virtues of Rust&#x27;s &lt;code&gt;Option&lt;&#x2F;code&gt; type are well documented, and &lt;code&gt;Option&lt;&#x2F;code&gt; above is
very similar, but just to spell everything out&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;None&lt;&#x2F;code&gt; can be matched on&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;None&lt;&#x2F;code&gt; can be used in arrays instead of &lt;code&gt;undefined&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;It is clear that &lt;code&gt;None&lt;&#x2F;code&gt; is a placeholder value&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now we can have this, which is better than before&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; class=&quot;language-typescript z-code&quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;users&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-annotation z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-begin z-ts&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;User&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-end z-ts&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-tuple z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt; &lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;none&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;none&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;some&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;A&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;none&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;some&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;B&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-whitespace z-comment z-leading z-ts&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; And so on&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can now decide that the &lt;code&gt;undefined&lt;&#x2F;code&gt; type variant in &lt;code&gt;T | undefined&lt;&#x2F;code&gt; means
&quot;nothing&quot;, in other words that it hasn&#x27;t been assigned a value yet. The &lt;code&gt;None&lt;&#x2F;code&gt;
variant of &lt;code&gt;Option&lt;&#x2F;code&gt; similarly means &quot;something&quot;, or &quot;placeholder&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;The &quot;nothing values&quot; can keep meaning nothing. I&#x27;m not fond of JavaScript and
TypeScript having both &lt;code&gt;undefined&lt;&#x2F;code&gt; and &lt;code&gt;null&lt;&#x2F;code&gt;, but it is what it is. It might
have made sense when JavaScript was (apocryphally) created in 10 days, but I
don&#x27;t have to like it.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Swift: Using [weak self] as control flow: callbacks vs async&#x2F;await</title>
        <published>2024-04-21T00:00:00+00:00</published>
        <updated>2024-04-21T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/swift-closure-weak-self-async/"/>
        <id>https://zkc.se/blog/swift-closure-weak-self-async/</id>
        <content type="html" xml:base="https://zkc.se/blog/swift-closure-weak-self-async/">&lt;p&gt;Instances of types in Swift, particularly when doing UI programming, are
sensitive to retain cycles: A holds on to B and B holds on to A —
they&#x27;re both prevented from being freed. &lt;code&gt;[weak self]&lt;&#x2F;code&gt; to the rescue?&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h1 id=&quot;simple-callback&quot;&gt;Simple callback&lt;&#x2F;h1&gt;
&lt;p&gt;When writing UIs in Swift, mainly UIKit from the point-of-view of this post,
it usually goes something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; class=&quot;language-swift z-code&quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-swift&quot;&gt;class&lt;&#x2F;span&gt; SomeUI: UIViewController {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    &lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-swift&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-type z-function z-swift&quot;&gt;onButtonPress&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter-clause z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-begin z-swift&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-end z-swift&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-code-block z-begin z-swift&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;        networkCall1() {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            [&lt;span class=&quot;z-keyword z-other z-declaration-modifier z-swift&quot;&gt;weak&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;] &lt;span class=&quot;z-keyword z-control z-loop z-swift&quot;&gt;in&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-statement z-swift&quot;&gt;guard&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-swift&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-if z-swift&quot;&gt;else&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-control z-transfer z-swift&quot;&gt;return&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-code-block z-end z-swift&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;thing1()
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            networkCall2() {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;                [&lt;span class=&quot;z-keyword z-other z-declaration-modifier z-swift&quot;&gt;weak&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;] &lt;span class=&quot;z-keyword z-control z-loop z-swift&quot;&gt;in&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-statement z-swift&quot;&gt;guard&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-swift&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-if z-swift&quot;&gt;else&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;                    &lt;span class=&quot;z-keyword z-control z-transfer z-swift&quot;&gt;return&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;                }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;thing2()
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Each time a network call has been performed, you get a chance to check if &lt;code&gt;self&lt;&#x2F;code&gt;
has been freed, and decide what to do. This is butt ugly, boring to write, and
a pain. It does have the nice property of being a reasonably easy way to avoid
retain cycles.&lt;&#x2F;p&gt;
&lt;p&gt;It becomes a bit gnarlier when you want to write aesthetically pleasing async code,
since we chose async &#x2F; await to avoid indentation in the first place. There is no
natural way to avoid retain cycles.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; class=&quot;language-swift z-code&quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-swift&quot;&gt;class&lt;&#x2F;span&gt; SomeUI: UIViewController {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    &lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-swift&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-type z-function z-swift&quot;&gt;onButtonPress&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter-clause z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-begin z-swift&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-end z-swift&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-code-block z-begin z-swift&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;        Task {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-storage z-modifier z-attribute z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-attribute z-swift&quot;&gt;@&lt;&#x2F;span&gt;MainActor&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-loop z-swift&quot;&gt;in&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            await networkCall1()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;thing1()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            await networkCall1()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;thing2()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;        &lt;span class=&quot;z-punctuation z-definition z-code-block z-end z-swift&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;self&lt;&#x2F;code&gt; will be retained until all the network calls are done. This might not be
a big deal, so let&#x27;s look at a more complicated example.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;checking-in-a-loop&quot;&gt;Checking in a loop&lt;&#x2F;h1&gt;
&lt;pre data-lang=&quot;swift&quot; class=&quot;language-swift z-code&quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-swift&quot;&gt;class&lt;&#x2F;span&gt; SomeUI: UIViewController {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    &lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-swift&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-type z-function z-swift&quot;&gt;loop&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter-clause z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-begin z-swift&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-end z-swift&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-code-block z-begin z-swift&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;        networkCall() {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            [&lt;span class=&quot;z-keyword z-other z-declaration-modifier z-swift&quot;&gt;weak&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;] &lt;span class=&quot;z-keyword z-control z-loop z-swift&quot;&gt;in&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-statement z-swift&quot;&gt;guard&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-swift&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-if z-swift&quot;&gt;else&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-control z-transfer z-swift&quot;&gt;return&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-code-block z-end z-swift&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;thing1()
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            &lt;span class=&quot;z-comment z-line z-double-slash z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-double-slash z-swift&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Create a timer that fires after 5s&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            delay(by: &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-swift&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-swift&quot;&gt;0&lt;&#x2F;span&gt;) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;                [&lt;span class=&quot;z-keyword z-other z-declaration-modifier z-swift&quot;&gt;weak&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;] &lt;span class=&quot;z-keyword z-control z-loop z-swift&quot;&gt;in&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-statement z-swift&quot;&gt;guard&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-swift&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-if z-swift&quot;&gt;else&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;                    &lt;span class=&quot;z-keyword z-control z-transfer z-swift&quot;&gt;return&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;                }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;loop()
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The loop above will be terminated as soon as the UI is freed, which is what we
wanted.&lt;&#x2F;p&gt;
&lt;p&gt;What seems to be a nice way to write that using async?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; class=&quot;language-swift z-code&quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-swift&quot;&gt;class&lt;&#x2F;span&gt; SomeUI: UIViewController {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    &lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-swift&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-type z-function z-swift&quot;&gt;loop&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter-clause z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-begin z-swift&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-end z-swift&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-code-block z-begin z-swift&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;        Task {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-storage z-modifier z-attribute z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-attribute z-swift&quot;&gt;@&lt;&#x2F;span&gt;MainActor&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-loop z-swift&quot;&gt;in&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-loop z-swift&quot;&gt;repeat&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;                await &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;networkCall()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;thing1()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-statement z-swift&quot;&gt;try&lt;&#x2F;span&gt;? await Task&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;sleep(nanoseconds: &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-swift&quot;&gt;5_000_000_000&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-code-block z-end z-swift&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-loop z-swift&quot;&gt;while&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-swift&quot;&gt;!&lt;&#x2F;span&gt;Task&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;isCancelled
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Really nice looking, but now we need to handle the fact that we can&#x27;t stop this loop
in any reasonable way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;attempt-1-task-cancellation&quot;&gt;Attempt 1: Task cancellation&lt;&#x2F;h2&gt;
&lt;p&gt;Our first attempt might be storing the &lt;code&gt;Task&lt;&#x2F;code&gt; and cancelling it when needed.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; class=&quot;language-swift z-code&quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-swift&quot;&gt;class&lt;&#x2F;span&gt; SomeUI: UIViewController {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    &lt;span class=&quot;z-storage z-type z-swift&quot;&gt;var&lt;&#x2F;span&gt; loopTask: Task&lt;span class=&quot;z-keyword z-operator z-comparative z-swift&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;(), Error&lt;span class=&quot;z-keyword z-operator z-comparative z-swift&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;?
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    &lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-swift&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-type z-function z-swift&quot;&gt;loop&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter-clause z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-begin z-swift&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-end z-swift&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-code-block z-begin z-swift&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;        &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;loopTask &lt;span class=&quot;z-keyword z-operator z-assignment z-swift&quot;&gt;=&lt;&#x2F;span&gt; Task {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-storage z-modifier z-attribute z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-attribute z-swift&quot;&gt;@&lt;&#x2F;span&gt;MainActor&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-loop z-swift&quot;&gt;in&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-loop z-swift&quot;&gt;repeat&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;                await networkCall()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;thing1()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-statement z-swift&quot;&gt;try&lt;&#x2F;span&gt;? await Task&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;sleep(nanoseconds: &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-swift&quot;&gt;5_000_000_000&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-code-block z-end z-swift&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-loop z-swift&quot;&gt;while&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-swift&quot;&gt;!&lt;&#x2F;span&gt;Task&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;isCancelled
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    &lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-swift&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-type z-function z-swift&quot;&gt;cancel&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter-clause z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-begin z-swift&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-end z-swift&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-code-block z-begin z-swift&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;        &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;loopTask?&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;cancel()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;    &lt;span class=&quot;z-punctuation z-definition z-code-block z-end z-swift&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will work if we make sure to call &lt;code&gt;cancel&lt;&#x2F;code&gt; on &lt;em&gt;every&lt;&#x2F;em&gt; path that can leave
our &lt;code&gt;UIViewController&lt;&#x2F;code&gt;. This might be feasible, but it&#x27;s not very maintainable. Seven years from
now the next programmer updating the &lt;code&gt;UIViewController&lt;&#x2F;code&gt; will need to do the right thing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;attempt-2-avoid-the-retain-cycle&quot;&gt;Attempt 2: Avoid the retain cycle&lt;&#x2F;h2&gt;
&lt;p&gt;Our second attempt is to avoid a retain cycle, which might look like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; class=&quot;language-swift z-code&quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-swift&quot;&gt;class&lt;&#x2F;span&gt; SomeUI: UIViewController {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    &lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-swift&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-type z-function z-swift&quot;&gt;loop&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter-clause z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-begin z-swift&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-end z-swift&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-code-block z-begin z-swift&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;        Task {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-storage z-modifier z-attribute z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-attribute z-swift&quot;&gt;@&lt;&#x2F;span&gt;MainActor&lt;&#x2F;span&gt; [&lt;span class=&quot;z-keyword z-other z-declaration-modifier z-swift&quot;&gt;weak&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;] &lt;span class=&quot;z-keyword z-control z-loop z-swift&quot;&gt;in&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            await networkCall1()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;?&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;thing1()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            await networkCall2()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;?&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;thing2()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-statement z-swift&quot;&gt;try&lt;&#x2F;span&gt;? await Task&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;sleep(nanoseconds: &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-swift&quot;&gt;5_000_000_000&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;?&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;loop()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;        &lt;span class=&quot;z-punctuation z-definition z-code-block z-end z-swift&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is an uncomplicated example, but notice how we&#x27;ll keep doing network calls
even if &lt;code&gt;self&lt;&#x2F;code&gt; has been freed. The only thing we&#x27;ll skip are the function calls
&lt;code&gt;self?.thing1()&lt;&#x2F;code&gt; and &lt;code&gt;self?.thing2()&lt;&#x2F;code&gt;. This may be undesirable!&lt;&#x2F;p&gt;
&lt;p&gt;Another issue with this approach is that since we spawn new &lt;code&gt;Task&lt;&#x2F;code&gt;s all the time,
it&#x27;s not immediately possible (without some work) to cancel a long chain or tree
of these.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;attempt-3-checking-self-after-every-await&quot;&gt;Attempt 3: checking self after every await&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s possible to check the state of &lt;code&gt;self&lt;&#x2F;code&gt; with continuous if-statements, but then
we&#x27;re writing icky code again:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; class=&quot;language-swift z-code&quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-swift&quot;&gt;class&lt;&#x2F;span&gt; SomeUI: UIViewController {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    &lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-swift&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-type z-function z-swift&quot;&gt;loop&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter-clause z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-begin z-swift&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-end z-swift&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-code-block z-begin z-swift&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;        Task {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-storage z-modifier z-attribute z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-attribute z-swift&quot;&gt;@&lt;&#x2F;span&gt;MainActor&lt;&#x2F;span&gt; [&lt;span class=&quot;z-keyword z-other z-declaration-modifier z-swift&quot;&gt;weak&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;] &lt;span class=&quot;z-keyword z-control z-loop z-swift&quot;&gt;in&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            await networkCall1()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-if z-swift&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-swift&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;thing1()
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-code-block z-end z-swift&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-if z-swift&quot;&gt;else&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-control z-transfer z-swift&quot;&gt;return&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            await networkCall2()
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-if z-swift&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-swift&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;thing2()
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            } &lt;span class=&quot;z-keyword z-control z-if z-swift&quot;&gt;else&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;                &lt;span class=&quot;z-keyword z-control z-transfer z-swift&quot;&gt;return&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-statement z-swift&quot;&gt;try&lt;&#x2F;span&gt;? await Task&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;sleep(nanoseconds: &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-swift&quot;&gt;5_000_000_000&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;            &lt;span class=&quot;z-keyword z-other z-statement z-swift&quot;&gt;self&lt;&#x2F;span&gt;?&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;loop()
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;final-words&quot;&gt;Final words&lt;&#x2F;h1&gt;
&lt;p&gt;The lifecycle of UI in Swift in general, and UIKit in particular is substandard.
There&#x27;s a lot to be said about React but at least it&#x27;s possible to be able to
do cleanup using a &lt;code&gt;useEffect&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is harder than I wish it was in Swift. In the end, we&#x27;re responsible for
writing code that works well, but it should be easier to get the system
to help out than it is in Swift &#x2F; iOS.&lt;&#x2F;p&gt;
&lt;p&gt;There are probably more ways to solve the retain cycle problem than the ones
listed above, but we have at least three tools with different tradeoffs.&lt;&#x2F;p&gt;
&lt;p&gt;Is there an even better way? Let me know.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Mapping iOS devices to their iOS version</title>
        <published>2024-04-14T00:00:00+00:00</published>
        <updated>2024-04-14T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/mapping-ios-devices-to-their-ios-version/"/>
        <id>https://zkc.se/blog/mapping-ios-devices-to-their-ios-version/</id>
        <content type="html" xml:base="https://zkc.se/blog/mapping-ios-devices-to-their-ios-version/">&lt;p&gt;I have an iOS app where I need to know what the latest available iOS version for
a given iOS&#x2F;iPadOS device is, but surprisingly I couldn&#x27;t find any off-the-shelf
solutions. I&#x27;m going to publish one myself. I will probably regret this.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h1 id=&quot;encouraging-users-to-update-their-phone-or-tablet&quot;&gt;Encouraging users to update their phone (or tablet)&lt;&#x2F;h1&gt;
&lt;p&gt;At &lt;a href=&quot;https:&#x2F;&#x2F;www.spiideo.com&#x2F;&quot;&gt;work&lt;&#x2F;a&gt;, we are working on an iOS&#x2F;iPadOS —
or simply iOS, even if that is somewhat incorrect —
app that has a lot of functionality, and some of our functionality is simply better
(the underlying platform is more bug free) or we are accessing certain platform
APIs that are only available on later versions. So we want to push users to
upgrade to the latest iOS version.&lt;&#x2F;p&gt;
&lt;p&gt;For that we have a modal dialog that pops up whenever the user opens the app,
but at most once every twenty-four hours.&lt;&#x2F;p&gt;
&lt;p&gt;Problem is, it&#x27;s popping up even though some of the users are on the latest
available version of iOS. We have a minimum iOS version of 15, but there are
relatively recent devices that are stuck on iOS 16. &lt;code&gt;iPhone10,6&lt;&#x2F;code&gt; (iPhone X) and
&lt;code&gt;iPad6,8&lt;&#x2F;code&gt; (iPad Pro 12.9-in. – 1st generation) are two models that are unreasonably
stuck on iOS&#x2F;iPadOS 16.&lt;&#x2F;p&gt;
&lt;p&gt;So we are asking users to upgrade to a later version of iOS than what&#x27;s possible,
and I&#x27;m sure that&#x27;s at least a little annoying for them.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;introducing-ios-hw-to-os&quot;&gt;Introducing &lt;code&gt;ios-hw-to-os&lt;&#x2F;code&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Now there exists both a (currently incomplete) JSON file in my
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bes&#x2F;ios-hw-to-os&quot;&gt;ios-hw-to-os&lt;&#x2F;a&gt; repository,
and a simple Swift package called &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bes&#x2F;ios-hw-to-os-spm&quot;&gt;ios-hw-to-os-spm&lt;&#x2F;a&gt;
that makes it easy to use from your Swift or Swift-XCode application.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s an example of how to use the API&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; class=&quot;language-swift z-code&quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-import z-swift&quot;&gt;&lt;span class=&quot;z-keyword z-other z-import z-swift&quot;&gt;import&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-module z-import z-swift&quot;&gt;IosHwToOs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-swift&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-type z-function z-swift&quot;&gt;useAllMappings&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter-clause z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-begin z-swift&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-end z-swift&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-code-block z-begin z-swift&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;    &lt;span class=&quot;z-keyword z-statement z-swift&quot;&gt;guard&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-swift&quot;&gt;let&lt;&#x2F;span&gt; mappings &lt;span class=&quot;z-keyword z-operator z-assignment z-swift&quot;&gt;=&lt;&#x2F;span&gt; IosHwToOsMappings&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;all() &lt;span class=&quot;z-keyword z-control z-if z-swift&quot;&gt;else&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-transfer z-swift&quot;&gt;return&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;    &lt;span class=&quot;z-punctuation z-definition z-code-block z-end z-swift&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    &lt;span class=&quot;z-keyword z-statement z-swift&quot;&gt;guard&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-swift&quot;&gt;let&lt;&#x2F;span&gt; device &lt;span class=&quot;z-keyword z-operator z-assignment z-swift&quot;&gt;=&lt;&#x2F;span&gt; mappings&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;devices&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;first(&lt;span class=&quot;z-keyword z-control z-switch z-swift&quot;&gt;where&lt;&#x2F;span&gt;: { $&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-swift&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;hardware &lt;span class=&quot;z-keyword z-operator z-comparative z-swift&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-literal z-string z-swift&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;P&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;}) &lt;span class=&quot;z-keyword z-control z-if z-swift&quot;&gt;else&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-transfer z-swift&quot;&gt;return&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-double-slash z-swift&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Prints IosHwToOsDevice(hardware: &amp;quot;iPhone10,1&amp;quot;, version: &amp;quot;16.7.7&amp;quot;)&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    print(&lt;span class=&quot;z-meta z-literal z-string z-swift&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-punctuation z-expression z-begin z-swift&quot;&gt;\(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-expression z-swift&quot;&gt;device&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-punctuation z-expression z-end z-swift&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-swift&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-type z-function z-swift&quot;&gt;useOneDevice&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter-clause z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-begin z-swift&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-function-arguments z-end z-swift&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-code-block z-begin z-swift&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;    &lt;span class=&quot;z-keyword z-statement z-swift&quot;&gt;guard&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-swift&quot;&gt;let&lt;&#x2F;span&gt; device &lt;span class=&quot;z-keyword z-operator z-assignment z-swift&quot;&gt;=&lt;&#x2F;span&gt; IosHwToOsDevice&lt;span class=&quot;z-keyword z-operator z-custom z-postfix z-unary z-swift&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-swift&quot;&gt;get&lt;&#x2F;span&gt;(hardware: &lt;span class=&quot;z-meta z-literal z-string z-swift&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;P&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-keyword z-control z-if z-swift&quot;&gt;else&lt;&#x2F;span&gt; {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-transfer z-swift&quot;&gt;return&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;&lt;span class=&quot;z-meta z-function-declaration z-swift&quot;&gt;    &lt;span class=&quot;z-punctuation z-definition z-code-block z-end z-swift&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-swift&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-double-slash z-swift&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Prints IosHwToOsDevice(hardware: &amp;quot;iPhone10,1&amp;quot;, version: &amp;quot;16.7.7&amp;quot;)&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;    print(&lt;span class=&quot;z-meta z-literal z-string z-swift&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-punctuation z-expression z-begin z-swift&quot;&gt;\(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-expression z-swift&quot;&gt;device&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-punctuation z-expression z-end z-swift&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-swift&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-swift&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Parsing the iOS version into a usable data structure &#x2F; type is left as an exercise
to the reader — we already have that at work — but it shouldn&#x27;t be too
hard and isn&#x27;t strictly necessary from the point-of-view of the library.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;some-wikipedia-some-yaml-some-json-some-rust-and-some-swift&quot;&gt;Some Wikipedia, some YAML, some JSON, some Rust, and some Swift&lt;&#x2F;h1&gt;
&lt;p&gt;I used Wikipedia as my source of information, specifically these pages —
which are excellent:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_iPhone_models&quot;&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_iPhone_models&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_iPad_models&quot;&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_iPad_models&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I manually copied the information into a YAML file, because even though I don&#x27;t
particularly like whitespace-as-strucutre, it has some features that JSON sorely
lacks – readabilty &amp;amp; comments. The file looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;devices&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; Supported iPad versions
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;iPad&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-decimal z-yaml&quot;&gt;17&lt;span class=&quot;z-punctuation z-separator z-decimal z-yaml&quot;&gt;.&lt;&#x2F;span&gt;4.1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Supported&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;hardware&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;iPad13,18&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;iPad13,19&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; ...more
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; Unsupported iPad versions
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;iPad&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-decimal z-yaml&quot;&gt;16&lt;span class=&quot;z-punctuation z-separator z-decimal z-yaml&quot;&gt;.&lt;&#x2F;span&gt;7.7&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Unsupported&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;hardware&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;iPad6,11&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;iPad6,12&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; ...more
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I then use a very small Rust program to convert the YAML into JSON. The JSON file
has a very different structure from the YAML file. The YAML file is structured
to be easy to update, and is sectioned by type of device, while the JSON file
is basically just an array of all the devices without any sectioning.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; class=&quot;language-json z-code&quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;devices&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-sequence z-begin z-json&quot;&gt;[&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;    &lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;      &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;hardware&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;iPad13,18&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;      &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;version&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;17.4.1&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-mapping z-end z-json&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-sequence z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;    &lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;      &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;hardware&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;iPad13,19&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;      &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;version&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;17.4.1&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-mapping z-end z-json&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-sequence z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-invalid z-illegal z-expected-sequence-separator z-json&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-invalid z-illegal z-expected-sequence-separator z-json&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-invalid z-illegal z-expected-sequence-separator z-json&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-invalid z-illegal z-expected-sequence-separator z-json&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-invalid z-illegal z-expected-sequence-separator z-json&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-invalid z-illegal z-expected-sequence-separator z-json&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-invalid z-illegal z-expected-sequence-separator z-json&quot;&gt;e&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After creating the JSON file, that one is copied over to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bes&#x2F;ios-hw-to-os-spm&quot;&gt;ios-hw-to-os-spm&lt;&#x2F;a&gt;
and packaged in a Swift package.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;contributions-welcome&quot;&gt;Contributions welcome&lt;&#x2F;h1&gt;
&lt;p&gt;Want to expand &lt;code&gt;ios-hw-to-os&lt;&#x2F;code&gt; to cover Apple Watch? Maybe you need devices older
than those that can run iOS 15? Do you want to add more fields or improve the Swift
API? PRs are welcome, and I think I left reasonably
clear instructions on how to manage the YAML &#x2F; JSON structure.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Font magic: Reducing the size of the web fonts I use</title>
        <published>2024-01-14T00:00:00+00:00</published>
        <updated>2024-01-14T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/font-magic/"/>
        <id>https://zkc.se/blog/font-magic/</id>
        <content type="html" xml:base="https://zkc.se/blog/font-magic/">&lt;p&gt;I recently learned some new things about fonts! The good-looking variable EB Garamond font is almost one megabyte, but
it contains &lt;em&gt;a lot&lt;&#x2F;em&gt; of glyphs that I don&#x27;t need for this site. EB Garamond is going on a diet.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;This was partially inspired by Cliffle&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;cliffle.com&#x2F;blog&#x2F;making-website-faster&quot;&gt;Making my website faster&lt;&#x2F;a&gt; post,
specifically the &lt;em&gt;Reducing the cost of webfonts&lt;&#x2F;em&gt; section. I say partially because when I first started using EB Garamond
and Josefin Sans, I thought they were both way too big. I searched for some options on how to shrink them, but at the
time I wasn&#x27;t feeling inspired to use Python (Python is a bit... much, at times).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;setting-up-a-web-font&quot;&gt;Setting up a web font&lt;&#x2F;h1&gt;
&lt;p&gt;It&#x27;s quite easy to set up web fonts, just download the ones you want, and then add them to your CSS file:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;css&quot; class=&quot;language-css z-code&quot;&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-keyword z-control z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-keyword z-css&quot;&gt;@&lt;&#x2F;span&gt;font-face&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-family&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;EBGaramond&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-style&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-support z-constant z-property-value z-css&quot;&gt;normal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-weight&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-css&quot;&gt;400&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-css&quot;&gt;&lt;span class=&quot;z-support z-function z-url z-css&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;fonts&#x2F;EBGaramond.ttf&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-css&quot;&gt;&lt;span class=&quot;z-support z-function z-font-face z-css&quot;&gt;format&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;truetype&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;unicode-range&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-support z-unicode-range z-css&quot;&gt;&lt;span class=&quot;z-support z-constant z-unicode-range z-prefix z-css&quot;&gt;U+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-codepoint-range z-css&quot;&gt;0000&lt;span class=&quot;z-punctuation z-section z-range z-css&quot;&gt;-&lt;&#x2F;span&gt;017F&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-keyword z-control z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-keyword z-css&quot;&gt;@&lt;&#x2F;span&gt;font-face&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-family&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;JosefinSans&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-style&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-support z-constant z-property-value z-css&quot;&gt;normal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-weight&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-css&quot;&gt;600&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-css&quot;&gt;&lt;span class=&quot;z-support z-function z-url z-css&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;fonts&#x2F;JosefinSans.ttf&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-css&quot;&gt;&lt;span class=&quot;z-support z-function z-font-face z-css&quot;&gt;format&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;truetype&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;unicode-range&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-support z-unicode-range z-css&quot;&gt;&lt;span class=&quot;z-support z-constant z-unicode-range z-prefix z-css&quot;&gt;U+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-codepoint-range z-css&quot;&gt;0000&lt;span class=&quot;z-punctuation z-section z-range z-css&quot;&gt;-&lt;&#x2F;span&gt;017F&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-keyword z-control z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-keyword z-css&quot;&gt;@&lt;&#x2F;span&gt;font-face&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-family&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;Source Code Pro&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-style&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-support z-constant z-property-value z-css&quot;&gt;normal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-weight&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-support z-constant z-property-value z-css&quot;&gt;auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-css&quot;&gt;&lt;span class=&quot;z-support z-function z-url z-css&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;fonts&#x2F;SourceCodePro.ttf&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-css&quot;&gt;&lt;span class=&quot;z-support z-function z-font-face z-css&quot;&gt;format&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;truetype&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;unicode-range&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-support z-unicode-range z-css&quot;&gt;&lt;span class=&quot;z-support z-constant z-unicode-range z-prefix z-css&quot;&gt;U+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-codepoint-range z-css&quot;&gt;0000&lt;span class=&quot;z-punctuation z-section z-range z-css&quot;&gt;-&lt;&#x2F;span&gt;017F&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;, &lt;span class=&quot;z-support z-unicode-range z-css&quot;&gt;&lt;span class=&quot;z-support z-constant z-unicode-range z-prefix z-css&quot;&gt;U+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-codepoint-range z-css&quot;&gt;2500&lt;span class=&quot;z-punctuation z-section z-range z-css&quot;&gt;-&lt;&#x2F;span&gt;25FF&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-selector z-css&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-css&quot;&gt;html&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-family&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;EBGaramond&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-sequence z-css&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-constant z-font-name z-css&quot;&gt;serif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-selector z-css&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-class z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-css&quot;&gt;.&lt;&#x2F;span&gt;top-title&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-family&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;JosefinSans&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-sequence z-css&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-constant z-font-name z-css&quot;&gt;sans-serif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-selector z-css&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-css&quot;&gt;code&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-sequence z-css&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-selector z-css&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-css&quot;&gt;pre&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-sequence z-css&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-selector z-css&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-css&quot;&gt;kbd&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-family&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;Source Code Pro&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-sequence z-css&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-constant z-font-name z-css&quot;&gt;monospace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;line-height&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-css&quot;&gt;100&lt;span class=&quot;z-keyword z-other z-unit z-css&quot;&gt;%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;word-wrap&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-support z-constant z-property-value z-css&quot;&gt;break-word&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;emoji-troubles&quot;&gt;Emoji troubles&lt;&#x2F;h1&gt;
&lt;p&gt;The problem I found was that after applying EB Garamond, the emojis I was using around the site like these lovely flags
🇸🇪🇬🇧🇺🇸🇭🇷🇧🇦🇷🇸🇩🇪 just stopped working. Instead I saw emoji placeholders like &quot;S E G B U S H R B H R S D E&quot;, if that makes
sense. The browser was trying to find an emoji inside of EB Garamond, but EB Garamond doesn&#x27;t seem to have any emojis.&lt;&#x2F;p&gt;
&lt;p&gt;To solve this, I had to select the unicode range I wanted to use from EB Garamond, and then fall back to &lt;code&gt;serif&lt;&#x2F;code&gt; or &lt;code&gt;sans-serif&lt;&#x2F;code&gt;
for any other glyph, which is easy enough, just add the &lt;code&gt;unicode-range&lt;&#x2F;code&gt; propery of &lt;code&gt;@font-face&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;css&quot; class=&quot;language-css z-code&quot;&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-keyword z-control z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-keyword z-css&quot;&gt;@&lt;&#x2F;span&gt;font-face&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-family&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;EBGaramond&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-style&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-support z-constant z-property-value z-css&quot;&gt;normal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-weight&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-css&quot;&gt;400&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;font-display&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;swap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-css&quot;&gt;&lt;span class=&quot;z-support z-function z-url z-css&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;fonts&#x2F;EBGaramond.ttf&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-css&quot;&gt;&lt;span class=&quot;z-support z-function z-font-face z-css&quot;&gt;format&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;truetype&lt;span class=&quot;z-punctuation z-definition z-string z-end z-css&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;mark&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;unicode-range&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt;&lt;span class=&quot;z-support z-unicode-range z-css&quot;&gt;&lt;span class=&quot;z-support z-constant z-unicode-range z-prefix z-css&quot;&gt;U+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-codepoint-range z-css&quot;&gt;0000&lt;span class=&quot;z-punctuation z-section z-range z-css&quot;&gt;-&lt;&#x2F;span&gt;017F&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;mark&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-font-face z-css&quot;&gt;&lt;span class=&quot;z-meta z-property-list z-css&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-css&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I chose the range &lt;code&gt;U+0000-017F&lt;&#x2F;code&gt; because that&#x27;s what I need. You can use the &lt;a href=&quot;https:&#x2F;&#x2F;symbl.cc&#x2F;en&#x2F;unicode&#x2F;table&#x2F;&quot;&gt;symbl.cc Unicode Character Table&lt;&#x2F;a&gt;
to find out which glyphs you might need. I chose &lt;em&gt;Basic Latin&lt;&#x2F;em&gt;, &lt;em&gt;Latin-1 Supplement&lt;&#x2F;em&gt;, and &lt;em&gt;Latin Extended-A&lt;&#x2F;em&gt; because together
they cover the glyphs I use — the ones I need to spell my name — &lt;em&gt;Erik Živković&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;setting-up-a-venv-for-fonttools&quot;&gt;Setting up a venv for fonttools&lt;&#x2F;h1&gt;
&lt;p&gt;For a Python non-believer like me this might actually be the hardest part.&lt;&#x2F;p&gt;
&lt;p&gt;My setup script &lt;code&gt;py-setup.sh&lt;&#x2F;code&gt; looks like this.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;!&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;python3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;m&lt;&#x2F;span&gt; venv .venv&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-source z-shell&quot;&gt;source&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; .venv&#x2F;bin&#x2F;activate&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;pip3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install fonttools&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;reducing-the-number-of-glyphs&quot;&gt;Reducing the number of glyphs&lt;&#x2F;h1&gt;
&lt;p&gt;To reduce the number of glyphs I ran this script, adapted from Cliffle&#x27;s blog, that I call &lt;code&gt;py-fixfonts.sh&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;!&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-source z-shell&quot;&gt;source&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; .venv&#x2F;bin&#x2F;activate&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;pyftsubset&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;    font-orig&#x2F;EB_Garamond&#x2F;EBGaramond-VariableFont_wght.ttf &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;    --&lt;&#x2F;span&gt;unicodes&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-option z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;U+0000-017F&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;    --&lt;&#x2F;span&gt;ignore-missing-glyphs&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;    --&lt;&#x2F;span&gt;layout-features-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-option z-shell&quot;&gt;=&lt;&#x2F;span&gt;dnom,frac,numr &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;    --&lt;&#x2F;span&gt;output-file&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-option z-shell&quot;&gt;=&lt;&#x2F;span&gt;static&#x2F;fonts&#x2F;EBGaramond.ttf&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;pyftsubset&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;    font-orig&#x2F;Josefin_Sans&#x2F;JosefinSans-VariableFont_wght.ttf &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;    --&lt;&#x2F;span&gt;text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-option z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Domain Specific Language Front page · Blog · Photos&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;    --&lt;&#x2F;span&gt;ignore-missing-glyphs&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;    --&lt;&#x2F;span&gt;layout-features-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-option z-shell&quot;&gt;=&lt;&#x2F;span&gt;dnom,frac,numr &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;    --&lt;&#x2F;span&gt;output-file&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-option z-shell&quot;&gt;=&lt;&#x2F;span&gt;static&#x2F;fonts&#x2F;JosefinSans.ttf&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;pyftsubset&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;    font-orig&#x2F;SourceCodePro&#x2F;TTF&#x2F;SourceCodePro-Regular.ttf &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;    --&lt;&#x2F;span&gt;unicodes&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-option z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;U+0000-017F,U+2500-25FF&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;    --&lt;&#x2F;span&gt;ignore-missing-glyphs&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;    --&lt;&#x2F;span&gt;layout-features-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-option z-shell&quot;&gt;=&lt;&#x2F;span&gt;dnom,frac,numr &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;    --&lt;&#x2F;span&gt;output-file&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-option z-shell&quot;&gt;=&lt;&#x2F;span&gt;static&#x2F;fonts&#x2F;SourceCodePro.ttf&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The Josefin Sans fonts is only used for the page title and the section links, so I tell &lt;code&gt;pyftsubset&lt;&#x2F;code&gt; to only keep the
glyphs needed for exactly those texts.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;results&quot;&gt;Results&lt;&#x2F;h1&gt;
&lt;p&gt;The table below says it all, size for the EB Garamond font was reduced to about 10% of its original size, and
Josefin Sans too was reduced to a similar percentage of the original.&lt;&#x2F;p&gt;
&lt;div class=&quot;hscroll&quot;&gt;
    &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Font&lt;&#x2F;th&gt;&lt;th&gt;Size before&lt;&#x2F;th&gt;&lt;th&gt;Size After&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;EBGaramond-VariableFont_wght.ttf&lt;&#x2F;td&gt;&lt;td&gt;927 kB&lt;&#x2F;td&gt;&lt;td&gt;95 kB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;JosefinSans-VariableFont_wght.ttf&lt;&#x2F;td&gt;&lt;td&gt;118 kB&lt;&#x2F;td&gt;&lt;td&gt;10 kB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;SourceCodePro-Regular.ttf&lt;&#x2F;td&gt;&lt;td&gt;205 kB&lt;&#x2F;td&gt;&lt;td&gt;57 kB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;

&lt;&#x2F;div&gt;
&lt;h1 id=&quot;final-notes&quot;&gt;Final notes&lt;&#x2F;h1&gt;
&lt;p&gt;I assume the &lt;code&gt;unicode-range&lt;&#x2F;code&gt; property could be removed at this point, but I&#x27;ll keep it around anyway, since I think
it&#x27;s cute.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Abandoning Microsoft Windows</title>
        <published>2024-01-05T00:00:00+00:00</published>
        <updated>2024-01-05T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/abandoning-microsoft-windows/"/>
        <id>https://zkc.se/blog/abandoning-microsoft-windows/</id>
        <content type="html" xml:base="https://zkc.se/blog/abandoning-microsoft-windows/">&lt;p&gt;Ever since I got my first computer, an AST Advantage! Adventure 6066d, I have been running some version of Microsoft
Windows. But now I don&#x27;t think I&#x27;ll use Microsoft Windows ever again. I think the people at Microsoft understand this as well,
and that&#x27;s why they&#x27;re branching out so hard with other software endeavours — GitHub, Copilot, Visual Studio Code,
and so on.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;a class=&quot;image&quot; href=&quot;&amp;#x2F;blog&amp;#x2F;abandoning-microsoft-windows&amp;#x2F;ast-advantage-6066d-1.png&quot;&gt;
    &lt;img src=&quot;&amp;#x2F;blog&amp;#x2F;abandoning-microsoft-windows&amp;#x2F;ast-advantage-6066d-1.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Look at this amazing computer. It couldn&#x27;t even play MP3&#x27;s because MP3&#x27;s required CPU extensions only available on
Pentiums.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;ast-advantage-6066d-2.jpg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;ast-advantage-6066d-2.jpg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;It is known that breaking a camel&#x27;s back takes a lot of weight. In this essay I will list the final straws, as well
as what I&#x27;m replacing Windows with.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;second-to-last-straw-keyboard-shortcuts&quot;&gt;Second-to-last straw: Keyboard shortcuts&lt;&#x2F;h1&gt;
&lt;p&gt;Some people (gamers) usually call keyboard shortcuts &quot;hotkeys&quot;. But I&#x27;ve learned to adapt to normie culture, and now
I sometimes call hotkeys by their real name. Keyboard shortcuts are very important to Microsoft, because they empower
users to reach essential functionality fast. I remember my favorite shortcut, WinKey + Pause&#x2F;Break, which brought up
&lt;em&gt;System Properties&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;win95-system-properties.gif&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;win95-system-properties.gif&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;An amazing, almost magical place, where you could reinstall your friends&#x27; network drivers. Reinstalling drivers was
super common at this time. I had a friend that needed to reinstall his network drivers every time we had a LAN party
because his brother uninstalled them as soon as he went back home after a long weekend.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t remember any keyboard shortcuts from Windows 3.11, but Windows 95, 98, ME, and Windows 2000 all had a bunch of
useful ones. They were generally unobtrusive, meaning they didn&#x27;t interfere when playing computer games!&lt;&#x2F;p&gt;
&lt;p&gt;In Windows 11, it&#x27;s &lt;em&gt;really&lt;&#x2F;em&gt; hard, to the point of being almost impossible without some intrusive changes,
to turn off a bunch of new standard keyboard shortcuts, which bring up stupid guides supposed to &quot;help&quot; the user.
I never could figure out how to turn them off! I could be playing StarCraft 2, and in the middle of an important
skirmish some dumb Microsoft Windows Wizard would start because I happened to press WinKey + F or something like that.
Windows even has a &quot;game mode&quot;, which I never understood, because it doesn&#x27;t turn these hotkeys off! On top of that,
the nvidia drivers add their own unnecessary hotkeys, which have overlays that vomit themselves onto the screen
when you&#x27;re unlucky enough to randomly hit some combination of keys.&lt;&#x2F;p&gt;
&lt;p&gt;I suspect some of the keyboard shortcuts exist to guide people towards subscriptions that Microsoft can make some money
off of.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;final-straw-copilot-keyboard-key&quot;&gt;Final straw: Copilot keyboard key&lt;&#x2F;h1&gt;
&lt;p&gt;On January 4, 2024, Microsoft announced that all new Microsoft Windows computers are required to have a
&lt;a href=&quot;https:&#x2F;&#x2F;www.theverge.com&#x2F;2024&#x2F;1&#x2F;4&#x2F;24023809&#x2F;microsoft-copilot-key-keyboard-windows-laptops-pcs&quot;&gt;Copilot key&lt;&#x2F;a&gt;.
This new key will replace the current &quot;application key&quot; on the left hand side of the keyboard.&lt;&#x2F;p&gt;
&lt;p&gt;This is a mostly harmless change, and it definitely won&#x27;t affect me — because I&#x27;m switching to Linux.
I won&#x27;t be using Microsoft Windows anymore.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;fedora-39&quot;&gt;Fedora 39&lt;&#x2F;h1&gt;
&lt;p&gt;My first attempt at a new Operating System on the desktop is Fedora 39, which is a Linux distribution.
I was worried that it would be hard getting StarCraft 2 to run smoothly on Fedora, but it really wasn&#x27;t.
Installing the nvidia graphics drivers was a bit of a hassle! My computer has &quot;secure boot&quot; enabled, so I needed
to add a signing key that the computer accepts, and then use that to sign the drivers, but following a
&lt;a href=&quot;https:&#x2F;&#x2F;blog.monosoul.dev&#x2F;2022&#x2F;05&#x2F;17&#x2F;automatically-sign-nvidia-kernel-module-in-fedora-36&#x2F;&quot;&gt;simple guide&lt;&#x2F;a&gt;
worked flawlessly. I lost a few hours before I understood what was going on, but now that it is solved everything
is sunshine and roses.&lt;&#x2F;p&gt;
&lt;p&gt;I get about 300 fps in StarCraft 2, which is equal to, or better than,
what I got in Windows! Installing the &lt;a href=&quot;https:&#x2F;&#x2F;lutris.net&#x2F;games&#x2F;battlenet&#x2F;&quot;&gt;Battle.Net launcher using Lutris&lt;&#x2F;a&gt;
(available from the software store on fedora) was very convenient!&lt;&#x2F;p&gt;
&lt;p&gt;My daily driver is an Apple MacBook Pro M2 Max computer, and I interface professionally with Linux almost every day,
so using Linux on my desktop computer will certainly not pose any challenges.&lt;&#x2F;p&gt;
&lt;p&gt;There are still a few challenges getting Linux up and running — understanding that &quot;secure boot&quot; is a thing,
installing the graphics driver separately from special software sources, understanding the &quot;falling back to noveau&quot;
error message on the boot screen, and so on.&lt;&#x2F;p&gt;
&lt;p&gt;My only regret is paying for Windows 11 in the first place.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Lookahead 2024</title>
        <published>2024-01-01T00:00:00+00:00</published>
        <updated>2024-01-01T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/lookahead-2024/"/>
        <id>https://zkc.se/blog/lookahead-2024/</id>
        <content type="html" xml:base="https://zkc.se/blog/lookahead-2024/">&lt;p&gt;Looking back to be able to look forward!
&quot;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;George_Santayana#In_popular_culture&quot;&gt;Those who cannot remember the past are condemned to repeat it&lt;&#x2F;a&gt;&quot;
— and boy  am I repeating mistakes I promised myself I wouldn&#x27;t. So many mistakes.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h1 id=&quot;being-a-leader-of-sorts&quot;&gt;Being a leader (of sorts)&lt;&#x2F;h1&gt;
&lt;p&gt;I&#x27;m the Tech Lead for Spiideo&#x27;s frontend teams, which means that I don&#x27;t just have a responsibility towards my own teams,
but also towards everyone else in every other team. The responsibilities in question are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Fostering a good culture&lt;&#x2F;li&gt;
&lt;li&gt;Being open to change&lt;&#x2F;li&gt;
&lt;li&gt;Resisting bad engineering practices&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I&#x27;d also like to see myself as someone who contributes positively outside of work too: Writing good bug reports on
open source projects and helping out on forums. Being socially progressive. Reaching out and helping out, for small
things and large. But I also do a lot of dumb shit.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;fostering-a-good-culture&quot;&gt;Fostering a good culture&lt;&#x2F;h1&gt;
&lt;p&gt;I&#x27;ve worked at a huge company as a Senior engineer, working my way up from 24-year-old junior engineer-me. I left that
company, Sony Mobile, in 2015. We didn&#x27;t have Slack at that point, but maybe they have something now? The only people
I interacted with were the colleagues sitting next to me, and the ones I needed to interact with by e-mail, or in person
(by walking over to their desk). I guess tickets in the issue handling system also counted. My social reach was limited,
and often in person, where my body language and facial expressions could accompany what I said. More importantly, I didn&#x27;t
have the level of responsibility that I have now.&lt;&#x2F;p&gt;
&lt;p&gt;In 2015, I didn&#x27;t just quit Sony Mobile, I also joined Spiideo. A small team of five developers sitting in one room doing
a lot of coding. It was great, and it was in person. Bad or lewd jokes, making fun of each other in a loving way —
there was a lot to look forward to on a Sunday afternoon. But we didn&#x27;t just joke around in person, work Slack was full
of dank jokes.&lt;&#x2F;p&gt;
&lt;p&gt;Eight years later, we&#x27;re a lot more people! Slack is full of names of people I&#x27;ve never met.
Last year I still took opportunities to rip into someone lovingly. Last year I still posted some lewd dank stuff.
But I&#x27;ve also been challenged a lot of times on that, and rightly so. Irony and sarcasm in text just isn&#x27;t very effective.
Friendly banter in one small, tightly-knit, group can be bullying in another group. This doesn&#x27;t just apply to Slack,
but to any online social interactions.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not possible for me to be &lt;em&gt;just&lt;&#x2F;em&gt; a tech lead. For my own sake, I need to have a heavier non-technical leadership aura as well.
So what I will do is to look around me, find positive traits in the people I admire, and make those traits a part of
my own vibe. Acquiring positive traits is not enough though. I have to shed behavior that makes other people uncomfortable,
sad, angry, or worse. I hope those changes will let me be a steward of positivity.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;being-open-to-change&quot;&gt;Being open to change&lt;&#x2F;h1&gt;
&lt;p&gt;If the last section was about changing my outward behavior, this one must be the opposite. Just thinking about inner
change is scary to me.&lt;&#x2F;p&gt;
&lt;p&gt;This last year I&#x27;ve spent a lot of time being a hard-ass LLM hater. At work. In my socials. Most of my criticism still
seem valid to me. LLMs will make the bad parts of the internet even worse: It&#x27;s already easier to generate convincing spam,
it&#x27;s already easier to generate content for search-engine optimized sites that only want to serve you more ads.&lt;&#x2F;p&gt;
&lt;p&gt;However, it&#x27;s also undeniable that a new generation of developers, as well as some of the more progressive old heads,
are finding a lot of success using Copilot as well as local models. I have a young colleague that said that programming
was boring before LLMs, but now he&#x27;s inspired. I have no reason to challenge that. I am worried that the hard fought
lessons that made me the programmer I am today are necessary to improve. But I hope that they are not.&lt;&#x2F;p&gt;
&lt;p&gt;How far will coding assistant LLMs take us? What areas are &lt;em&gt;truly&lt;&#x2F;em&gt; fit for LLM applications, and which are unfit? (I
had a chat with Simon Willison on Mastodon, where I asked a variant of this question.)&lt;&#x2F;p&gt;
&lt;p&gt;I need to be more open to change, but I need to do it without losing sight of my ideals. LLM technology is particularly
easy to dislike by way of its potentially &lt;em&gt;transformative&lt;&#x2F;em&gt; effects on society. It&#x27;s not &quot;just&quot; a new piece of technology
that will disrupt businesses, take jobs, and probably create new jobs. Bad people have been given a superpower overnight.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;resisting-bad-engineering-practices&quot;&gt;Resisting bad engineering practices&lt;&#x2F;h1&gt;
&lt;p&gt;There may be tension between fostering good culture, being open to change, and resisting bad engineering practices.
Tension seems endemic to engineering, but it is necessary to help the teams &lt;em&gt;resist bad engineering practices&lt;&#x2F;em&gt; in the face of it.
Engineering practices are their own social organism inside an organisation. Senior engineers that engage in positive
social practices can still enable bad engineering practices, and vice versa. Linus Torvalds is an example of someone
that has excellent technical skills, but is known to have had abysmal social approaches to get the engineering right.
Steve Jobs is someone that built an amazing legacy in tech, but was terrible socially.&lt;&#x2F;p&gt;
&lt;p&gt;Being an enabler for good engineering practices is something I&#x27;ve been trying to do for a long time. Doing even more,
helping the other tech leads, and all the developers in all the teams is what I&#x27;m looking to achieve next.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;final-words&quot;&gt;Final words&lt;&#x2F;h1&gt;
&lt;p&gt;I don&#x27;t want my place of work to have any Torvalds or Jobs types. I certainly don&#x27;t want to be seen as one. Not even a
carbon copy. Not even &quot;just a bad coworker&quot;, and definitely not a bully. I hope that someone can find that inspiring.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>So what&#x27;s wrong with ▒▒▒▒▒▒▒?</title>
        <published>2023-12-22T00:00:00+00:00</published>
        <updated>2023-12-22T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/so-whats-wrong-with-insert-tech/"/>
        <id>https://zkc.se/blog/so-whats-wrong-with-insert-tech/</id>
        <content type="html" xml:base="https://zkc.se/blog/so-whats-wrong-with-insert-tech/">&lt;p&gt;My blog is insignificant, and I intend to keep it that way! But besides being
a waste of bytes, it&#x27;s part of the internet, and the internet is very important
to a lot of people!&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s play &quot;So what&#x27;s wrong with ▒▒▒▒▒▒▒?&quot;&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h1 id=&quot;so-what-s-wrong-with-cryptocurrency&quot;&gt;So what&#x27;s wrong with cryptocurrency?&lt;&#x2F;h1&gt;
&lt;p&gt;First of all, it has dubious utility except for speculation and criminal activity, and
honestly sometimes those are the same thing. Some people, nice good-meaning people,
don&#x27;t mind that it&#x27;s wiping out decades of green energy advances, for reasons unknown
(lmao, I mean exchanging fake internet money for real, usable, money).&lt;&#x2F;p&gt;
&lt;p&gt;Even the purportedly green proof-of-stake cryptocurrencies are still dumb ponzi-
schemes: if you came in early you&#x27;re smart and rich and if you came in late you
hope to become the former.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Grade: F-&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Bottom line: Stay away.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;so-what-s-wrong-with-internet-advertisements&quot;&gt;So what&#x27;s wrong with internet advertisements?&lt;&#x2F;h1&gt;
&lt;p&gt;Either you pay for it, or you&#x27;re the product. There&#x27;s a lot of wisdom in that. People
my age used to watch a lot of linear TV, and we saw a lot of ads! That fucking sucked,
so when fast home internet met Bittorrent, broadcast TV became irrelevant. Netflix and
others improved on that by making it even easier (for a fee). Too many services and
amazingly, fucking ads, are probably going to make piracy come back like Houthis in Aden.&lt;&#x2F;p&gt;
&lt;p&gt;Website ads are delivering malware straight to your browser, and there&#x27;s not much you
can do about it, unless you install a privacy-respecting web browser and get a good ad
blocker.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Grade: E&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Bottom line: Start paying for IT (amazing pun) - &lt;a href=&quot;https:&#x2F;&#x2F;masto.host&quot;&gt;Mastodon&lt;&#x2F;a&gt;,
Email, and much more. Reject your surveillance capitalism overlords.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;so-what-s-wrong-with-generative-ai&quot;&gt;So what&#x27;s wrong with Generative AI?&lt;&#x2F;h1&gt;
&lt;p&gt;Great for coding. Great for helping you outline a new idea. Great for creating page after
page of SEO optimized bullshit to get more eyeballs on ads.&lt;&#x2F;p&gt;
&lt;p&gt;Hilariously, generative AI probably has a bright future! And that bright future looks like this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Replace free online resources like Wikipedia with a $20 OpenAI subscription&lt;&#x2F;li&gt;
&lt;li&gt;Make concise texts longer for no reason other than to make them look more impressive than they are&lt;&#x2F;li&gt;
&lt;li&gt;Make long texts short so that our dumb monkey brains don&#x27;t have to read so much&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Unfortunately for the users, general-purpose LLMs are extremely mid. Mid in the literal sense:
they express the average of their training set. Meaning that a generated article about Roman
windows from the Middle Ages starts generating text about MS DOS after a title like &quot;What existed
before windows?&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;But you should enhance your LLM with a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Prompt_engineering#Retrieval-augmented_generation&quot;&gt;Retrieval Augmented Generation (RAG)&lt;&#x2F;a&gt;,
someone inevitably thinks. The most successful applications will use techniques like that, but
currently that&#x27;s not what most people are interacting with. Maybe one day.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;internet advertisements&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;p&gt;Let&#x27;s visit our old friend internet advertisements again! Not many people are going to pay $20
or $10 or even $5 for a Generative AI assistant. So you&#x27;d better be fucking ready for the
coming boom of juicy Coca Cola descriptions in the middle of your generated text.&lt;&#x2F;p&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;Even if Copilot is admittedly probably going to be very useful for developers, developers
are a tiny fraction of the addressable market (every person on the internet).&lt;&#x2F;p&gt;
&lt;p&gt;Microsoft is losing &lt;a href=&quot;https:&#x2F;&#x2F;www.techradar.com&#x2F;pro&#x2F;microsoft-is-reportedly-losing-huge-amounts-of-money-on-github-copilot&quot;&gt;$80 per copilot user per month&lt;&#x2F;a&gt;,
and the AI revolution isn&#x27;t exactly &lt;a href=&quot;https:&#x2F;&#x2F;www.theverge.com&#x2F;2023&#x2F;10&#x2F;10&#x2F;23911059&#x2F;ai-climate-impact-google-openai-chatgpt-energy&quot;&gt;environmentally friendly&lt;&#x2F;a&gt;
either. That might change though: hardware and software will keep getting better, but will we
put that to good use or will we use the slack to create even bigger things?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Grade: C&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Bottom line: Has a lot of utility when applied right, but we have yet to apply it to many
things that are not Very Stupid.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Unsticking “Find My” from a Mac after changing my Apple ID e-mail</title>
        <published>2023-08-01T00:00:00+00:00</published>
        <updated>2023-08-01T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/unsticking-find-my-from-a-mac/"/>
        <id>https://zkc.se/blog/unsticking-find-my-from-a-mac/</id>
        <content type="html" xml:base="https://zkc.se/blog/unsticking-find-my-from-a-mac/">&lt;p&gt;I recently changed the e-mail address of my Apple ID, but the Find My association
on the mac didn&#x27;t get the memo.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;This is the story of how I went from a computer that couldn&#x27;t be transferred to
my colleague, to one that could.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;changing-e-mail-of-my-apple-id&quot;&gt;Changing e-mail of my Apple ID&lt;&#x2F;h1&gt;
&lt;p&gt;To begin with, I had a mac which was signed in with my Apple ID, let&#x27;s say
that it was &lt;code&gt;erik.zivkovic@example.com&lt;&#x2F;code&gt;. I was signed in to multiple Apple
service, including &quot;Find My&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;When we added &quot;Sign in with Apple&quot; to our web and iOS applications, I had a
problem on my hands - I was already signed in to our dev and prod environments
using my Google Workspace e-mail, which was &lt;code&gt;erik.zivkovic@example.com&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To test Sign in With Apple, I needed a new e-mail address because my old one
was already associated with my Google Workspace credentials (we don&#x27;t have
many-to-one mappings of credentials).&lt;&#x2F;p&gt;
&lt;p&gt;So I did the &quot;smart thing&quot;, I asked to get an extra e-mail address associated
with my Google Workspace profile, and then I changed my Apple ID to use the
new address — &lt;code&gt;erik.zivkovic@example.com&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;handing-off-my-old-workhorse-to-a-colleague&quot;&gt;Handing off my old workhorse to a colleague&lt;&#x2F;h1&gt;
&lt;p&gt;After wiping the computer properly I handed the computer over to my colleague
who tried to sign in using his Apple ID. Instead of being logged in he was
presented with a dialog box —&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;macOS dialog&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;p&gt;&lt;strong&gt;Apple ID Password&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Enter Apple ID password for &quot;erik.zivkovic@example.com&quot; to turn off Find My Mac.&lt;&#x2F;p&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;Naturally, I tried my Apple ID password. But it didn&#x27;t work, because my Apple ID
is no longer &lt;code&gt;erik.zivkovic@example.com&lt;&#x2F;code&gt;, it&#x27;s &lt;code&gt;erik@example.com&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;My computer was still enrolled to &quot;Find My&quot;, and was being managed by my Apple ID,
with seemingly no way to turn it off.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;apple-chat-support-actually-helped&quot;&gt;Apple chat support actually helped&lt;&#x2F;h1&gt;
&lt;p&gt;After doing a few rounds with Swedish Apple support, which unfortunately weren&#x27;t
much help, I decided to try U.S. Apple support.&lt;&#x2F;p&gt;
&lt;p&gt;The nice lady helped me understand what I needed to do, shortly summarized below,
so you don&#x27;t have to spend hours chatting with support&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Make sure the problematic computer is connected to the internet&lt;&#x2F;li&gt;
&lt;li&gt;Sign in to &lt;a href=&quot;https:&#x2F;&#x2F;iCloud.com&quot;&gt;iCloud.com&lt;&#x2F;a&gt; using your Apple ID&lt;&#x2F;li&gt;
&lt;li&gt;In the map view, there is a dropdown where you can select computers&lt;&#x2F;li&gt;
&lt;li&gt;Select the problematic mac&lt;&#x2F;li&gt;
&lt;li&gt;Select &quot;Erase Mac&quot;&lt;&#x2F;li&gt;
&lt;li&gt;The mac should start erasing remotely&lt;&#x2F;li&gt;
&lt;li&gt;It should now be possible to &quot;Remove from account&quot; — do that&lt;&#x2F;li&gt;
&lt;li&gt;After erasing is complete
&lt;ul&gt;
&lt;li&gt;Use Disk Utility to create a new partition, &lt;code&gt;APFS&lt;&#x2F;code&gt; worked well for me —
call the new partition &quot;Macintosh HD&quot;&lt;&#x2F;li&gt;
&lt;li&gt;Quit Disk Utility, then install macOS&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;You should now have an unstuck computer.&lt;&#x2F;p&gt;
&lt;p&gt;I wrote a &lt;a href=&quot;https:&#x2F;&#x2F;apple.stackexchange.com&#x2F;q&#x2F;462691&#x2F;138654&quot;&gt;Q&#x2F;A style answer&lt;&#x2F;a&gt; on
the &quot;Ask Different&quot; StackExchange for this issue.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;an-unrelated-but-annoying-bug&quot;&gt;An unrelated but annoying bug&lt;&#x2F;h1&gt;
&lt;p&gt;I also ran into an issue where I first used a &lt;code&gt;Mac OS Extended (Journaled)&lt;&#x2F;code&gt;
filesystem for the disk&#x2F;partition. When trying to install to the &quot;Macintosh HD&quot;
that was formatted using &lt;code&gt;Mac OS Extended (Journaled)&lt;&#x2F;code&gt; I got an annoying error:&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Installer popover&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;p&gt;The operation could not be completed (com.apple.BuildInfo.preflight.error error 10.)&lt;&#x2F;p&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;After scratching my head for a while I tried using &lt;code&gt;APFS&lt;&#x2F;code&gt; for the file system instead
of &lt;code&gt;Mac OS Extended (Journaled)&lt;&#x2F;code&gt;. And it worked!&lt;&#x2F;p&gt;
&lt;p&gt;I wrote a &lt;a href=&quot;https:&#x2F;&#x2F;apple.stackexchange.com&#x2F;q&#x2F;462689&#x2F;138654&quot;&gt;Q&#x2F;A style answer&lt;&#x2F;a&gt; on
the &quot;Ask Different&quot; StackExchange for this issue too.&lt;&#x2F;p&gt;
&lt;p&gt;Good Luck!&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Book: Rust Atomics and Locks</title>
        <published>2023-07-23T00:00:00+00:00</published>
        <updated>2023-07-23T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/rust-atomics-and-locks/"/>
        <id>https://zkc.se/blog/rust-atomics-and-locks/</id>
        <content type="html" xml:base="https://zkc.se/blog/rust-atomics-and-locks/">&lt;p&gt;Learning low level concurrency primitives through Rust! I read the book
&quot;Rust Atomics and Locks&quot; by Mara Bos, and it helped me develop my understanding
of, and build an intuition for, how atomics work in modern computers.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;First of all — I highly recommend buying (or borrowing) &lt;a href=&quot;https:&#x2F;&#x2F;marabos.nl&#x2F;atomics&#x2F;&quot;&gt;the book&lt;&#x2F;a&gt;.
Buy locally if you can! &lt;em&gt;Support your local book dealers&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;audience&quot;&gt;Audience&lt;&#x2F;h1&gt;
&lt;p&gt;Developers that need a deeper understanding of the inner workings of our
programs and machines.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;focus&quot;&gt;Focus&lt;&#x2F;h1&gt;
&lt;p&gt;To me, the most interesting chapters of the book are &lt;em&gt;Chapter 2. Atomics&lt;&#x2F;em&gt; and
&lt;em&gt;Chapter 3. Memory Ordering&lt;&#x2F;em&gt;. Other parts of the book build on these two
chapters and show us how to create higher level primitives on top of atomics.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;problem-statement&quot;&gt;Problem statement&lt;&#x2F;h1&gt;
&lt;p&gt;To build a standard library for Rust with useful multi-threading primitives like
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;struct.Mutex.html&quot;&gt;Mutex&lt;&#x2F;a&gt;, or third-party
APIs like Tokio&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;latest&#x2F;tokio&#x2F;sync&#x2F;mpsc&#x2F;fn.channel.html&quot;&gt;Channel&lt;&#x2F;a&gt;,
we need to have a means of building those primitives.&lt;&#x2F;p&gt;
&lt;p&gt;Atomic operations are one of the necessary building blocks to achieve that.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;Sidebar with my friend jonasdn&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;p&gt;It&#x27;s completely possible to have a solid systems programming career without ever
needing to know about memory ordering or atomics. But it doesn&#x27;t hurt to know about
them either — They&#x27;re building blocks for the things that you do use.&lt;&#x2F;p&gt;
&lt;p&gt;– &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.nu&#x2F;@jonasdn&quot;&gt;@jonasdn@mastodon.nu&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

    
&lt;&#x2F;div&gt;
&lt;h1 id=&quot;atomics&quot;&gt;Atomics&lt;&#x2F;h1&gt;
&lt;p&gt;Atomics enable us to share information between threads in a &lt;em&gt;data race free&lt;&#x2F;em&gt; way.
The tools we have in the toolbox are &lt;em&gt;atomic variables&lt;&#x2F;em&gt;, and &lt;em&gt;atomic fences&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Atomic variables are small — way too small to hold any significant amount of data.
The maximum size of an atomic variable depends on the platform but can at least
have the size of a pointer on that platform, meaning 64 bits for modern platforms
like x86-64 or ARM64&#x2F;AArch64.&lt;&#x2F;p&gt;
&lt;p&gt;If you have an atomic variable, you can write to it from one thread, and the
result will be visible to another thread at some (not too distant) time in the
future, without further synchronization.&lt;&#x2F;p&gt;
&lt;p&gt;The most important attribute of atomics is that it&#x27;s possible to use them to order
&lt;em&gt;other&lt;&#x2F;em&gt; instructions, meaning it&#x27;s possible to know that &lt;em&gt;some other data&lt;&#x2F;em&gt; than the
atomic variable itself is ready to read fully and correctly.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;memory-ordering&quot;&gt;Memory Ordering&lt;&#x2F;h1&gt;
&lt;p&gt;To be able to achieve our goal of correctly and reliably sending data between
threads we need to know &lt;em&gt;when&lt;&#x2F;em&gt; we&#x27;re allowed to access that data. The term &lt;em&gt;when&lt;&#x2F;em&gt; inside
a computer program, or even inside a computer, is a complicated thing to nail down.&lt;&#x2F;p&gt;
&lt;p&gt;Compilers are &lt;em&gt;allowed to reorder instructions&lt;&#x2F;em&gt;, as long as the end result is the same.
Rust, C, C++, etc. all have one or more optimization steps that reorder and combine
different parts of your code in the name of performance. And that&#x27;s a good thing,
because otherwise our programs would be slow.&lt;&#x2F;p&gt;
&lt;p&gt;Processors also reorder instructions — pipelined instructions stages, speculative
execution, and other things end up reordering the actual instructions. This is done
because CPUs often wait for things like RAM to be loaded into a cache line, and while
it&#x27;s doing that it can complete other instructions that are ready to execute.&lt;&#x2F;p&gt;
&lt;p&gt;How do we bring order to this world? We need to have control over the chaos
that are programs running on CPUs. We need to control in which order things
happen. But we don&#x27;t want too much control. That would slow down our programs — compilers
and CPUs reorder instructions for a reason!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;atomic-variables&quot;&gt;Atomic variables&lt;&#x2F;h2&gt;
&lt;p&gt;An atomic variable stores a small amount of data, and when you load from it or
store to it, you need to specify a memory ordering flag.&lt;&#x2F;p&gt;
&lt;p&gt;The memory orderings available in Rust are found in the
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;atomic&#x2F;enum.Ordering.html&quot;&gt;Ordering&lt;&#x2F;a&gt; enum:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-enum z-rust&quot;&gt;enum&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-enum z-rust&quot;&gt;Ordering&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Weakest ordering guarantees
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    Relaxed&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    Release&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    Acquire&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    AcqRel&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Strongest ordering guarantees
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    SeqCst&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-enum z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The typical methods you will use on atomic variables are&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;atomic&#x2F;struct.AtomicBool.html#method.load&quot;&gt;load&lt;&#x2F;a&gt; Loads a value from the variable&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;atomic&#x2F;struct.AtomicBool.html#method.store&quot;&gt;store&lt;&#x2F;a&gt; Stores a value to the variable&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;atomic&#x2F;struct.AtomicBool.html#method.compare_exchange&quot;&gt;compare_exchange&lt;&#x2F;a&gt;
First checks if the value inside the variable is the expected one, and then replaces it if the check passes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There&#x27;s far more information available in the book, and in the Rust documentation.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;relaxed-ordering&quot;&gt;Relaxed ordering&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;Ordering::Relaxed&lt;&#x2F;code&gt; is the weakest ordering. This is useful when simply sharing
data between threads inside the atomic variable, and is the most performant.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately &lt;code&gt;Ordering::Relaxed&lt;&#x2F;code&gt; can&#x27;t be used to prevent the compiler or the processor
from reordering instructions by itself. Using a Relaxed ordering only guarantees that once
written, the value can be safely read from another thread.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;release-acquire-ordering&quot;&gt;Release &amp;amp; Acquire ordering&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;Ordering::Release&lt;&#x2F;code&gt; is used to store into an atomic variable, and guarantees that
any instructions before it on the same thread happen-before any instructions after
an &lt;code&gt;Ordering::Acquire&lt;&#x2F;code&gt; load from that same atomic variable on another thread. But
not without a few caveats —&lt;&#x2F;p&gt;
&lt;p&gt;If you store into an atomic variable using the Release ordering, and then load
that same variable on another thread using an Acquire ordering there is a guarantee
that any instructions before the release-store happen-before any instructions
after the acquire-load &lt;strong&gt;if and only if&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;The release-store is observed by the acquire-load&lt;&#x2F;em&gt; — example: if the acquire-load sees
an AtomicBoolean change from false to true, and that is the expected precondition
for another instruction to have happened, then the instructions of the release-store
happen-before the acquire-load.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;The release-store was from the same thread as the instructions expected to have happened-before&lt;&#x2F;em&gt;
— example: If two (or more) threads store into an atomic variable only one
of the threads will have a happens-before relationship with the acquire-load,
namely the thread that had its release-store observed by the acquire-load.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The last rule means that if ten threads all release-store (write) to the same
atomic variable, only one of them will have a happens-before relationship with
the acquire-load (read), and only that one thread can be expected to have had
all of its instructions ordered correctly. If we try to read memory written by
any of the other threads at that point, that memory might be improperly written
or synchronized leading to Undefined Behavior.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;atomic-fences&quot;&gt;Atomic fences&lt;&#x2F;h2&gt;
&lt;p&gt;An atomic &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;atomic&#x2F;fn.fence.html&quot;&gt;fence&lt;&#x2F;a&gt; is an
operation that does not read or write any data itself, but can be used together
with reading and writing to accomplish a certain ordering. One interesting property
is that reading and writing can be done using &lt;code&gt;Ordering::Relaxed&lt;&#x2F;code&gt;, and it will still work.
This is mostly useful if there are multiple atomic variables that need to be used
together with a single fence. Another interesting property of an atomic fence is
that it can be issued &lt;em&gt;conditionally&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In short: issuing a Release fence followed by a Relaxed store on one thread,
then issuing a Relaxed load followed by an Acquire fence on another thread
establishes a happens-before relationship between the fence instructions even
though the actual store and the actual load were both Relaxed. This seemed
counterintuitive to me when I read it. Especially the part where the store
and the load happen between the fences instead of before&#x2F;after them.&lt;&#x2F;p&gt;
&lt;p&gt;The paragraphs in the &lt;em&gt;Rust Atomics and Locks&lt;&#x2F;em&gt; book covering atomic fences had
me asking how fences were supposed to be used. It was all there, of course, but
not clear enough for me to fully understand it without additional resources.
Jeff Preshing&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;preshing.com&#x2F;20130922&#x2F;acquire-and-release-fences&#x2F;&quot;&gt;blog post&lt;&#x2F;a&gt;
made it click. Have a look!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-if-we-don-t-use-atomics&quot;&gt;What if we don&#x27;t use atomics?&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s declare a shared mutable variable that we are going to use in a couple of
examples.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Have some globally modifiable data (unsafe)
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;static&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-other z-rust&quot;&gt;GLOBAL_DATA&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;u128&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Imagine starting two threads, writing data in one of them, and reading data from
the other.&lt;&#x2F;p&gt;
&lt;p&gt;Thread 1:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Write some shared data using unsafe
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;unsafe&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-other z-rust&quot;&gt;GLOBAL_DATA&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;12345&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Thread 2:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; How long do we wait here before the data is readable?
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; data &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;unsafe&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-other z-rust&quot;&gt;GLOBAL_DATA&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; do something with data...
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s almost impossible to know how long to wait for the data to become available
in the second thread. This is because it could be stuck in an L1 cache inside the
CPU, a cache that may &quot;never&quot; be available to us since the threads can live on
different CPU cores.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;fixing-it-using-atomic-variables-and-fences&quot;&gt;Fixing it using atomic variables and fences&lt;&#x2F;h1&gt;
&lt;p&gt;Thread 1:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Write some shared data using unsafe
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;unsafe&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-other z-rust&quot;&gt;GLOBAL_DATA&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;12345&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Then issue a Release fence and a relaxed write
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;atomic&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;fence&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Ordering&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Release&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;atomic_bool&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;store&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-rust&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Ordering&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Relaxed&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Thread 2:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Assume that this code is called often (in a loop?)
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; At some point atomic_bool will flip to true in this thread
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;if&lt;&#x2F;span&gt; atomic_bool&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;load&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Ordering&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Relaxed&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Since we issue an Acquire fence here _and_ we saw atomic_bool be true,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; we can be sure that GLOBAL_DATA is safe to read after this fence.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;atomic&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;fence&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Ordering&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Acquire&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; data &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;unsafe&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-other z-rust&quot;&gt;GLOBAL_DATA&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; do something with data...
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we&#x27;ve made sure that the compiler isn&#x27;t allowed to reorder the data write to
&lt;code&gt;GLOBAL_DATA&lt;&#x2F;code&gt; to &lt;em&gt;after&lt;&#x2F;em&gt; the store of &lt;code&gt;true&lt;&#x2F;code&gt; to &lt;code&gt;atomic_bool&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And we&#x27;ve made sure that the read of the &lt;code&gt;GLOBAL_DATA&lt;&#x2F;code&gt; can&#x27;t be reordered to before
the load of &lt;code&gt;atomic_bool&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;Ordering&lt;&#x2F;code&gt;s we use: &lt;code&gt;Acquire&lt;&#x2F;code&gt; and &lt;code&gt;Release&lt;&#x2F;code&gt;, in the exact places they&#x27;re used
not only makes sure that instructions can&#x27;t be reordered by the compiler, they also
inform the CPU to share or flush relevant cache lines (in L1, L2, etc.) in a way that
makes the write to &lt;code&gt;GLOBAL_DATA&lt;&#x2F;code&gt; with &lt;code&gt;Release&lt;&#x2F;code&gt; visible to the next read of &lt;code&gt;GLOBAL_DATA&lt;&#x2F;code&gt;
from the thread that executes the atomic &lt;code&gt;Acquire&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;As I wrote in the &lt;em&gt;Atomics&lt;&#x2F;em&gt; section above, atomics is what you use to
&quot;order &lt;em&gt;other&lt;&#x2F;em&gt; instructions&quot;. Instructions that aren&#x27;t protected by a Mutex, or
data that can&#x27;t fit inside an atomic variable itself. Typically, it&#x27;s about fully
and correctly writing to some shared memory from one thread, signalling that it&#x27;s
ready through atomic operations, and then reading that shared data from another
thread.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;em&gt;other&lt;&#x2F;em&gt; instruction in the example above is the write to the &lt;code&gt;GLOBAL_DATA&lt;&#x2F;code&gt; variable,
which isn&#x27;t atomic.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s important to get this right — reading data that isn&#x27;t fully written is
Undefined Behavior and at that point all bets are off!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;that-one-weird-paragraph&quot;&gt;That one weird paragraph&lt;&#x2F;h1&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;div class=&quot;note-title&quot;&gt;A quote from Rust Atomics and Locks: Chapter 3. Memory Ordering&lt;&#x2F;div&gt;
    &lt;p&gt;The basic happens-before rule is that everything that happens within the same thread
happens in order. If a thread is executing &lt;code&gt;f(); g();&lt;&#x2F;code&gt;, then &lt;code&gt;f();&lt;&#x2F;code&gt; &lt;em&gt;happens-before&lt;&#x2F;em&gt;
&lt;code&gt;g()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;I spent way too much time thinking about this paragraph in the book. As far as I
can tell, function calls are allowed to be reordered, since most code can be
reordered.&lt;&#x2F;p&gt;
&lt;p&gt;What I think it means is that the observable effects in that thread at runtime
are the same as if &lt;code&gt;f();&lt;&#x2F;code&gt; happened before &lt;code&gt;g();&lt;&#x2F;code&gt;, not that they were necessarily
executed in that order in software or even in hardware.&lt;&#x2F;p&gt;
&lt;p&gt;The point the book tries to make in the paragraphs after that is that happens-before
relationships between threads only happen for certain types of operations, of
which atomic variables and fences are two.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;final-words&quot;&gt;Final words&lt;&#x2F;h1&gt;
&lt;p&gt;Use atomics to&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Send small amounts of data between threads directly inside an atomic variable&lt;&#x2F;li&gt;
&lt;li&gt;Send large amounts of data between threads by creating happens-before relationships
between instructions in different threads using atomic variables and atomic fences&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I can&#x27;t stress enough how important the last point is — the capability to order
&lt;em&gt;other&lt;&#x2F;em&gt; instructions than atomic instructions &lt;em&gt;between threads&lt;&#x2F;em&gt;, and use that to
correctly synchronize data between them.&lt;&#x2F;p&gt;
&lt;p&gt;Dig deeper by getting a copy of &lt;a href=&quot;https:&#x2F;&#x2F;marabos.nl&#x2F;atomics&#x2F;&quot;&gt;Rust Atomics and Locks&lt;&#x2F;a&gt; by Mara Bos.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Computer architecture for developers</title>
        <published>2022-11-04T00:00:00+00:00</published>
        <updated>2022-11-04T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/computer-architecture/"/>
        <id>https://zkc.se/blog/computer-architecture/</id>
        <content type="html" xml:base="https://zkc.se/blog/computer-architecture/">&lt;p&gt;An adaption of a talk I gave at work aimed at raising awareness of, and interest in,
computer architecture. The intended audience has low to no knowledge of computer
architecture, but hopefully anyone can enjoy it.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;div class=&quot;note&quot;&gt;
    &lt;div class=&quot;note-title&quot;&gt;A note on accessiblity&lt;&#x2F;div&gt;
    &lt;p&gt;This article contains a lot of images. I have tried to make the article
accessible by explaining most things in text, so you wouldn&#x27;t necessarily
need the images, they&#x27;re mostly there for flair. If there are accessibility
problems though, please let me know.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h1 id=&quot;act-one-why-do-we-need-computers&quot;&gt;Act one - why do we need computers?&lt;&#x2F;h1&gt;
&lt;p&gt;I guess it all starts with nonsense like &quot;what is 1 + 1?&quot;. Many people throughout
history have asked questions like that, and most settled for pen and paper —
sensible, efficient. But just like a kid&#x27;s dinosaur you eventually replace it
with something more exciting (like complex numbers, perhaps?) and someone needs
to be there to pick up the slack.&lt;&#x2F;p&gt;
&lt;p&gt;A half adder is at least as sensible as pen and paper for calculating 1 + 1,
so people started using half adders. Half adders can be built by wiring together
an XOR gate and an AND gate, yielding two inputs (A, B) and two outputs (Sum, Carry).&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0001_gate.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0001_gate.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;A half adder has a truth table that looks like this&lt;&#x2F;p&gt;
&lt;div class=&quot;hscroll&quot;&gt;
    &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;input A&lt;&#x2F;th&gt;&lt;th&gt;input B&lt;&#x2F;th&gt;&lt;th&gt;output Sum&lt;&#x2F;th&gt;&lt;th&gt;output Carry&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;That worked for a while, but wiring up half adders all day gets old fast.
&quot;And nobody liked that&quot;, as it were. Long story short: that&#x27;s why we invented
assembly language.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0002_nasm.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0002_nasm.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;&lt;pre data-lang=&quot;asm&quot; class=&quot;language-asm z-code&quot;&gt;&lt;code class=&quot;language-asm&quot; data-lang=&quot;asm&quot;&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;&lt;span class=&quot;z-keyword z-control z-assembly&quot;&gt;mov&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-register z-assembly&quot;&gt;ax&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-decimal z-assembly&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;&lt;span class=&quot;z-keyword z-control z-assembly&quot;&gt;mov&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-register z-assembly&quot;&gt;bx&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-decimal z-assembly&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;&lt;span class=&quot;z-keyword z-control z-assembly&quot;&gt;add&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-register z-assembly&quot;&gt;ax&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-register z-assembly&quot;&gt;bx&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is assembly language in nasm form. &lt;code&gt;mov ax, 1&lt;&#x2F;code&gt; means put the number 1 in
register &lt;code&gt;ax&lt;&#x2F;code&gt;, basically &lt;code&gt;let ax = 1;&lt;&#x2F;code&gt; in pseudocode. &lt;code&gt;add ax, bx&lt;&#x2F;code&gt; on the last
line adds the numbers together
and puts the result in the first register. Writing it as pseudocode would yield
something like &lt;code&gt;let ax = ax + bx;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.nasm.us&#x2F;&quot;&gt;nasm&lt;&#x2F;a&gt; is an x86 assembler, and it&#x27;s the nasm syntax I have
used above. Check it out, it&#x27;s pretty cool.&lt;&#x2F;p&gt;
&lt;p&gt;The nasm compiler compiles assembly code into x86 machine code, and we&#x27;ll have a
peek at what that looks like and what kind of conclusions can be drawn, but first
we&#x27;ll take a quick look at hexadecimal notation.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0003_hexadecimal.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0003_hexadecimal.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;&lt;div class=&quot;hscroll&quot;&gt;
    &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Decimal&lt;&#x2F;th&gt;&lt;th&gt;Hex&lt;&#x2F;th&gt;&lt;th&gt;Binary&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;0000&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0001&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;...&lt;&#x2F;td&gt;&lt;td&gt;...&lt;&#x2F;td&gt;&lt;td&gt;...&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;10&lt;&#x2F;td&gt;&lt;td&gt;a&lt;&#x2F;td&gt;&lt;td&gt;1010&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;11&lt;&#x2F;td&gt;&lt;td&gt;b&lt;&#x2F;td&gt;&lt;td&gt;1011&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;...&lt;&#x2F;td&gt;&lt;td&gt;...&lt;&#x2F;td&gt;&lt;td&gt;...&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;15&lt;&#x2F;td&gt;&lt;td&gt;f&lt;&#x2F;td&gt;&lt;td&gt;1111&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;The first column shows a decimal number 0 to 15, the second column would be the
corresponding hexadecimal number and the last column is the binary equivalent.
A lot of rows were skipped 😇.&lt;&#x2F;p&gt;
&lt;p&gt;Now that we&#x27;ve at least seen some hexadecimal we can convert our assembly code
into something called machine code by compiling it using the nasm compiler which
turns it into x86 machine code.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0004_machine_code_1.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0004_machine_code_1.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;&lt;pre data-lang=&quot;asm&quot; class=&quot;language-asm z-code&quot;&gt;&lt;code class=&quot;language-asm&quot; data-lang=&quot;asm&quot;&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control z-assembly&quot;&gt;mov&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-register z-assembly&quot;&gt;ax&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-decimal z-assembly&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt;8&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-decimal z-assembly&quot;&gt;01&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-decimal z-assembly&quot;&gt;00&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control z-assembly&quot;&gt;mov&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-register z-assembly&quot;&gt;bx&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-decimal z-assembly&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-decimal z-assembly&quot;&gt;01&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-decimal z-assembly&quot;&gt;00&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control z-assembly&quot;&gt;add&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-register z-assembly&quot;&gt;ax&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-register z-assembly&quot;&gt;bx&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-assembly&quot;&gt;&lt;span class=&quot;z-constant z-character z-decimal z-assembly&quot;&gt;01&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-assembly&quot;&gt;8&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first thing we see in the compiled x86 machine code is that each textual
instruction has been converted into a sequence of bytes.&lt;&#x2F;p&gt;
&lt;p&gt;As an aside, I can mention that x86 instructions are stored as little endian.&lt;&#x2F;p&gt;
&lt;p&gt;Little endian is one of two ways of storing or transmitting bytes in a computer
or over a computer network. The other way would be big endian. Every byte of a
given sequence of bytes would be stored with the &quot;little number at the lowest byte&quot; in
little endian, so a number like &lt;code&gt;0x0A0B0C0D&lt;&#x2F;code&gt; would have its last byte (meaning
last when reading from left to right, the least significant byte, or the byte with
the least &quot;important&quot; information: &lt;code&gt;0x0D&lt;&#x2F;code&gt;) stored at the
lowest memory address, with each consecutive byte being stored at a higher address.
Read the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Endianness&quot;&gt;endiannesss&lt;&#x2F;a&gt; article on wikipedia
if you want to do a deep-dive.&lt;&#x2F;p&gt;
&lt;p&gt;I personally think that the terms little-endian and big-endian are extremely
confusing and I have to look them up every time. Another bad computer science &#x2F;
programming name is &lt;code&gt;.filter()&lt;&#x2F;code&gt; for arrays, which should really have been called
&lt;code&gt;.keep()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s look a little closer at the machine code.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0005_machine_code_2.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0005_machine_code_2.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The leftmost column is a byte called opcode. The opcode tells the CPU what
we want it to do. &lt;code&gt;b8&lt;&#x2F;code&gt; would mean &lt;code&gt;mov&lt;&#x2F;code&gt; data into the register &lt;code&gt;ax&lt;&#x2F;code&gt;.
&lt;code&gt;bb&lt;&#x2F;code&gt; on the other hand means &lt;code&gt;mov&lt;&#x2F;code&gt; data into the register &lt;code&gt;bx&lt;&#x2F;code&gt;.
The data columns for the first two lines both hold the number 1 in little endian.&lt;&#x2F;p&gt;
&lt;p&gt;The third line is a little more interesting because it&#x27;s the opcode &lt;code&gt;01&lt;&#x2F;code&gt; which
is &lt;code&gt;add&lt;&#x2F;code&gt;, but it only takes a single byte argument. That byte needs to be split
into three parts: The first two bits signify what the next six bytes represent.
&lt;code&gt;11&lt;&#x2F;code&gt; means both of the coming three bit sequences are registers, &lt;code&gt;011&lt;&#x2F;code&gt; means &lt;code&gt;bx&lt;&#x2F;code&gt;
and &lt;code&gt;000&lt;&#x2F;code&gt; means &lt;code&gt;ax&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But what would it look like if we turned all of these hexadecimal machine code
instructions into binary numbers instead?&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0006_machine_code_3.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0006_machine_code_3.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I&#x27;d say that looks a bit like the inputs to the half adder we studied above, just
a teeny tiny bit more complex.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe you already knew, but...&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0007_machine_code_4.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0007_machine_code_4.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;machine code is generally independent of the host operating system of your
computer. If you have an x86 mac, x86 windows, or x86 linux computer then most of the
instructions inside a program would be the same no matter the platform.
Only the code talking to the operating system would differ significantly.&lt;&#x2F;p&gt;
&lt;p&gt;But we were talking about adding numbers, weren&#x27;t we? For a long time people
were writing computer programs in assembly language to perform complex tasks
like putting people on the moon.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0008_several_million_years_later.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0008_several_million_years_later.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;And for a long time that was the best way to do it.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0009_c_programming.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0009_c_programming.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;But later scientist discovered another way to add numbers together. Unfortunately
that method was the C programming language, which I hope most modern number adder
people will shy away from  like the plague.&lt;&#x2F;p&gt;
&lt;p&gt;C is... a (not very good) language but has found a niche together with C++ as unreliable,
unsafe, but very fast number adders. But there are a lot of number adder languages
out there, and some of them can be laid out on the Garbage Collected (GC)&#x2F;non-GC vs
unsafe&#x2F;safe axes like so.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0010_safe_gc_unsafe.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0010_safe_gc_unsafe.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The unsafe + GC quadrant is conspicuously vacant.
We have C and C++ in the unsafe + non-GC quadrant,
Java, Python, Javascript, and Go in the safe + GC quadrant,
and lastly Swift and Rust in the safe + non-GC quadrant.&lt;&#x2F;p&gt;
&lt;p&gt;What is a (memory) safe language anyway? Safe languages exhibit at least the following properties&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;No undefined behavior&lt;&#x2F;li&gt;
&lt;li&gt;No use-after-free memory reads&lt;&#x2F;li&gt;
&lt;li&gt;No out-of-bounds memory reads&lt;&#x2F;li&gt;
&lt;li&gt;No double-free memory releases&lt;&#x2F;li&gt;
&lt;li&gt;Only &quot;logic bugs&quot; can happen&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;What is a GC (Garbage Collected) language?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Memory safe&lt;&#x2F;li&gt;
&lt;li&gt;Most things tend to be heap allocated&lt;&#x2F;li&gt;
&lt;li&gt;Memory is freed from the heap when the runtime decides (as opposed to the programmer)&lt;&#x2F;li&gt;
&lt;li&gt;Tend to be a bit slower, tend to have &quot;GC pauses&quot;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s have a look at my completely made up and over-generalizing chart™️&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0011_alternate_view.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0011_alternate_view.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The picture shows a rough timeline and a rough fast&#x2F;slow categorization of
the same languages that were compared previously. Assembly was invented around 1947,
a good 25 years before C. In the 90&#x27;s we got Python, Javascript, and Java tightly
following each other, all Garbage Collected languages (Abe Simpson voice: which was the style at the time).&lt;&#x2F;p&gt;
&lt;p&gt;In the 2000s we got Golang, also a safe GC language. In 2010 and 2014 we saw the
birth of two, currently very popular, safe non-GC languages: Rust and Swift, respectively.&lt;&#x2F;p&gt;
&lt;p&gt;From my totally made up diagram we can draw the conclusion that most GC languages
are pretty slow, but Go seems to be an outlier? What&#x27;s going on? Let&#x27;s put a pin in that for now.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;act-two-why-do-we-need-to-know-how-computers-work&quot;&gt;Act two - Why do we need to know how computers work?&lt;&#x2F;h1&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0012_rhetorical_question.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0012_rhetorical_question.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Rhetorical, obviously. The textbook answer goes something like &quot;to be able to write
better programs&quot;, but the correct answer is &quot;because computers are Cool&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;If act one was setting up the story, getting to know our protagonist, who just wants to
&quot;add 1 + 1 really fast&quot;, then act two will launch us into conflict with our common
enemy — memory.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0013_memory.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0013_memory.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Let&#x27;s try to deduce why a GC&#x27;d language would be slower than a non-GC&#x27;d one.
Let&#x27;s try to conquer memory 💪.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-novice-tries-to-conquer-memory&quot;&gt;A novice tries to conquer memory&lt;&#x2F;h2&gt;
&lt;p&gt;The novice knows that memory is &quot;segmented&quot; into two main areas: the stack and
the heap. Functions mostly use stack memory while &quot;classes&quot; would be put on the heap.
Java almost entire works off of classes, so almost all the memory would be heap allocated.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0014_heap_stack.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0014_heap_stack.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The novice also knows that the heap is slower than the stack because things
can be created anywhere on the heap, meaning the program has to follow a lot
of pointers to run a program.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0015_fetching_memory.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0015_fetching_memory.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Not only that, but storing the thing AND the pointer takes up more space which
probably makes things slower too. But why?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-competent-programmer-gives-it-a-try&quot;&gt;A competent programmer gives it a try&lt;&#x2F;h2&gt;
&lt;p&gt;Inside the CPU there are several cores and each core has several layers of caching
for memory, and the different layers have different latencies. So accessing
memory tha has already been cached is way faster.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0016_cpu_cores.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0016_cpu_cores.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The latencies are  relative to
each other depending on how far from the CPU registers the memory is cached.
If the registers have latency 1 (no unit) then L1 cache would be 3, L2 cache
would be 12, RAM would be 240 and finally an SSD would be 2400 times slower than
accessing a register.&lt;&#x2F;p&gt;
&lt;p&gt;The sizes of the different levels of memory storage are important, too.
The completely made up computer architecture we will be discussing has
256 bytes of registers, 32 kB of L1 cache, 2 MB of L2 cache, and 16 GB of RAM.&lt;&#x2F;p&gt;
&lt;p&gt;This makes sense because if there is a lot of memory on the heap then stuff in
the L1 and L2 caches would need to be cleared more often because stuff is just
located in different parts of memory all the time.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0017_cache_miss.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0017_cache_miss.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;When the CPU core doesn&#x27;t have the wanted memory in L1 or L2 cache, that&#x27;s
called a cache miss, and the computer would need to fetch the data from RAM,
which is slow.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;an-expert-gives-it-a-try&quot;&gt;An expert gives it a try&lt;&#x2F;h2&gt;
&lt;p&gt;Modern computers operate using Virtual Memory, where 64-bit CPUs use 48 bits of
&lt;em&gt;virtual&lt;&#x2F;em&gt; address space giving a maximum theoretical available physical RAM of 256 TB.&lt;&#x2F;p&gt;
&lt;p&gt;Most computers don&#x27;t have that much memory. But the CPU,
or the Operating System for that matter, don&#x27;t care about that. Each program
will be given a huge chunk of virtual memory space, and programs running in
different processes can even get the same, overlapping, virtual memory space.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0018_virtual_memory.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0018_virtual_memory.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;When a CPU loads memory it does so using Memory Pages, which have a predetermined
size depending on your hardware (and sometimes configurable by the OS). A common
size is a page size of 4 kB.
If there are too many pages to fit in RAM, the Operating System will &quot;page out&quot; to SSD,
which means copy the bytes from RAM to SSD to make space for other things in RAM.&lt;&#x2F;p&gt;
&lt;p&gt;When the CPU later asks for that page, it will be loaded back into RAM, and some
other page might page out instead.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0019_paging.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0019_paging.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Unfortunately the novice and competent programmers have been lied to. The stack &#x2F;
heap dichotomy is a lie.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0020_stack_heap_lie.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0020_stack_heap_lie.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Instead of the stack growing from lower physical addresses and the heap growing
from larger physical addresses, leading to an inevitable memory clash in the middle
of the physical stick of RAM, memory is arranged in pages which are mapped using
virtual memory with a seemingly endless supply of addresses.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0021_physical_pages.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0021_physical_pages.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;&lt;div class=&quot;hscroll&quot;&gt;
    &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Program&lt;&#x2F;th&gt;&lt;th&gt;Type&lt;&#x2F;th&gt;&lt;th&gt;Address&lt;&#x2F;th&gt;&lt;th&gt;Data&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Chrome&lt;&#x2F;td&gt;&lt;td&gt;Stack&lt;&#x2F;td&gt;&lt;td&gt;0xFFFF&lt;&#x2F;td&gt;&lt;td&gt;0xFEEDC0DE&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;VSCode&lt;&#x2F;td&gt;&lt;td&gt;Heap&lt;&#x2F;td&gt;&lt;td&gt;0xFFA0&lt;&#x2F;td&gt;&lt;td&gt;0xF00DC0DE&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Terminal&lt;&#x2F;td&gt;&lt;td&gt;Stack&lt;&#x2F;td&gt;&lt;td&gt;0xFECC&lt;&#x2F;td&gt;&lt;td&gt;0xCAFEC0DE&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;Each page contains data from a singe program and the pages have no particular
order in physical RAM, they&#x27;re just scattered around.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;things-we-didn-t-talk-about&quot;&gt;Things we didn&#x27;t talk about&lt;&#x2F;h2&gt;
&lt;p&gt;OS &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Memory_overcommitment&quot;&gt;memory overcommit&lt;&#x2F;a&gt;.
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Translation_lookaside_buffer&quot;&gt;Translation Lookaside Buffer&lt;&#x2F;a&gt;
(TLB). &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Memory_management_unit#x86-64&quot;&gt;Memory Management Unit&lt;&#x2F;a&gt; (MMU).
All real, not made up things, that you can search for on your favorite search engine.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;act-three-explaining-fast-software&quot;&gt;Act three - Explaining fast software&lt;&#x2F;h1&gt;
&lt;p&gt;Act one introduced us to the concept of math, and how humans have tried to avoid
doing it since way before I was born. Software seems like a good solution
but some programming languages are slower than others.&lt;&#x2F;p&gt;
&lt;p&gt;Act two tried to lay the foundation for understanding why some programming
languages are slow by explaining hardware, but didn&#x27;t reveal any solutions.&lt;&#x2F;p&gt;
&lt;p&gt;Now is the time to combine our newfound knowledge of hardware and software to do what we
came to do. Slay our enemy, Memory.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0022_kill_memory.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0022_kill_memory.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Imagine that you have some data that could be expressed as an array, where each
piece of data takes 64 bytes, and there are 512 elements, how would that data
be laid out in memory?&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0023_java_array.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0023_java_array.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;In Java, it would probably be an array of 512 elements where each element was
an 8 byte pointer to an object taking up 64 bytes. The total amount of memory
needed would be 512 * (8 + 64) bytes.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0024_java_array_realistic.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0024_java_array_realistic.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;In a real world Java application, each 64 byte node would probably contain several
pointers to other pieces of data as well. A tasty pointer soup, if you will.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0025_cache_size_latency.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0025_cache_size_latency.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The more memory each element uses, the more likely it becomes that a complete
data set that is currently used by the CPU to do computations can&#x27;t fit into
L1 or L2 cache.&lt;&#x2F;p&gt;
&lt;p&gt;Each time the size of the data set is larger than L1 cache
the CPU hits a latency cliff, where it needs to ask L2 cache for more data.
When the data set is larger than L2 another latency penalty is experienced by
the program.&lt;&#x2F;p&gt;
&lt;p&gt;First a 3x latency penalty for data sets larger than L1, then a 12x
latency penalty for data sets larger than L2, and so on. And in the ultimate
worst case, penalties for memory being paged in and out of SSD storage.&lt;&#x2F;p&gt;
&lt;p&gt;Having fast software, or Killing Memory as it were, is a matter of seeing
the whole picture. Packing data tightly, not needing to fetch data from a more
expensive type of memory, and using less memory, all of these are important to
keep software fast. Modern computers are complex and complicated, and it&#x27;s not
obvious what is going on inside of them. The more you know about the particular
computer you are targeting, the better.&lt;&#x2F;p&gt;
&lt;p&gt;Calculating 1 + 1 is finally in reach. Or maybe something a bit more complicated, too.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;epilogue&quot;&gt;Epilogue&lt;&#x2F;h1&gt;
&lt;p&gt;It&#x27;s not all bad.&lt;&#x2F;p&gt;
&lt;p&gt;What are the available mitigations, for a software developer like you? First of
all you need to start using languages with larger amount of control of data
layout. Languages that give you the opportunity to choose if data is behind a
pointer allocation (heap) or not. Languages like Rust.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;0026_ferris.svg&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;0026_ferris.svg&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;And what about Go? We put a pin in it, remember? Go occupies a strange niche:
A GC language that&#x27;s faster than its siblings. It&#x27;s more modern, but not based
on LLVM like Swift and Rust. It uses the Plan 9 toolchain, but more importantly
Go has structs that can live on the stack, and mostly uses its GC for long-lived
objects things are passed around between different parts of the program. And even
then it may skip heap allocations by doing escape analysis.&lt;&#x2F;p&gt;
&lt;p&gt;Escape analysis is a compiler optimization technique that elides heap allocations
if the compiler can prove that it can do the given task directly on the stack instead.
Rust uses the LLVM compiler for optimizations, and LLVM can also do escape analysis.&lt;&#x2F;p&gt;
&lt;p&gt;Whew, I hoped &lt;em&gt;any&lt;&#x2F;em&gt; of that made sense.&lt;&#x2F;p&gt;
&lt;p&gt;If you find any errors, or just want to ask a question, contact me using my e-mail address.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;references&quot;&gt;References&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Endianness&quot;&gt;Wikipedia: Endianness&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Virtual_memory&quot;&gt;Wikipedia: Virtual Memory&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Translation_lookaside_buffer&quot;&gt;Wikipedia: Translation Lookaside Buffer&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Memory_management_unit#x86-64&quot;&gt;Wikipedia: Memory Management Unit&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Memory_overcommitment&quot;&gt;Wikipedia: Memory overcommitment&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Array indexing is a footgun and ? is here to help you</title>
        <published>2022-08-10T00:00:00+00:00</published>
        <updated>2022-08-10T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/question-mark-here/"/>
        <id>https://zkc.se/blog/question-mark-here/</id>
        <content type="html" xml:base="https://zkc.se/blog/question-mark-here/">&lt;p&gt;A short look at why array indexing  bugs happen, and ?uestioning why languages
don&#x27;t do more. I need you to use the nearest question mark.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;pre data-lang=&quot;typescript&quot; class=&quot;language-typescript z-code&quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;useEffect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;activeAccount&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-optional z-ts&quot;&gt;?.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;        &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;cancelable&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;exec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;            &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;id&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;            &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;networking&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;search&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;param1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;param2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-constant z-language z-undefined z-ts&quot;&gt;undefined&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-constant z-language z-undefined z-ts&quot;&gt;undefined&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-constant z-language z-undefined z-ts&quot;&gt;undefined&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;param3&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;param4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;param5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;param6&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;param7&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;            &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;        &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-promise z-ts&quot;&gt;then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;content&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-ts&quot;&gt;length&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-relational z-ts&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;setShowCreateTopLevel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-boolean z-true z-ts&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;content&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;levelId&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;setTopLevelId&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;content&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;levelId&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;        &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt; &lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Imagine reviewing this code, a normal and good thing to do, and finding nothing
wrong. Imagine this being one of a handful of changes in different files.
My money is you don&#x27;t find the bug.&lt;&#x2F;p&gt;
&lt;p&gt;Personally, I think my brain would believe that the first bounds check
&lt;code&gt;result.content.length &amp;gt; 0&lt;&#x2F;code&gt; was a refinement, and that the code was working
as it should. Workload goes up, review quality goes down.&lt;&#x2F;p&gt;
&lt;p&gt;But this bug is completely unnecessary, especially in modern JavaScript,
TypeScript and Rust. Unfortunately, the compilers for TypeScript and Rust
won&#x27;t help you find the bug. But I&#x27;ll come back to the bug in a minute.&lt;&#x2F;p&gt;
&lt;p&gt;I like Rust and I like TypeScript but in different ways and for different reasons.&lt;&#x2F;p&gt;
&lt;p&gt;I like Rust because of &lt;span class=&quot;system-font&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lexi-lambda.github.io&#x2F;blog&#x2F;2019&#x2F;11&#x2F;05&#x2F;parse-don-t-validate&#x2F;&quot; title=&quot;Parse Don&amp;#39;t Validate&quot;&gt;P̸̡̿a̸̮̋ṛ̷͝s̴̺̉͝e̸͕̖͆̕ ̴̪̐́Ḍ̶̹̒o̵̲̹͊̽n̷͕͂&#x27;̸̨̉t̸̖̚ ̵̕͜Ṿ̴̬͛a̴̤̍̕l̶͇͘i̴̻̐d̷̙̣̈a̶͕͛͛t̶̬̀͘ē̶̲̟&lt;&#x2F;a&gt;&lt;&#x2F;span&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Nominal_type_system&quot;&gt;Nominal Types&lt;&#x2F;a&gt;,
and great error handling.&lt;&#x2F;p&gt;
&lt;p&gt;I like TypeScript because JavaScript is unusable and TypeScript is marginally less
unusable.&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;But is it really unusable?&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;p&gt;Yes it is extremely unusable.&lt;&#x2F;p&gt;

    
&lt;&#x2F;div&gt;
&lt;h1 id=&quot;javascript-is-unusable&quot;&gt;JavaScript is unusable&lt;&#x2F;h1&gt;
&lt;p&gt;Unusable is a &lt;i&gt;strong word&lt;&#x2F;i&gt; — Like most other scripting languages,
JavaScript has the following properties:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Having more than 50 lines of code makes it effectively write-only.&lt;&#x2F;li&gt;
&lt;li&gt;Every person added to a project introduces bugs at an increasingly exponential rate.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;TypeScript doesn&#x27;t have those same properties. As long as you are diligent about
your design, use types everywhere, and turn on all the &lt;code&gt;strict&lt;&#x2F;code&gt; checks the compiler has,
you can keep adding people and have (slightly sub-)linear increases in productivity.&lt;&#x2F;p&gt;
&lt;p&gt;But TypeScript has so many paper cuts. I&#x27;m figuratively bleeding.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;and-typescript-is-unsound&quot;&gt;And TypeScript is unsound&lt;&#x2F;h1&gt;
&lt;p&gt;TypeScript is &lt;a href=&quot;https:&#x2F;&#x2F;effectivetypescript.com&#x2F;2021&#x2F;05&#x2F;06&#x2F;unsoundness&#x2F;&quot;&gt;wildly unsound&lt;&#x2F;a&gt;,
and it will let you do this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; class=&quot;language-typescript z-code&quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Function calls don&amp;#39;t invalidate refinements&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-class z-ts&quot;&gt;class&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-class z-ts&quot;&gt;UnsoundRefinement&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-ts&quot;&gt;private&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-field z-declaration z-ts&quot;&gt; &lt;span class=&quot;z-meta z-definition z-property z-ts&quot;&gt;&lt;span class=&quot;z-variable z-object z-property z-ts&quot;&gt;mutable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-optional z-ts&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-annotation z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-primitive z-ts&quot;&gt;string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;&lt;span class=&quot;z-meta z-method z-declaration z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-definition z-method z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;refineMe&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-return z-type z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-primitive z-ts&quot;&gt;void&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;&lt;span class=&quot;z-meta z-method z-declaration z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;        &lt;span class=&quot;z-variable z-language z-this z-ts&quot;&gt;this&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;mutable&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Not undefined&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;&lt;span class=&quot;z-meta z-method z-declaration z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language z-this z-ts&quot;&gt;this&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;mutable&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-ts&quot;&gt;!==&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-undefined z-ts&quot;&gt;undefined&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;&lt;span class=&quot;z-meta z-method z-declaration z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;            &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-language z-this z-ts&quot;&gt;this&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;clearMutable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;&lt;span class=&quot;z-meta z-method z-declaration z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-whitespace z-comment z-leading z-ts&quot;&gt;            &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; This is a runtime Error&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;&lt;span class=&quot;z-meta z-method z-declaration z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;            &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-console z-ts&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-console z-ts&quot;&gt;log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language z-this z-ts&quot;&gt;this&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;mutable&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-ts&quot;&gt;length&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;&lt;span class=&quot;z-meta z-method z-declaration z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;        &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;&lt;span class=&quot;z-meta z-method z-declaration z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;&lt;span class=&quot;z-meta z-method z-declaration z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-definition z-method z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;clearMutable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-return z-type z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-primitive z-ts&quot;&gt;void&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;&lt;span class=&quot;z-meta z-method z-declaration z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;        &lt;span class=&quot;z-variable z-language z-this z-ts&quot;&gt;this&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;mutable&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-undefined z-ts&quot;&gt;undefined&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;&lt;span class=&quot;z-meta z-method z-declaration z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-class z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;and-typescript-doesn-t-seem-to-care-that-it-s-unsound&quot;&gt;And TypeScript doesn&#x27;t seem to care that it&#x27;s unsound&lt;&#x2F;h1&gt;
&lt;p&gt;Here&#x27;s TypeScript just throwing its hands in the air:&lt;&#x2F;p&gt;
&lt;div class=&quot;aside&quot;&gt;
    &lt;div class=&quot;aside-title&quot;&gt;&lt;p&gt;strictFunctionTypes&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
    
    
    &lt;p&gt;During development of this feature, we discovered a large number of inherently
unsafe class hierarchies, including some in the DOM. Because of this, the
setting only applies to functions written in function syntax, not to those in method syntax.&lt;&#x2F;p&gt;
&lt;p&gt;— &lt;a href=&quot;https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;tsconfig#strictFunctionTypes&quot;&gt;The TypeScript Documentation&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

    
&lt;&#x2F;div&gt;
&lt;p&gt;The reason I know about this is because I managed to run into it
&lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;q&#x2F;52641612&#x2F;816017&quot;&gt;very early&lt;&#x2F;a&gt; in my TypeScript &quot;career&quot;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;sound-programming-languages-love-runtime-errors&quot;&gt;Sound programming languages love runtime errors&lt;&#x2F;h1&gt;
&lt;p&gt;I don&#x27;t like runtime errors. I&#x27;ll be clear and state that I&#x27;ll take a runtime
error (or panic) over unsoundness every day of the week, but I don&#x27;t have to like it.&lt;&#x2F;p&gt;
&lt;p&gt;C programmers claim that they can allocate and deallocate memory manually and
that it&#x27;s &quot;fine, actually&quot; (it&#x27;s not). Rust and TypeScript programmers claim that
they can decide when to check array lengths before accessing elements and that
&quot;it&#x27;s fine actually&quot; (it is fine actually) — BUT I DON&#x27;T LIKE IT.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;feeling_lucky&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;slice&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;[&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;str&lt;&#x2F;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;usize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; Runtime panic if slice is shorter than 1000 elements.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; The panic is on the index access, not the .len() call.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    slice&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;999&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;typescript&quot; class=&quot;language-typescript z-code&quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;feelingLucky&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;arr&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-annotation z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-primitive z-ts&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-tuple z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-return z-type z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-primitive z-ts&quot;&gt;number&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-whitespace z-comment z-leading z-ts&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Throws a runtime error if slice is shorter than 1000 elements.&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-whitespace z-comment z-leading z-ts&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; The panic is on the .length access, since index-out-of bounds returns undefined.&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;arr&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;999&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-ts&quot;&gt;length&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is no reason why the &lt;code&gt;?&lt;&#x2F;code&gt; operator can&#x27;t just solve this. Both of them.
The type signatures will be different, but that&#x27;s ok with me.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;am_lucky_actually&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;slice&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;[&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;str&lt;&#x2F;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; This isn&amp;#39;t actually valid rust, can&amp;#39;t use ? here:
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    slice&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;999&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-closure z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-closure z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-closure z-rust&quot;&gt;v&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; This is what you would need to write today:
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; slice[999].get()?.map(|v| v.len())
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;typescript&quot; class=&quot;language-typescript z-code&quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;amLuckyActually&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;arr&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-annotation z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-primitive z-ts&quot;&gt;number&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-tuple z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-return z-type z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-primitive z-ts&quot;&gt;number&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-type z-ts&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-builtin z-ts&quot;&gt;undefined&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;arr&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;999&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-optional z-ts&quot;&gt;?.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-ts&quot;&gt;length&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I personally think array indexing shouldn&#x27;t lead to runtime crashes except
when doing &lt;code&gt;.unwrap()&lt;&#x2F;code&gt;, &lt;code&gt;!&lt;&#x2F;code&gt;. In Rust it could be argued that you could skip
the checking step in &lt;code&gt;unsafe&lt;&#x2F;code&gt; code, but &lt;code&gt;get_unchecked&lt;&#x2F;code&gt; already exists so
&lt;i&gt;big shrug&lt;&#x2F;i&gt;, I guess.&lt;&#x2F;p&gt;
&lt;p&gt;Since TypeScript already has (broken) refinement, it could just allow infallible
array indexing when it can prove that the access will be in bounds. Maybe Rust
can get that too, some day. Refinement is really neat, and I wish it wasn&#x27;t
broken in TypeScript.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;back-to-the-initial-review&quot;&gt;Back to the initial review&lt;&#x2F;h1&gt;
&lt;p&gt;Load bearing code —&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; class=&quot;language-typescript z-code&quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;content&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-ts&quot;&gt;length&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-relational z-ts&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;setShowCreateTopLevel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-boolean z-true z-ts&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;content&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;levelId&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;                &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;setTopLevelId&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;content&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;levelId&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The length check doesn&#x27;t wrap the array indexing call.&lt;&#x2F;p&gt;
&lt;p&gt;I easily miss details like this, and I would expect the compiler to have my back.
It does, in a sense, have my back (it crashes), but I resent that I have to find
this error in &lt;a href=&quot;https:&#x2F;&#x2F;sentry.io&quot;&gt;Sentry&lt;&#x2F;a&gt;. 2500 crashes in one week, just as
everyone is enjoying their vacation.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not a big deal. It really isn&#x27;t. But if I could choose, I think I&#x27;d like
to have a compiler that didn&#x27;t let me crash unexpectedly.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>New guide: Rust resources</title>
        <published>2022-07-23T00:00:00+00:00</published>
        <updated>2022-07-23T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/card-carrying-member/"/>
        <id>https://zkc.se/blog/card-carrying-member/</id>
        <content type="html" xml:base="https://zkc.se/blog/card-carrying-member/">&lt;p&gt;Three years, eight months, and two days ago I started a local project on my
computer called &lt;code&gt;my-little-rust&lt;&#x2F;code&gt;. I tried out some &lt;code&gt;match&lt;&#x2F;code&gt; statements, I &lt;code&gt;Box&lt;&#x2F;code&gt;ed
a few things, and I haven&#x27;t stopped since.  It seems I&#x27;m a card carrying member
of the Rust Evangelism Strike Force now.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;I had heard of Rust a few years before that. I think my friend Jonas sent me
an image of a printed version of &lt;em&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;&quot;&gt;The Rust Programming Language&lt;&#x2F;a&gt;&lt;&#x2F;em&gt; book.
Since then, I&#x27;ve become a card-carrying member of the Rust Evangelism Strike Force.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;resf.webp&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;resf.webp&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Today, while answering a question on the Rust users forum, I was reminded that I
joined on December 7, 2019. And it made me wonder when I started using Rust.
&lt;code&gt;gfind -name &quot;*.rs&quot; -type f -printf &#x27;%T+ %p\n&#x27; | sort | head -n 1&lt;&#x2F;code&gt; helped with
that. I created the &lt;code&gt;my-little-rust&lt;&#x2F;code&gt; project on November 21, 2018.
I&#x27;ve written thousands and thousands of lines of Rust since then, but I hope that my most
important contribution will be spreading the use of Rust where I work, as well
as helping others on &lt;a href=&quot;https:&#x2F;&#x2F;users.rust-lang.org&#x2F;&quot;&gt;URLO&lt;&#x2F;a&gt;, StackOverflow, Reddit,
and everywhere else.&lt;&#x2F;p&gt;
&lt;p&gt;I had a bunch of blog posts that I have been revisiting over the
last few years, and I thought it could be a good idea to share them.
So without further ado, I present — The &lt;a href=&quot;&#x2F;rust-resources&quot;&gt;Rust resources&lt;&#x2F;a&gt; page.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Memories of computing; around 1994</title>
        <published>2022-07-19T00:00:00+00:00</published>
        <updated>2022-07-19T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/memories-of-computing-around-1994/"/>
        <id>https://zkc.se/blog/memories-of-computing-around-1994/</id>
        <content type="html" xml:base="https://zkc.se/blog/memories-of-computing-around-1994/">&lt;p&gt;In which I reminisce about the first PCs I came into contact with, as well as
our own software — GKO — &lt;em&gt;Gammalt Kinesiskt Ordspråk (&quot;Old Chinese Proverb&quot;)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;In 1994, my friends Stefan and Paul (brothers) had just got a new computer, a Compaq machine if I
remember correctly. They were the first kids that I knew that had got a computer.
I think it was an all-in-one computer, maybe it was one of these, a CDS 524:&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;compaq_cds_524.png&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;compaq_cds_524.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Before that I had only ever touched my paternal grandfather&#x27;s old computer that
booted from 5.25-inch floppies straight into a &quot;word-processor&quot; and whatever
gibberish I wrote could be printed on a matrix printer.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway. Stefan &amp;amp; Paul&#x27;s computer booted MS DOS and then
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Windows_3.1x&quot;&gt;Windows 3.1&lt;&#x2F;a&gt; on top of that.
Playing a computer game meant shutting down Windows, and going into the DOS
prompt. I guess their father Istvan taught them, because YouTube wasn&#x27;t to be
invented for another 11 years. &quot;Searching the internet&quot; definitely wasn&#x27;t a thing.
Istvan was either studying manuals or asked unknown 1994-era computer geeks 👻&lt;&#x2F;p&gt;
&lt;p&gt;According to &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;History_of_the_Internet_in_Sweden&quot;&gt;the history if internet in Sweden&lt;&#x2F;a&gt;
the first internet connections were available in 1994. But not to us. Certainly not to us.
Interestingly, HSB BRF Hilda (where Stefan &amp;amp; Paul lived) would be one of the first areas
in Sweden where everyone got 100 Mbit connections with an Ethernet plug in each apartment
and a low cost to boot. But at that time I had already moved to Kristianstad. But I digress.&lt;&#x2F;p&gt;
&lt;p&gt;Our unnamed hero taught Istvan who taught Stefan &amp;amp; Paul, who then
taught me, how to open the MS DOS QBasic editor. There we found a game we could
play called &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Gorillas_%28video_game%29&quot;&gt;Gorillas&lt;&#x2F;a&gt;.
It looked like this:&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;gorillas_screenshot.png&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;gorillas_screenshot.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I remember us trying to figure out how to change things in the source code. It
was gibberish to me then, but someone figured out how to change stuff
like colors, and banana speed.&lt;&#x2F;p&gt;
&lt;p&gt;Before all of this my most eye opening computer experience had to have been
using the Amiga Workbench to produce speech from text. That was amazing and
helped cement my love for computers. I owe thanks to whoever created that gem.
Friends of mine had crates of Amiga diskettes which were copied at their house
after school. Everyone seemed to have an infinite number of games.
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;The_Great_Giana_Sisters&quot;&gt;Giana sisters&lt;&#x2F;a&gt; which was
both a Super Mario Bros rip-off and original in its own right.
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Another_World_(video_game)&quot;&gt;Another World&lt;&#x2F;a&gt; was an
amazing computer game that we played on the Amiga and I can&#x27;t believe it was
released in 1991:&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;another_world.png&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;another_world.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I never had an Amiga though. I had a NES 8-bit system, which was great, but I
only had about 8 games. And it had been going strong since around 1989. The only
&quot;piracy&quot; I did was hooking it up to a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Game_Genie&quot;&gt;Game Genie&lt;&#x2F;a&gt;
which let anyone with a &lt;em&gt;Game Genie Manual&lt;&#x2F;em&gt; skip levels and get health boosts.&lt;&#x2F;p&gt;
&lt;p&gt;We played a lot of &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;DuckTales_(video_game)&quot;&gt;Duck Tales&lt;&#x2F;a&gt;
on my friends Ricardo and Carlos&#x27; (brothers) Commodore 64. I always felt it was such a hassle to
rewind the tapes though.&lt;&#x2F;p&gt;
&lt;p&gt;After 1994 the home computer revolution really got started in Sweden.
Ricardo &amp;amp; Carlos&#x27; father worked with computers, so they were also very early.
During recess, we would run to their apartment and play
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Warcraft:_Orcs_%26_Humans&quot;&gt;WarCraft&lt;&#x2F;a&gt;
in their parents&#x27; bedroom. It was always a race against time to run back
to school in time. My best friend at the time, Samy, also got a computer
around this time, but I think it might have been in 1995 or early 1996.
His Packard Bell computer booted into this madness:&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;packard_bell_navigator.png&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;packard_bell_navigator.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Packard_Bell_Navigator&quot;&gt;Packard Bell Navigator&lt;&#x2F;a&gt;
was an alternative shell for Windows 3.1 that was supposed to be &quot;easy to use&quot;.
Thankfully it didn&#x27;t take long to go the way of the Dodo.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, anyway. Sorry. Back to 1994: QBasic was beautiful magic. Somehow, probably
with Istvan&#x27;s help, we managed to learn some QBasic. And we put it to good use, too.
I still remember how much fun it was to run our program and see the results.
I don&#x27;t remember whose idea it was to make a random sentence generator, and I
don&#x27;t remember what the code looked like. I do remember laughing so hard I almost
passed out from not getting enough air.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;gko.png&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;gko.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;&lt;em&gt;Häll aldrig olja i din grannes parabolantenn&lt;&#x2F;em&gt;, &lt;em&gt;Never pour oil in your neighbor&#x27;s satellite dish&lt;&#x2F;em&gt;,
funnier words have never been spoken by anyone, let alone a computer — signed twelve-year-old me.
We named it &lt;em&gt;Gammalt Kinesiskt Ordspråk&lt;&#x2F;em&gt;: &lt;em&gt;Old Chinese Proverb&lt;&#x2F;em&gt;. It was promptly
shortened to GKO. We expanded the list of sentences over time but it was hard to
recreate the kick of the first few days. I&#x27;m a bit sad that someone didn&#x27;t realize that
saving the source code was worthwhile. Years later, around 96-97 I would get my
own PC, and after crashing it a few times I started a somewhat rigorous backup
scheme. First on 3.5-inch floppies and then on CD-ROMs.&lt;&#x2F;p&gt;
&lt;p&gt;Much later I got to hear that ideas are worthless. In 1994 no one was asking
us to create something that didn&#x27;t exist before, and the act of creation was and
is a wonderful thing. There are a lot of caveats, of course, but they seem self-evident.
The list of caveats will vary over time as well. The one that finds this a week, a year,
a decade, or more from now will have to apply the ethics of their respective times.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Gammalt Kinesiskt Ordspråk&lt;&#x2F;em&gt; started me on a long path of programming. I&#x27;m still
programming, and I still think it&#x27;s a lot of fun to be in the creative state of mind.
Taking ideas and making them into something tangible.&lt;&#x2F;p&gt;
&lt;p&gt;I have one more game I want to mention. Years before, I had the pleasure to play
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;SkiFree&quot;&gt;SkiFree&lt;&#x2F;a&gt; on my uncle&#x27;s monochrome
(red monochrome to be exact) &quot;portable computer&quot;. It was the size of your regular pizza-box
computer, required to be plugged into the wall to run, and had a very small LCD screen
built-in that you could lift out of the chassis. SkiFree is the game where you
ski downhill trying to jump over things and avoid obstacles, and you can do that
for as long as you like, or at least until the &lt;em&gt;Yeti&lt;&#x2F;em&gt; gets you.&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;ski_free.png&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;ski_free.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I still have a lot of memories of computing, probably many more than I will ever
have the energy to write about, but I hope I&#x27;ll return to the world of Stefan,
Paul, Ricardo, Carlos, and all of the other kids that went through the motions of
grades one through eight in Rosengård, Malmö, Sweden during the 80&#x27;s and 90&#x27;s.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Easily manage a chain of commits and their respective Pull Requests using git</title>
        <published>2021-11-08T00:00:00+00:00</published>
        <updated>2021-11-08T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/dependent-git-commits/"/>
        <id>https://zkc.se/blog/dependent-git-commits/</id>
        <content type="html" xml:base="https://zkc.se/blog/dependent-git-commits/">&lt;p&gt;This blog post was originally posted as a
&lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;61897602&#x2F;how-can-i-easily-manage-a-chain-of-commits-and-their-respective-pull-requests-us&quot;&gt;Q&amp;amp;A style answer on Stack Overflow&lt;&#x2F;a&gt;.
I recently edited the answer on Stack Overflow, with a slightly improved method,
so I felt like sharing it on my personal blog would be beneficial too.&lt;&#x2F;p&gt;
&lt;p&gt;(A Q&amp;amp;A style question on Stack Overflow is a question that you answer at the same time as you ask the question,
kind of like writing a blog post but right on Stack Overflow instead, under the guise of a question)&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h1 id=&quot;the-original-question&quot;&gt;The original question&lt;&#x2F;h1&gt;
&lt;blockquote&gt;
&lt;p&gt;I have chain of commits, each commit with its own branch, but they are all part of the same feature.&lt;&#x2F;p&gt;
&lt;p&gt;When I get comments on my Pull Requests (GitHub&#x2F;Bitbucket&#x2F;Whatever) I want all the following Pull Requests to get my fixes with as little manual work as possible.&lt;&#x2F;p&gt;
&lt;p&gt;In this scenario no one else is using my branches so I am free to force push to them if I need to.&lt;&#x2F;p&gt;
&lt;p&gt;I used to work at a major Android device manufacturer, and I loved the way Gerrit handled this with ease. Gerrit isn&#x27;t widely used outside of Android though so I want to find a good workflow that covers the 90% case, even in a large-ish team.&lt;&#x2F;p&gt;
&lt;p&gt;I usually solve this in one of two ways:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Do fixup commits, push them to their respective branch and then merge upwards however many times is needed until all the branches have all the fixes. This can be a lot of work, depending on how long the chain of commits is.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Do a &lt;code&gt;git rebase -i&lt;&#x2F;code&gt; and then do &lt;code&gt;git push origin &amp;lt;sha&amp;gt;:remote-branch&lt;&#x2F;code&gt; as many times as needed. This is also a lot of work, and afterwards there is a mismatch between the local and remote branches (which can be remedied by &lt;code&gt;git reset&lt;&#x2F;code&gt; but that adds even more work). This can also be error prone since it&#x27;s easy to misspell shas or branch names.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Is there an easier way of managing a chain of commits that are destined for Pull Requests?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;the-answer&quot;&gt;The answer&lt;&#x2F;h1&gt;
&lt;p&gt;I found a really good method for handling this on [William Chargin&#x27;s blog][https:&#x2F;&#x2F;wchargin.github.io&#x2F;posts&#x2F;managing-dependent-pull-requests&#x2F;], for what he calls &quot;Dependent Pull Requests&quot; which is a good way of describing it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Edit 2021-11-08&lt;&#x2F;strong&gt;: I have started using &lt;code&gt;git notes&lt;&#x2F;code&gt; for managing the &lt;code&gt;remote-branch&lt;&#x2F;code&gt; instead of adding it to the commit message. This makes the git commit message history much cleaner.&lt;&#x2F;p&gt;
&lt;p&gt;I have modified the original script, and since it uses an MIT license I have followed the guidelines and added my name as well.&lt;&#x2F;p&gt;
&lt;p&gt;The following modifications were made to the script:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Make it compatible with macOS by using a regexp that works on the macOS version of &lt;code&gt;sed&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Use the git notes command &lt;code&gt;git notes show&lt;&#x2F;code&gt; to get the remote-branch message instead of &lt;code&gt;git show&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Use a more generic label for the branch name matcher.&lt;&#x2F;li&gt;
&lt;li&gt;Default to an empty branch prefix.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;preface&quot;&gt;Preface&lt;&#x2F;h1&gt;
&lt;p&gt;To follow along in this answer you need to be reasonably skilled using git, and you have probably used &lt;code&gt;git rebase -i&lt;&#x2F;code&gt; enough to be comfortable with it.&lt;&#x2F;p&gt;
&lt;p&gt;If this is your first git rodeo, it might be wise to get some experience and come back another time.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;potential-drawbacks&quot;&gt;Potential drawbacks&lt;&#x2F;h1&gt;
&lt;p&gt;The method gets you close to the convenience of Gerrit, as long as you are aware of the potential drawbacks:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Force pushing isn&#x27;t always a good strategy.&lt;&#x2F;li&gt;
&lt;li&gt;All the updated branches will have their tests run again if you have CI (which is good, but also bad if your CI is expensive).&lt;&#x2F;li&gt;
&lt;li&gt;Watch out for remote branch name collision.&lt;&#x2F;li&gt;
&lt;li&gt;Some reviewers prefer commit-by-commit changes.&lt;&#x2F;li&gt;
&lt;li&gt;Probably other stuff too!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;method&quot;&gt;Method&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;&#x2F;h2&gt;
&lt;p&gt;For this method to work you must configure git to use these settings
(I like to configure it globally, but you can remove &lt;code&gt;--global&lt;&#x2F;code&gt; if you want it only for a specific repository)&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; config&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;global&lt;&#x2F;span&gt; notes.rewriteRef refs&#x2F;notes&#x2F;commits&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; config&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;global&lt;&#x2F;span&gt; notes.rewrite.amend true&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; config&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;global&lt;&#x2F;span&gt; notes.rewrite.rebase true&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;branch-strategy&quot;&gt;Branch strategy&lt;&#x2F;h2&gt;
&lt;p&gt;All your commits live on a single local branch which does not necessarily need to be pushed except if you want to keep a remote backup while your work is in progress (recommended).&lt;&#x2F;p&gt;
&lt;p&gt;Add as many commits you need to build your logical chain of dependent pull requests. I once used a chain of 11 commits.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; git log&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;oneline&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;aaaaaaa3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; (HEAD -&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; my-backup-branch&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Feature:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; Step 3&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;aaaaaaa2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; Feature: Step 2&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;aaaaaaa1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; Feature: Step 1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;aaaaaaaa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; (origin&#x2F;master&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Probably&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; some merge commit&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;manage-your-commits&quot;&gt;Manage your commits&lt;&#x2F;h2&gt;
&lt;p&gt;For &lt;strong&gt;each commit in the chain&lt;&#x2F;strong&gt; you must add a &lt;code&gt;git notes&lt;&#x2F;code&gt; that tells the script which remote branch that it should be pushed to. The remote branch does not need to exist. Add the &lt;code&gt;git notes&lt;&#x2F;code&gt; when creating
the commit or at any time before pushing your changes.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; git notes add&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;m&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;remote-branch: my-feature-step-3&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; git log&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;commit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3 (HEAD -&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; my-backup-branch&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Author:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; Erik Zivkovic &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;...&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Date:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;   Fri May 19 19:47:53 2020 +0200&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Feature:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; Step 3&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Notes:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;remote-branch:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; my-feature-step-3&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;[...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; more commits]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;ready-for-pushing-and-creating-updating-prs&quot;&gt;Ready for pushing and creating&#x2F;updating PRs&lt;&#x2F;h2&gt;
&lt;p&gt;I would recommend that you do NOT do a &lt;code&gt;git rebase -i&lt;&#x2F;code&gt; fixup AND use the script at the same time. Perform any changes and then test your chain of commits first, then you push. That is the way I recommend doing it.&lt;&#x2F;p&gt;
&lt;p&gt;Make sure that all the commits in the chain have a unique &lt;code&gt;remote-branch: &amp;lt;branch name&amp;gt;&lt;&#x2F;code&gt; line!&lt;&#x2F;p&gt;
&lt;p&gt;To finish it all off call &lt;code&gt;git rebase -i&lt;&#x2F;code&gt; with the &lt;code&gt;-x &quot;git push-to-target&quot;&lt;&#x2F;code&gt; parameter.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; git rebase&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;i&lt;&#x2F;span&gt; aaaaaaaa&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;x&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;git push-to-target&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;[This&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; will open your chosen git editor with a git rebase window]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;pick&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; aaaaaaa1 Feature: Step 1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-exec z-shell&quot;&gt;exec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; git push-to-target&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;pick&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; aaaaaaa2 Feature: Step 2&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-exec z-shell&quot;&gt;exec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; git push-to-target&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;pick&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; aaaaaaa3 Feature: Step 3&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-exec z-shell&quot;&gt;exec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; git push-to-target&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The magic, of course, is that &lt;code&gt;git rebase&lt;&#x2F;code&gt; stops after each &lt;code&gt;pick&lt;&#x2F;code&gt; command and runs the &lt;code&gt;exec&lt;&#x2F;code&gt; command, which:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Reads the &lt;code&gt;git notes&lt;&#x2F;code&gt; message.&lt;&#x2F;li&gt;
&lt;li&gt;Finds the &lt;code&gt;remote-branch&lt;&#x2F;code&gt; line.&lt;&#x2F;li&gt;
&lt;li&gt;Force Pushes (&lt;code&gt;--force-with-lease&lt;&#x2F;code&gt;) the current &lt;code&gt;HEAD&lt;&#x2F;code&gt; (which points to the &lt;code&gt;pick&lt;&#x2F;code&gt;) to &lt;code&gt;remote-branch&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;If the remote branch does not exist, it is created. Otherwise it is updated.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If everything worked, you should see updated remote branches in git log.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; git log&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;oneline&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;aaaaaaa3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; (HEAD -&lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; my-backup-branch, origin&#x2F;my-feature-step-3&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Feature:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; Step 3&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;aaaaaaa2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; (origin&#x2F;my-feature-step-2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Feature:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; Step 2&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;aaaaaaa1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; (origin&#x2F;my-feature-step-1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Feature:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; Step 1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;aaaaaaaa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; (origin&#x2F;master&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Probably&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; some merge commit&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;pull-requests&quot;&gt;Pull Requests&lt;&#x2F;h1&gt;
&lt;p&gt;If you did not have any Pull Requests, now is the time to create them using whatever service you have (Github, Bitbucket, ...), and have the branches point to each other in order.&lt;&#x2F;p&gt;
&lt;p&gt;If the Pull Requests already existed, they should now be updated and tests running again (if you have CI).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;more-commits-handling-review-comments-etc&quot;&gt;More commits, handling review comments, etc.&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;If you get review comments, just &lt;code&gt;git rebase -i&lt;&#x2F;code&gt; and do any fixups.&lt;&#x2F;li&gt;
&lt;li&gt;If you do more feature work, just keep adding commits on top and add unique &lt;code&gt;remote-branch:&lt;&#x2F;code&gt; labels in a &lt;code&gt;git notes&lt;&#x2F;code&gt; for each commit.&lt;&#x2F;li&gt;
&lt;li&gt;Finally push again with &lt;code&gt;git rebase -i &amp;lt;sha&amp;gt; -x &quot;git push-to-target&quot;&lt;&#x2F;code&gt; (after testing your changes locally, should go without saying).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;cleanup&quot;&gt;Cleanup&lt;&#x2F;h1&gt;
&lt;p&gt;When everything is merged, you might want to delete your remote backup branch.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;tips&quot;&gt;Tips&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;Tip: Add the script to your path, then you can use it as &lt;code&gt;git push-to-target&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Tip: &lt;code&gt;git config --global alias.ptt push-to-target&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Tip: &lt;code&gt;git rebase -i &amp;lt;SHA&amp;gt; -x &quot;git ptt&quot;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;additional-notes&quot;&gt;Additional Notes&lt;&#x2F;h1&gt;
&lt;p&gt;Note: I have contacted the developer by e-mail to inform him of my changes and ask what he thinks of them, but I have not yet received an answer.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;script&quot;&gt;Script&lt;&#x2F;h1&gt;
&lt;p&gt;The script &lt;em&gt;should&lt;&#x2F;em&gt; work on Linux&#x2F;macOS&#x2F;WSL. I have only tested it on macOS.&lt;&#x2F;p&gt;
&lt;p&gt;The majority of this script was written by William Chargin, I just made it work on macOS and made some minor changes that seemed good to me.&lt;&#x2F;p&gt;
&lt;p&gt;File: &lt;code&gt;git-push-to-target&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;!&#x2F;bin&#x2F;sh&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; git-push-to-target: Push this commit to a branch specified in its&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; commit description.&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Copyright (c) 2017 William Chargin. Released under the MIT license.&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Copyright (c) 2020 Erik Zivkovic.&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Originally https:&#x2F;&#x2F;wchargin.github.io&#x2F;posts&#x2F;managing-dependent-pull-requests&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Usage: For a commit add a git notes line `remote-branch: branchname` then in a rebase do `exec git push-to-target`&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Tip: Add this file to your path, then you can use it as git push-to-target&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Tip: git config --global alias.ptt push-to-target&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Tip: git rebase -i &amp;lt;SHA&amp;gt; -x &amp;quot;git ptt&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-set z-shell&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;eu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;DIRECTIVE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;remote-branch&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;  &lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; any regex metacharacters should be escaped&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;BRANCH_PREFIX&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;           &lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Add a branch prefix if needed&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-shell&quot;&gt;target_branch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-braces z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;    &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;directive&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;        &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; notes show HEAD &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;&#x2F;span&gt;        &lt;span class=&quot;z-keyword z-operator z-logical z-pipe z-shell&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;n&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;s&#x2F;^&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;DIRECTIVE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;: \([A-Za-z0-9_.-]*\)$&#x2F;\1&#x2F;p&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;&#x2F;span&gt;        &lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-if z-shell&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-test z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;z&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;directive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-test z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-then z-shell&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;        &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-printf z-shell&quot;&gt;printf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-file-descriptor z-shell&quot;&gt;2&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;error: missing &amp;quot;%s&amp;quot; directive\n&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;DIRECTIVE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;        &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-keyword z-control z-flow z-return z-shell&quot;&gt;return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; 1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-end z-shell&quot;&gt;fi&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-if z-shell&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-test z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-printf z-shell&quot;&gt;printf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;%s\n&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;directive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-pipe z-shell&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;wc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;gt&lt;&#x2F;span&gt; 1 &lt;span class=&quot;z-support z-function z-test z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-then z-shell&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;        &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-printf z-shell&quot;&gt;printf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-file-descriptor z-shell&quot;&gt;2&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;error: multiple &amp;quot;%s&amp;quot; directives\n&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;DIRECTIVE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;        &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-keyword z-control z-flow z-return z-shell&quot;&gt;return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; 1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-end z-shell&quot;&gt;fi&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-printf z-shell&quot;&gt;printf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;%s%s\n&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;BRANCH_PREFIX&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;directive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-braces z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-shell&quot;&gt;main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-braces z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-if z-shell&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-test z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;:-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-shell&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;--query&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-test z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-then z-shell&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;        &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;target_branch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;        &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-keyword z-control z-flow z-return z-shell&quot;&gt;return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-end z-shell&quot;&gt;fi&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;    &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;remote&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;:-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;origin&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;    &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;branch&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-command z-parens z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;target_branch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-set z-shell&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; push&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;force-with-lease&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;remote&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; HEAD:refs&#x2F;heads&#x2F;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;branch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-braces z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language z-shell&quot;&gt;@&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>An overview of the concepts in async &#x2F; await in Rust</title>
        <published>2021-03-16T00:00:00+00:00</published>
        <updated>2021-03-16T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/rust-async-await/"/>
        <id>https://zkc.se/blog/rust-async-await/</id>
        <content type="html" xml:base="https://zkc.se/blog/rust-async-await/">&lt;p&gt;Async &#x2F; await in Rust promises to simplify concurrent code, and to allow a large
number of concurrent tasks to be scheduled at the same time — with less overhead
than the same number of OS Threads would require.&lt;&#x2F;p&gt;
&lt;p&gt;In general, async &#x2F; await lets you write code that avoids &quot;callback hell&quot;, in
favor of a linear style similar to &lt;em&gt;blocking&lt;&#x2F;em&gt; code while still letting other
tasks progress during awaits.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Any minimal async &#x2F; await code in Rust is made up of at least the following
pieces:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;An executor&lt;&#x2F;li&gt;
&lt;li&gt;A Future with an internal state machine&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But before we dig into those, let&#x27;s see what operating system threads are all
about.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;operating-system-threads&quot;&gt;Operating System Threads&lt;&#x2F;h1&gt;
&lt;p&gt;Rust has a really good concurrency story. For me it&#x27;s probably the feature I
like the most. Rust prevents you from making a lot of mistakes, mistakes that
are easy to make in most other imperative programming languages.&lt;&#x2F;p&gt;
&lt;p&gt;Each new thread allocates a stack, with an OS-defined size. On linux, and other
operating systems with virtual memory, the program won&#x27;t actually use up
physical memory even though 1 MiB is &quot;allocated&quot; to the thread when it starts.
That way you can start thousands of threads without trouble.&lt;&#x2F;p&gt;
&lt;p&gt;The problems start when the OS needs to context switch between threads, and a
lot of CPU time is wasted during signalling between the kernel and the program.&lt;&#x2F;p&gt;
&lt;p&gt;Enter async &#x2F; await.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;async-await&quot;&gt;Async &#x2F; await&lt;&#x2F;h1&gt;
&lt;p&gt;Since async &#x2F; await tasks don&#x27;t require OS signalling to context switch, the
theory is that you can have a lot more of them, and they can make your program
execute faster than a program with the same number of operating system threads.&lt;&#x2F;p&gt;
&lt;p&gt;The two most important parts of the async &#x2F; await story are the executor, and
the state machine wrapped in a future.&lt;&#x2F;p&gt;
&lt;p&gt;A future is a computation that will finish and yield a result at some later,
unknown time. Futures don&#x27;t have to be executed in an async &#x2F; await context,
they are a tool that is available even in the absence of async &#x2F; await.&lt;&#x2F;p&gt;
&lt;p&gt;An executor is the thing that takes the state machine futures and drives them to
completion.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;executors&quot;&gt;Executors&lt;&#x2F;h2&gt;
&lt;p&gt;Rust purposefully doesn&#x27;t include an async &#x2F; await executor in the standard
library. There might be executors that are good for small embedded devices, and
other executors that are good for large servers.&lt;&#x2F;p&gt;
&lt;p&gt;For the sake of argument, I will pick the very
popular &lt;a href=&quot;https:&#x2F;&#x2F;tokio.rs&#x2F;&quot;&gt;tokio&lt;&#x2F;a&gt; executor and describe how it works at a high
level.&lt;&#x2F;p&gt;
&lt;p&gt;Tokio in multi-threading mode starts as many operating system threads as there
are cores on the given machine, on my computer that would be 8 logical cores
which translates to 8 threads.&lt;&#x2F;p&gt;
&lt;p&gt;The &quot;low&quot; number of threads means that if there are 8 currently running tasks,
one in each thread, and all of them are blocking (e.g. stupidly
calling &lt;code&gt;std::thread::sleep&lt;&#x2F;code&gt;), then it would not be possible for any other tasks
to make progress and my hypothetical web server would be frozen.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s why Alice Ryhl, one of the maintainers of tokio, says that a task should
&lt;a href=&quot;https:&#x2F;&#x2F;ryhl.io&#x2F;blog&#x2F;async-what-is-blocking&#x2F;&quot;&gt;not execute for more than 100 microseconds&lt;&#x2F;a&gt;
between two &lt;code&gt;.await&lt;&#x2F;code&gt;s.&lt;&#x2F;p&gt;
&lt;p&gt;If a task needs to run for a longer time, then it should be spawned using e.g.
&lt;code&gt;tokio::task::spawn_blocking&lt;&#x2F;code&gt; which will run on a separate OS thread, or just
run the code on an os thread directly using &lt;code&gt;std::thread::spawn&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;futures-and-state-machines&quot;&gt;Futures and state machines&lt;&#x2F;h2&gt;
&lt;p&gt;An async function looks something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;async &lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;my_task&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; more code
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;async fn&lt;&#x2F;code&gt; is just sugar for transforming the return parameter into a &lt;code&gt;Future&lt;&#x2F;code&gt;
that is implemented as an anonymous struct that can&#x27;t be named by anyone but the
compiler.&lt;&#x2F;p&gt;
&lt;p&gt;The resulting high level code transform (ignoring the anonymous struct) would be
something like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;my_task&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Future&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;Output = &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; A state machine that when driven by the executor
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-rust&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; finally yields an Option&amp;lt;String&amp;gt;.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When compiling an async function, the Rust compiler will build a state machine
of the states the function can be in during its asynchronous life cycle. The two
obvious states are &lt;code&gt;Initialized&lt;&#x2F;code&gt; and &lt;code&gt;Complete&lt;&#x2F;code&gt;, but between those any number of
states for different code branches can be generated.&lt;&#x2F;p&gt;
&lt;p&gt;As soon as you call &lt;code&gt;.await&lt;&#x2F;code&gt; on the async function, or enqueue it as a new task
using the regular non-blocking &lt;code&gt;tokio::spawn&lt;&#x2F;code&gt; method, the state machine will
start moving forward. In Rust&#x27;s async &#x2F; await model, this is called polling.&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;div class=&quot;note-title&quot;&gt;Important note about Futures in Rust&lt;&#x2F;div&gt;
    &lt;p&gt;Unlike many other programming languages that have types named &lt;code&gt;Future&lt;&#x2F;code&gt;, Rust
does NOT start executing a &lt;code&gt;Future&lt;&#x2F;code&gt; automatically. The &lt;code&gt;Future&lt;&#x2F;code&gt; must be driven
forward by something. The most common &quot;something&quot; in async &#x2F; await is the
Executor. To start driving a future the easiest way is to &lt;code&gt;.await&lt;&#x2F;code&gt; it.
Just do &lt;code&gt;my_task().await&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h2 id=&quot;what-about-the-stack&quot;&gt;What about the stack?&lt;&#x2F;h2&gt;
&lt;p&gt;Regular functions require a stack. In async &#x2F; await, the Rust compiler will
generate a state machine that is capable of storing the correct amount of data
by encoding every possible combination of stack allocations in the form of an
enum. Interestingly this includes the &lt;em&gt;entire&lt;&#x2F;em&gt; call graph of the async function.
That is why just like recursive types are currently not possible without some
hand waving in Rust, recursive &lt;code&gt;async fn&lt;&#x2F;code&gt; is not possible either - unless you
&lt;code&gt;Box&lt;&#x2F;code&gt; the recursive call. Boxing the call places it on the heap, in essence
&lt;a href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;futures-and-segmented-stacks&#x2F;&quot;&gt;turning it to its own private little &quot;stack&quot; segment allocation&lt;&#x2F;a&gt;
.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;when-to-use-async-await&quot;&gt;When to use async &#x2F; await&lt;&#x2F;h1&gt;
&lt;p&gt;Do use async &#x2F; await when&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You have to support many concurrent tasks.&lt;&#x2F;li&gt;
&lt;li&gt;You have tasks that call out to non-blocking async functions, e.g. HTTP-calls.&lt;&#x2F;li&gt;
&lt;li&gt;You have an interactive system that gets continuous input while serving output.&lt;&#x2F;li&gt;
&lt;li&gt;You can &quot;guarantee&quot; that your code executes for at most 100 microseconds between &lt;code&gt;.await&lt;&#x2F;code&gt;s.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Do NOT use async &#x2F; await when&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You need to compute something complex &#x2F; blocking as fast as possible&lt;&#x2F;li&gt;
&lt;li&gt;You only have a few well known tasks that are independent&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;alternatives&quot;&gt;Alternatives&lt;&#x2F;h1&gt;
&lt;p&gt;Unless you fulfill the criteria for async &#x2F; await, use something else:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Raw operating system threads &lt;code&gt;std::thread::spawn&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;A data-parallelism library like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rayon-rs&#x2F;rayon&quot;&gt;rayon&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;I&#x27;m sure there are more options out there.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Strings in Rust</title>
        <published>2021-03-14T00:00:00+00:00</published>
        <updated>2021-03-14T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/rust-strings/"/>
        <id>https://zkc.se/blog/rust-strings/</id>
        <content type="html" xml:base="https://zkc.se/blog/rust-strings/">&lt;p&gt;During the last 20 years I have used a number of garbage collected and reference
counted programming languages. All of them have a single type for representing
strings. Rust has two types of strings that can be stored in three different
ways.&lt;&#x2F;p&gt;
&lt;p&gt;I want to shortly illustrate how Rust&#x27;s strings interact with the heap, with the
stack, and with the data segment of your binary, as well as shortly explain what
those things are.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Java, Swift, TypeScript, and Go all have string types that make it irrelevant if
they&#x27;re stored on the stack or on the heap. A Java string is always heap
allocated, while a Go string may be stack or heap allocated. The point is that
you don&#x27;t need to know: the way you use the type doesn&#x27;t change.&lt;&#x2F;p&gt;
&lt;p&gt;Rust doesn&#x27;t work quite that way. In general, the programmer needs to choose
between types that store data either on the stack or on the heap. The choice
is generally speaking a trade-off between speed and versatility.&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;div class=&quot;note-title&quot;&gt;Scope&lt;&#x2F;div&gt;
    &lt;p&gt;Please note that this post does not touch upon the topics of UTF8, UTF8 validity,
and so on. Neither does it talk about lifetimes, except for &lt;code&gt;&#x27;static&lt;&#x2F;code&gt;, which is
not explained further. This post basically glosses over everything that is not
needed to understand &lt;code&gt;String&lt;&#x2F;code&gt; or &lt;code&gt;str&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;We need to take a small detour.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;stack-and-heap&quot;&gt;Stack and heap&lt;&#x2F;h1&gt;
&lt;p&gt;This is a conceptual view of the stack and heap parts of program memory.
This is probably a virtual memory if you&#x27;re on a laptop computer or physical
memory if you&#x27;re on a small embedded hardware without an operating system.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                  A view of program memory in a made up 16 bit computer 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; low memory addresses   ======================================= addr[0x00F0] 
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                        |               HEAP                  |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                        | typically grows towards higher addr |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                        |                 |                   |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                        |                 ˇ                   |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                        |&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;|
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                        |                 ^                   |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                        |                 |                   |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                        | typically grows towards lower addr  |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                        |               STACK                 |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; high memory addresses  ======================================= addr[0xFFFF] 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The stack and heap memory is structured in a way that they grow towards each
other. In my examples I use a made up 16 bit memory architecture. That means
that pointers are 16 bits and registers are 16 bits as well.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                        PROGRAM                      MEMORY
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;use std::str;                           =====================================
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fn main() {                             |             HEAP                  |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &#x2F;&#x2F; A stack allocated i16            |                                   |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;+-- let x: i16 = 5;                     |                                   |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;|                                       | addr[0x00F0] &amp;lt;-----+              |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;|   &#x2F;&#x2F; A heap allocated i16             | type: i16          |              |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;|   let y: Box&amp;lt;i16&amp;gt; = Box::new(5);      | value: 5           |              |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;|       |                               |                    |              |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;|       |                               |&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;|&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;|
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;|       |                               | addr[0xFFE0]       |              |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;|       |                               | type: Box&amp;lt;i16&amp;gt;     |              |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;|       +-------------------------------&amp;gt; value: 0x00F0 -----+              |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;|                                       |                                   |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;|                                       | addr[0xFFF0]                      |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;|                                       | type: i16                         |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;+---------------------------------------&amp;gt; value: 5                          |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                                        |             STACK                 |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}                                       =====================================
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The program above illustrates the difference between putting something on the
stack, which is immediately available to the function, since in some sense the
current stack frame &lt;em&gt;is&lt;&#x2F;em&gt; the function. When something is put on the heap, we say
that it&#x27;s &lt;em&gt;boxed&lt;&#x2F;em&gt;. In this case the &lt;code&gt;Box&lt;&#x2F;code&gt; is essentialy just a stack allocated
struct, that internally holds a pointer to the heap, where the actual data is
stored. Illustrated by the &lt;code&gt;-&amp;gt;&lt;&#x2F;code&gt; arrows above.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;three-types-of-string-storage&quot;&gt;Three types of string storage&lt;&#x2F;h1&gt;
&lt;p&gt;A string in Rust can be stored in one of three ways:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;On the heap&lt;&#x2F;li&gt;
&lt;li&gt;On the stack&lt;&#x2F;li&gt;
&lt;li&gt;In the &lt;code&gt;data&lt;&#x2F;code&gt; segment of the application binary&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We need one more detour.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;application-binary-segments&quot;&gt;Application binary segments&lt;&#x2F;h1&gt;
&lt;p&gt;The segments in a binary are often illustrated like this, please note that
this is &lt;em&gt;after&lt;&#x2F;em&gt; loading the binary file from disk into main memory: the stack
and heap segments aren&#x27;t stored in the binary on disk.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;text&lt;&#x2F;code&gt; segment actually contains the compiled machine code, and the &lt;code&gt;data&lt;&#x2F;code&gt;
segment contains application data found by the compiler while compiling.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                                     SEGMENTS
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      low mem =============================================================
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              |                       .text                               |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              |                contains machine code                      |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              =============================================================
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              |                        .data                              |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              | contains data known to the app binary at compile time     |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              =============================================================
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; addr[0x00F0] |                         HEAP                              |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              | contains dynamically allocated data created at run time   |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              | * data that lives &amp;quot;much&amp;quot; longer than one function         |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              | * data that is too big for the stack                      |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              | * data that must live behind a pointer, i.e. unknown size |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              |&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              |                         STACK                             |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              | contains memory allocated by functions at run time        |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              | * data with a known size                                  |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; addr[0xFFFF] | * data that mostly does not outlive the function itself   |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     high mem =============================================================
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this case, the string &lt;code&gt;&quot;abc&quot;&lt;&#x2F;code&gt; has been found by the compiler and put in the
&lt;code&gt;data&lt;&#x2F;code&gt; segment. When our function is run, the x variable points directly into
the &lt;code&gt;data&lt;&#x2F;code&gt; segment, at the address where &lt;code&gt;&quot;abc&quot;&lt;&#x2F;code&gt; starts. Since the &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt; also
stores a length, the program will only read three characters when run.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;two-types-of-strings&quot;&gt;Two types of strings&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;string&quot;&gt;String&lt;&#x2F;h2&gt;
&lt;p&gt;The first of the two types is &lt;code&gt;String&lt;&#x2F;code&gt; which is the heap allocated, growable,
string type. It&#x27;s growable, which means that unlike Java it&#x27;s possible to change
the string as long as there is enough room left. If there isn&#x27;t enough room, it
will expand its size automatically.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;code&gt;String&lt;&#x2F;code&gt; may be owned, something like &lt;code&gt;let x: String = String::from(&quot;abc&quot;)&lt;&#x2F;code&gt;,
or referenced &lt;code&gt;fn takes_string_ref(x: &amp;amp;mut String)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;String&lt;&#x2F;code&gt; is implemented as a wrapper around &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;str&quot;&gt;str&lt;&#x2F;h2&gt;
&lt;p&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.str.html&quot;&gt;str&lt;&#x2F;a&gt; is simple, but also
very very complicated. You can either accept the standard explanation without
further questioning it, or you can read my take below 👇.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;code&gt;str&lt;&#x2F;code&gt; is a &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nomicon&#x2F;exotic-sizes.html&quot;&gt;Dynamically Sized Type&lt;&#x2F;a&gt;.
Furthermore, it is a primitive type, and unlike &lt;code&gt;String&lt;&#x2F;code&gt; you can&#x27;t find it in the
standard library since it&#x27;s a compiler internal type.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;str&lt;&#x2F;code&gt; is callad a &quot;string slice&quot;. Unlike most other types you can NOT get an
instance of a raw &lt;code&gt;str&lt;&#x2F;code&gt;. It is is most often seen with  its buddy Mr. Ampersand,
as in: &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt;. Other possibilities are &lt;code&gt;Rc&amp;lt;str&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;Box&amp;lt;str&amp;gt;&lt;&#x2F;code&gt;. The use case
for &lt;code&gt;Box&amp;lt;str&amp;gt;&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;users.rust-lang.org&#x2F;t&#x2F;use-case-for-box-str-and-string&#x2F;8295&#x2F;4&quot;&gt;is that it doesn&#x27;t contain&lt;&#x2F;a&gt;
the &lt;code&gt;capacity&lt;&#x2F;code&gt; field of &lt;code&gt;String&lt;&#x2F;code&gt;, so it takes up less memory.&lt;&#x2F;p&gt;
&lt;p&gt;Just like a &lt;code&gt;&amp;amp;i64&lt;&#x2F;code&gt; is a reference to an actual &lt;code&gt;i64&lt;&#x2F;code&gt;, an &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt; is a reference.
But a reference to what? An &lt;code&gt;i64&lt;&#x2F;code&gt; can be stack allocated, so the &lt;code&gt;&amp;amp;i64&lt;&#x2F;code&gt; is
a pointer to some other place in the stack. A &lt;code&gt;Box&amp;lt;i64&amp;gt;&lt;&#x2F;code&gt; is heap allocated,
and you can get a &lt;code&gt;&amp;amp;i64&lt;&#x2F;code&gt; reference to that one, too.&lt;&#x2F;p&gt;
&lt;p&gt;But the &lt;code&gt;&amp;amp;i64&lt;&#x2F;code&gt; isn&#x27;t just a pointer, it has an implicit size too.
The compiler knows that since the type is 64 bits, it knows how much data to read
when reading the pointed-to reference. But what size is an &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;div class=&quot;note-title&quot;&gt;Aside&lt;&#x2F;div&gt;
    &lt;p&gt;Since the Rust 2018 edition, we need to put references to trait objects,
which have an unknown compile-time size,
behind the &lt;code&gt;dyn&lt;&#x2F;code&gt; keyword: &lt;code&gt;&amp;amp;dyn MyTrait&lt;&#x2F;code&gt;. That way the compiler knows to
generate a vtable (a table of function pointers) that the runtime can use to find
the functions of the actual underlying struct. &lt;code&gt;dyn MyTrait&lt;&#x2F;code&gt; is a Dynamically
Sized Type too, and it also has to be pointed to by a &lt;code&gt;&amp;amp;&lt;&#x2F;code&gt; reference, or be
boxed somehow: e.g. &lt;code&gt;Box&amp;lt;dyn MyTrait&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;But what about &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt;? A pointer to a string isn&#x27;t enough, the computer must know
how many bytes of data to read. Fortunately, it does contain the length too,
just as a &lt;code&gt;&amp;amp;[u8]&lt;&#x2F;code&gt; reference knows how many bytes to read behind the pointer.&lt;&#x2F;p&gt;
&lt;p&gt;I think there are nice similarities between how the lack of a known compile
time size of a &lt;code&gt;str&lt;&#x2F;code&gt; forces the runtime code to store the runtime length together
with the pointer to the actual data, and how references to trait objects need to
store a pointer to a vtable to work properly. They&#x27;re both Dynamically Sized Types
too.&lt;&#x2F;p&gt;
&lt;p&gt;So a &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt; is basically &lt;code&gt;type str { pointer: *const u8, len: usize }&lt;&#x2F;code&gt;.
Maybe it would have been less confusing if &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt; was presented another way?
What about &lt;code&gt;&amp;amp;str[u8; ?]&lt;&#x2F;code&gt;. &lt;em&gt;No that&#x27;s terrible, never write that again.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The way &lt;code&gt;str&lt;&#x2F;code&gt; is presented by the standard documentation leads me to believe
that the &lt;code&gt;&amp;amp;&lt;&#x2F;code&gt; in &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt; is the actual pointer, and that the &lt;code&gt;str&lt;&#x2F;code&gt; part is just
a placeholder for &lt;code&gt;len: usize&lt;&#x2F;code&gt; and an implicit data type &lt;code&gt;u8&lt;&#x2F;code&gt;. But that&#x27;s
maybe wrong, probably?&lt;&#x2F;p&gt;
&lt;p&gt;My personal take is that &lt;code&gt;str&lt;&#x2F;code&gt; &lt;em&gt;could&lt;&#x2F;em&gt; have been a standard library type, or
a &lt;code&gt;struct&lt;&#x2F;code&gt; instead, and used without it being a reference &quot;&lt;code&gt;&amp;amp;&lt;&#x2F;code&gt;&quot;. That way
the pointer field could have been seen in code, and all would have been well.
But since Rust is Rust, and &lt;code&gt;&amp;amp;&lt;&#x2F;code&gt; means shared reference, all the standard rules
around lifetimes and sharing kick in. That results in an overall nicer experience.
However, I find the lack of a deeper explanation or what-if explorations unsatisfying.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;three-types-of-string-storage-again&quot;&gt;Three types of string storage, again&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;heap&quot;&gt;Heap&lt;&#x2F;h2&gt;
&lt;p&gt;The standard library &lt;code&gt;String&lt;&#x2F;code&gt; is always heap allocated, but it can interact with
&lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt; in two ways&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Anything that takes a &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt; can take a reference to a &lt;code&gt;String&lt;&#x2F;code&gt; and it will just work&lt;&#x2F;li&gt;
&lt;li&gt;We can get a &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt; sub-slice of a &lt;code&gt;String&lt;&#x2F;code&gt; by doing &lt;code&gt;&amp;amp;my_string[1..3]&lt;&#x2F;code&gt; which for
the &lt;code&gt;String&lt;&#x2F;code&gt; &lt;code&gt;&quot;abcd&quot;&lt;&#x2F;code&gt; would be &lt;code&gt;&quot;bcd&quot;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Neither (1) nor (2) above need to allocate any extra memory except for the size
of the pointer and the length.&lt;&#x2F;p&gt;
&lt;p&gt;Here we allocate an empty &lt;code&gt;String&lt;&#x2F;code&gt; on the heap, and our handle to it, called &lt;code&gt;x&lt;&#x2F;code&gt;
is on the stack:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                 PROGRAM                                MEMORY
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;use std::str;                            ========================================
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fn main() {                              |              HEAP                    |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &#x2F;&#x2F; An empty String                   | addr[0x00F0] &amp;lt;----+                  |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    let x: String = String::new();       | type: *const u8   |                  |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                | value: [empty]    |                  |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                |                   |                  |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                |&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;|&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;|
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                |                   |                  |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                | addr[0xFFF0]      |                  |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                | type: String      |                  |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        +------------------------------- &amp;gt; value: 0x00F0 + len: 0 + capacity: 0 |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                                         |              STACK                   |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}                                        ========================================
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There&#x27;s a bit of lying going on above, since String itself doesn&#x27;t have the pointer,
it&#x27;s a wrapper around &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt;, and the &lt;code&gt;Vec&lt;&#x2F;code&gt; has the actual pointer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;data-segment&quot;&gt;Data segment&lt;&#x2F;h2&gt;
&lt;p&gt;As previously mentioned, all string literals, e.g. &lt;code&gt;let x = &quot;hello&quot;&lt;&#x2F;code&gt;, will have
the type &lt;code&gt;&amp;amp;&#x27;static str&lt;&#x2F;code&gt;, and they are stored in the &lt;code&gt;data&lt;&#x2F;code&gt; segment of the application
binary.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              PROGRAM                                     SEGMENTS
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                                            ======================================= low mem
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fn main() {                                 |              .text                  |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &#x2F;&#x2F; A str &amp;quot;string&amp;quot; with the value &amp;quot;abc&amp;quot;  =======================================
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &#x2F;&#x2F; which is stored in the data segment  |              .data                  |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    let x: &amp;amp;&amp;#39;static str = &amp;quot;abc&amp;quot;; ----+      | addr[0x0008] &amp;lt;----------+           |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                            |      | type: *const u8         |           |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                            +------&amp;gt; value: &amp;quot;abc&amp;quot;            |           |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                   ==========================|============
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                   |               HEAP      |           |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                   |                         |           | addr[0x00F0]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                   |                         |           |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                   |&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;|&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;|
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                   |                         |           |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                   |                         |           |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                   |                         |           |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        |                                   | addr[0xFFF0]            |           |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        | &#x2F;&#x2F; x is stored on the stack       | type: &amp;amp;&amp;#39;static str      |           | addr[0xFFFF]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        +-----------------------------------&amp;gt; value: 0x0008 + len: 3 -+           |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;         &#x2F;&#x2F; and contains a ptr and a len    |               STACK                 |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}                                           ======================================= high mem
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;stack&quot;&gt;Stack&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s possible to store string data on the stack, one way would be to create an
array of &lt;code&gt;u8&lt;&#x2F;code&gt; and then get a &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt; slice pointing into that array.&lt;&#x2F;p&gt;
&lt;p&gt;This is stolen from the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;str&#x2F;fn.from_utf8.html&quot;&gt;str documentation&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                        PROGRAM                                      MEMORY
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;use std::str;                                           =================================
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fn main() {                                             | HEAP (unused in this example) |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                                                        |&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;|
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    let sparkle_heart: [u8; 4] = [240, 159, 146, 150];  | addr[0xFFE0] &amp;lt;----------+     |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                                  |                     | type: *const u8         |     |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                                  +---------------------&amp;gt; value: [bytes...]       |     |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                                                        |                         |     |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;+-- let sparkle_heart = str::from_utf8(&amp;amp;sparkle_heart)  | addr[0xFFF0]            |     |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;|       .unwrap();                                      | type: &amp;amp;str              |     |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;|-------------------------------------------------------&amp;gt; value: 0xFFE0 + len: 4 -+     |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                                                        |             STACK             |
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}                                                       =================================
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;stack-strings-and-hybrid-strings&quot;&gt;Stack strings and Hybrid strings&lt;&#x2F;h2&gt;
&lt;p&gt;For stack allocated strings, or for hybrid stack&#x2F;heap implementations, there are
a number of crates available. Use your favorite search engine to find them.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;a-helpful-tip&quot;&gt;A helpful tip&lt;&#x2F;h1&gt;
&lt;p&gt;The reference variety of &lt;code&gt;String&lt;&#x2F;code&gt;: &lt;code&gt;&amp;amp;String&lt;&#x2F;code&gt;, should be avoided in favor of &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt;,
unless there is a need for a &quot;String out parameter&quot;. A &quot;String out parameter&quot;, or
&lt;code&gt;&amp;amp;mut String&lt;&#x2F;code&gt;, can be used when a currently owned String needs to be updated by
a receiving function, without having to move it into, and then out of, that function.&lt;&#x2F;p&gt;
&lt;p&gt;In short:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;String&lt;&#x2F;code&gt; for strings you need to change, or where a &lt;code&gt;String&lt;&#x2F;code&gt; is a required parameter.&lt;&#x2F;li&gt;
&lt;li&gt;Use &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt; as function parameters when you need to read string data, since all types of
strings can be cheaply turned into &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Use &lt;code&gt;&amp;amp;mut String&lt;&#x2F;code&gt; only when you need a &quot;String out parameter&quot;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;final-words&quot;&gt;Final words&lt;&#x2F;h1&gt;
&lt;p&gt;We learned that&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;String&lt;&#x2F;code&gt; is for growable strings on the heap.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;[u8; N]&lt;&#x2F;code&gt; (byte array) is for strings on the stack.&lt;&#x2F;li&gt;
&lt;li&gt;string literals &lt;code&gt;&quot;abc&quot;&lt;&#x2F;code&gt; are strings in the &lt;code&gt;data&lt;&#x2F;code&gt; segment.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt; is for peeking into string slices allocated on the
heap, in the &lt;code&gt;data&lt;&#x2F;code&gt; segment, or on the stack.&lt;&#x2F;li&gt;
&lt;li&gt;How &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt; points into the different types of string storage.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Rust 2020</title>
        <published>2019-10-31T00:00:00+00:00</published>
        <updated>2019-10-31T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/rust-2020-call-for-blogs/"/>
        <id>https://zkc.se/blog/rust-2020-call-for-blogs/</id>
        <content type="html" xml:base="https://zkc.se/blog/rust-2020-call-for-blogs/">&lt;p&gt;We have all been called upon by the rust community
to share our thoughts on what we want from Rust in 2020.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;My wants are centered around the developer&#x2F;debug experience more than the language itself.
I find the language to be expressive and attractive for many types of development,
and I find the community to be very pleasant.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;more&quot;&gt;More&lt;&#x2F;h1&gt;
&lt;p&gt;What do I want more of?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;more-introspection&quot;&gt;More introspection&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;locally&quot;&gt;Locally&lt;&#x2F;h3&gt;
&lt;p&gt;This might be targeted at LLDB more than Rust proper, but what I want are
more tools that are focused on letting the programmer understand what is going on
inside a running debug build, without having to stop the program.&lt;&#x2F;p&gt;
&lt;p&gt;A really nice tool that exists for Java is VisualVM.&lt;&#x2F;p&gt;
&lt;p&gt;I have tried to find equivalent tools for Rust&#x2F;LLDB&#x2F;GDB but have not been able
to find something that is both maintained and easy to use. Please let me know
if I have missed anything, &lt;a href=&quot;https:&#x2F;&#x2F;zkc.se&#x2F;pages&#x2F;about&#x2F;&quot;&gt;my contact information is available here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine being able to debug, learn, and draw conclusions from a live view into
a running Rust binary. The state of each Thread. Stack information for each Thread. Time
spent in each Thread. The number and size of Heap allocations. The current and
historic number of active Threads.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;on-the-server&quot;&gt;On the server&lt;&#x2F;h3&gt;
&lt;p&gt;It would be nice to be able to export those same metrics mentioned above to a metric
aggregator, e.g. Prometheus.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;more-ide&quot;&gt;More IDE&lt;&#x2F;h2&gt;
&lt;p&gt;I am an IntelliJ &#x2F; CLion user so I would like to see improvements for the Rust plugin
for CLion. It&#x27;s already usable, but it needs more polish and more features.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;less&quot;&gt;Less&lt;&#x2F;h1&gt;
&lt;p&gt;There was a section about disk usage here but then I found out about &lt;code&gt;cargo sweep&lt;&#x2F;code&gt; and &lt;code&gt;sccache&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s what I want. Thank you for reading my incoherent ramblings.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Java 8 to 11: TLDR edition</title>
        <published>2018-12-31T00:00:00+00:00</published>
        <updated>2018-12-31T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/java-8-java-11-migration/"/>
        <id>https://zkc.se/blog/java-8-java-11-migration/</id>
        <content type="html" xml:base="https://zkc.se/blog/java-8-java-11-migration/">&lt;p&gt;It&#x27;s been two years and two months since I last wrote a blog post - I promise to make it count!&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h1 id=&quot;updates&quot;&gt;Updates&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;2019-01-05&lt;&#x2F;em&gt; Added section on combining Gradle, Error Prone, and Lombok.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;2019-01-05&lt;&#x2F;em&gt; Clarified which JNLP image to use.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;2019-01-18&lt;&#x2F;em&gt; Added section on JDK&#x2F;JRE&#x2F;JVM switching in a IntelliJ project that uses Gradle.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;why-now&quot;&gt;Why &lt;em&gt;now&lt;&#x2F;em&gt;?&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;The Jenkins Docker JNLP Slave image finally has a version that supports Java 11!
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;FROM jenkins&#x2F;jnlp-slave:latest-jdk11&lt;&#x2F;code&gt; for now.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;issues.jenkins-ci.org&#x2F;browse&#x2F;JENKINS-51986&quot;&gt;Issue tracker&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hub.docker.com&#x2F;r&#x2F;jenkins&#x2F;jnlp-slave&#x2F;&quot;&gt;Docker Hub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jenkinsci&#x2F;docker-jnlp-slave&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Many projects have recently solved their initial &lt;em&gt;Java 9&lt;&#x2F;em&gt; issues (which are required for Java 11 support)
&lt;ul&gt;
&lt;li&gt;Including Spring!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;I am no longer procrastinating.&lt;&#x2F;li&gt;
&lt;li&gt;Maybe you thought the title would explain why I stopped blogging.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;macOS 10.14&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;brew.sh&#x2F;&quot;&gt;Homebrew&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you skip the parts about installing Java 11 it&#x27;s mostly platform independent after that.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;relevant-documentation&quot;&gt;Relevant documentation&lt;&#x2F;h1&gt;
&lt;p&gt;If you don&#x27;t want to read the rest of my incoherent ramblings:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AdoptOpenJDK&#x2F;homebrew-openjdk&quot;&gt;Install OpenJDK 11 using brew&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.oracle.com&#x2F;javase&#x2F;9&#x2F;migrate&#x2F;&quot;&gt;Oracle: Migrate to Java 9&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;why-openjdk&quot;&gt;Why OpenJDK?&lt;&#x2F;h1&gt;
&lt;p&gt;As mentioned in &lt;a href=&quot;https:&#x2F;&#x2F;blog.jetbrains.com&#x2F;idea&#x2F;2018&#x2F;09&#x2F;using-java-11-in-production-important-things-to-know&#x2F;&quot;&gt;JetBrains: Using Java 11 In Production: Important Things To Know&lt;&#x2F;a&gt;
(by Trisha Gee!)&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Oracle’s JDK (commercial) – you can use this in development and testing for free, but if you use it in production you have to pay for it.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;You &lt;em&gt;probably&lt;&#x2F;em&gt; don&#x27;t want to pay for it.&lt;&#x2F;p&gt;
&lt;p&gt;Even better:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that since Java 11, Oracle’s commercial JDK and Oracle’s OpenJDK builds are functionally the same, so we should be able to run our applications on either without having to make any changes or losing any features.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;list-available-java-versions&quot;&gt;List available Java versions&lt;&#x2F;h1&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&#x2F;usr&#x2F;libexec&#x2F;java_home&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;V&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On my machine this currently yields&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-job z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-job z-shell&quot;&gt;%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &#x2F;usr&#x2F;libexec&#x2F;java_home&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;V&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Matching&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; Java Virtual Machines (2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;)&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-colon z-shell&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;1.8.0_144,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; x86_64:	&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Java SE 8&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;	&#x2F;Library&#x2F;Java&#x2F;JavaVirtualMachines&#x2F;jdk1.8.0_144.jdk&#x2F;Contents&#x2F;Home&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&#x2F;Library&#x2F;Java&#x2F;JavaVirtualMachines&#x2F;jdk1.8.0_144.jdk&#x2F;Contents&#x2F;Home&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;getting-java-11-installed&quot;&gt;Getting Java 11 installed&lt;&#x2F;h1&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;brew&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; tap AdoptOpenJDK&#x2F;openjdk&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;brew&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; cask install adoptopenjdk11&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And now let&#x27;s check what happened&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-job z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-job z-shell&quot;&gt;%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &#x2F;usr&#x2F;libexec&#x2F;java_home&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;V&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Matching&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; Java Virtual Machines (2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;)&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-colon z-shell&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;11.0.1,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; x86_64:	&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;AdoptOpenJDK 11.0.1&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;	&#x2F;Library&#x2F;Java&#x2F;JavaVirtualMachines&#x2F;adoptopenjdk-11.0.1.jdk&#x2F;Contents&#x2F;Home&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;1.8.0_144,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; x86_64:	&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Java SE 8&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;	&#x2F;Library&#x2F;Java&#x2F;JavaVirtualMachines&#x2F;jdk1.8.0_144.jdk&#x2F;Contents&#x2F;Home&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;&#x2F;Library&#x2F;Java&#x2F;JavaVirtualMachines&#x2F;adoptopenjdk-11.0.1.jdk&#x2F;Contents&#x2F;Home&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Magic!&lt;&#x2F;p&gt;
&lt;p&gt;Now if I wanted to, I could uninstall Java 8, probably. But I don&#x27;t. You might though.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to, please do:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;19039752&#x2F;removing-java-8-jdk-from-mac&quot;&gt;StackOverflow: Uninstall Java 8&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.oracle.com&#x2F;javase&#x2F;8&#x2F;docs&#x2F;technotes&#x2F;guides&#x2F;install&#x2F;mac_jdk.html&quot;&gt;Oracle: Uninstall Java 8&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;update-to-use-gradle-5-0&quot;&gt;Update to use Gradle 5.0&lt;&#x2F;h1&gt;
&lt;p&gt;Gradle 5+ is required for Java 11. Do your upgrade in whatever way you usually do it. Personally I add a configuration
to my root &lt;code&gt;build.gradle&lt;&#x2F;code&gt; file that looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;groovy&quot; class=&quot;language-groovy z-code&quot;&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;wrapper &lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-groovy&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    gradleVersion &lt;span class=&quot;z-keyword z-operator z-assignment z-groovy&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;5.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    distributionType &lt;span class=&quot;z-keyword z-operator z-assignment z-groovy&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-class z-groovy&quot;&gt;Wrapper&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-class z-groovy&quot;&gt;DistributionType&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-groovy&quot;&gt;ALL&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-groovy&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then just run the associated task &lt;code&gt;.&#x2F;gradlew wrapper&lt;&#x2F;code&gt;, which updates Gradle for that project.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;java-modules-project-jigsaw&quot;&gt;Java Modules &#x2F; Project Jigsaw&lt;&#x2F;h1&gt;
&lt;p&gt;No need to use &lt;code&gt;Java Modules&lt;&#x2F;code&gt; if you don&#x27;t want or need them!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;intellij-idea-support&quot;&gt;IntelliJ IDEA support&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;add-and-set-the-jdk&quot;&gt;Add and set the JDK&lt;&#x2F;h2&gt;
&lt;p&gt;First add Java 11 as a JDK - go to &lt;code&gt;File -&amp;gt; Project Structure -&amp;gt; Project&lt;&#x2F;code&gt;. Click &lt;code&gt;New&lt;&#x2F;code&gt; next to the Project SDK dropdown,
(if Java 11 is not already present in the dropdown list). Now find the install path of Java 11. Should be the path
that was output from the above &lt;code&gt;java_home&lt;&#x2F;code&gt; command: &lt;code&gt;&#x2F;Library&#x2F;Java&#x2F;JavaVirtualMachines&#x2F;adoptopenjdk-11.0.1.jdk&#x2F;Contents&#x2F;Home&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;When switching the project between JDK 8 and JDK 11, which might happen when switching branches or fixing bugs based on
older commits, you may need to visit the &lt;code&gt;Project Structure&lt;&#x2F;code&gt; dialog again.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;set-jdk-jre-for-the-gradle-runtime&quot;&gt;Set JDK&#x2F;JRE for the Gradle runtime&lt;&#x2F;h2&gt;
&lt;p&gt;This is important since for some reason the project JDK isn&#x27;t the same as the Gradle JDK&#x2F;JRE.&lt;&#x2F;p&gt;
&lt;p&gt;Open the &lt;code&gt;Gradle sidebar&lt;&#x2F;code&gt; and click on the &lt;code&gt;wrench&lt;&#x2F;code&gt;, or go to &lt;code&gt;Preferences -&amp;gt; Build, Execution, Deployment -&amp;gt; Build Tools -&amp;gt; Gradle&lt;&#x2F;code&gt;.
There you will find a box called &lt;code&gt;Gradle JVM&lt;&#x2F;code&gt; where you can select which version of Java that gradle should run as when
IntelliJ needs to run it.&lt;&#x2F;p&gt;
&lt;p&gt;This is important if you use the IntelliJ builder for compiling, but delegate to Gradle when testing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;use-a-gradle-configuration-to-set-jdk-version-for-intellij-subprojects&quot;&gt;Use a Gradle configuration to set JDK version for IntelliJ subprojects&lt;&#x2F;h2&gt;
&lt;p&gt;Go to the root &lt;code&gt;build.gradle&lt;&#x2F;code&gt; and enter this nugget somewhere:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;groovy&quot; class=&quot;language-groovy z-code&quot;&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;allprojects &lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-groovy&quot;&gt;{&lt;&#x2F;span&gt; project &lt;span class=&quot;z-keyword z-operator z-arrow z-groovy&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    project&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;plugins&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-method-call z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-method z-groovy&quot;&gt;withId&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-begin z-groovy&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;java&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-end z-groovy&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-groovy&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;        sourceCompatibility &lt;span class=&quot;z-keyword z-operator z-assignment z-groovy&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-groovy&quot;&gt;11.0&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;        targetCompatibility &lt;span class=&quot;z-keyword z-operator z-assignment z-groovy&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-groovy&quot;&gt;11.0&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-groovy&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    project&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;plugins&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-method-call z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-method z-groovy&quot;&gt;withId&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-begin z-groovy&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;java-library&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-end z-groovy&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-groovy&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;        sourceCompatibility &lt;span class=&quot;z-keyword z-operator z-assignment z-groovy&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-groovy&quot;&gt;11.0&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;        targetCompatibility &lt;span class=&quot;z-keyword z-operator z-assignment z-groovy&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-groovy&quot;&gt;11.0&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-groovy&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-groovy&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now refresh the Gradle project in IntelliJ and you should be able to use Java 11 everywhere, since IntelliJ picks up
that subprojects are Java 11.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-did-i-get&quot;&gt;What did I get?&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Java_version_history#Java_SE_9&quot;&gt;Wikipedia has got your back&lt;&#x2F;a&gt;, but here&#x27;s the TLDR:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Java 9
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;G1 Garbage Collector&lt;&#x2F;code&gt; is now default&lt;&#x2F;li&gt;
&lt;li&gt;Not much else, &lt;code&gt;Java Modules&lt;&#x2F;code&gt; is probably the only thing of developer interest and you don&#x27;t need to use it unless
you are writing a library&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Java 10
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;var&lt;&#x2F;code&gt; keyword and &lt;em&gt;Local-variable type inference&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The rest is mostly runtime and behind-the-scenes stuff&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Java 11
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Local-Variable Syntax for Lambda Parameters&lt;&#x2F;em&gt;, more &lt;code&gt;var&lt;&#x2F;code&gt; :)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But mostly you got the freedom and&#x2F;or burden to adopt new Java versions faster!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;error-prone&quot;&gt;Error Prone&lt;&#x2F;h1&gt;
&lt;p&gt;You can now use the latest version of &lt;code&gt;Error Prone&lt;&#x2F;code&gt;, which should make you very happy.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;errorprone.info&#x2F;&quot;&gt;Project page&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tbroyer&#x2F;gradle-errorprone-plugin&quot;&gt;Gradle plugin&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;combining-gradle-error-prone-and-lombok&quot;&gt;Combining Gradle, Error Prone, and Lombok&lt;&#x2F;h1&gt;
&lt;p&gt;To get Gradle 5.0 to accept Lombok using Java 11 in combination with Error Prone I had to change the following&lt;&#x2F;p&gt;
&lt;p&gt;From&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;groovy&quot; class=&quot;language-groovy z-code&quot;&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;dependencies &lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-groovy&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    compileOnly &lt;span class=&quot;z-string z-quoted z-double z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;org.projectlombok:lombok&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    testCompileOnly &lt;span class=&quot;z-string z-quoted z-double z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;org.projectlombok:lombok&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-groovy&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; ... more dependencies
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-groovy&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;groovy&quot; class=&quot;language-groovy z-code&quot;&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;dependencies &lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-groovy&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    compileOnly &lt;span class=&quot;z-string z-quoted z-double z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;org.projectlombok:lombok&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    annotationProcessor &lt;span class=&quot;z-string z-quoted z-double z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;org.projectlombok:lombok&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    testCompileOnly &lt;span class=&quot;z-string z-quoted z-double z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;org.projectlombok:lombok&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    testAnnotationProcessor &lt;span class=&quot;z-string z-quoted z-double z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;org.projectlombok:lombok&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;    &lt;span class=&quot;z-comment z-line z-double-slash z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-groovy&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt; ... more dependencies
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-groovy&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That way, Error Prone knows about the code generated by Lombok.&lt;&#x2F;p&gt;
&lt;p&gt;Please note that I define dependency versions globally using the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;spring-gradle-plugins&#x2F;dependency-management-plugin&#x2F;releases&quot;&gt;Spring Dependency Management Plugin&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Let&#x27;s dump some tcp - Android packet sniffing</title>
        <published>2016-10-12T00:00:00+00:00</published>
        <updated>2016-10-12T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/android-tcpdump/"/>
        <id>https://zkc.se/blog/android-tcpdump/</id>
        <content type="html" xml:base="https://zkc.se/blog/android-tcpdump/">&lt;p&gt;Let&#x27;s hold hands while we take a dump together!&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h1 id=&quot;background&quot;&gt;Background&lt;&#x2F;h1&gt;
&lt;p&gt;If you don&#x27;t want to download any old tcpdump binary file and put it all
up in your rooted Android phone, because reasons, this guide might be for
you.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;goals&quot;&gt;Goals&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;Build tcpdump&lt;&#x2F;li&gt;
&lt;li&gt;Install tcpdump&lt;&#x2F;li&gt;
&lt;li&gt;Run tcpdump&lt;&#x2F;li&gt;
&lt;li&gt;Analyze the dump&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As a bonus, I want to explain how to do this relatively platform independently.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;&#x2F;h1&gt;
&lt;p&gt;As I said, platform independently. Here we go!&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately, platform independent means installing a lot of software.
If you are already on a relatively new version of Ubuntu, you can skip to
&quot;Ubuntu packages&quot; below.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ubuntu-xenial-in-vagrant&quot;&gt;Ubuntu Xenial in Vagrant&lt;&#x2F;h2&gt;
&lt;p&gt;Start by installing &lt;a href=&quot;https:&#x2F;&#x2F;www.vagrantup.com&#x2F;downloads.html&quot;&gt;Vagrant&lt;&#x2F;a&gt;,
and then dump this into a file called Vagrantfile somewhere on your computer:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Vagrant.configure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;(2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-keyword z-control z-loop z-do z-shell&quot;&gt;do&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-pipe z-shell&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-pipe z-shell&quot;&gt;|&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;config.vm.box&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; = &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;ubuntu&#x2F;xenial64&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt; &lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Edit this line so that it fits your system configuration&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;config.vm.synced_folder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;My&#x2F;host&#x2F;computer&#x2F;folder&#x2F;Downloads&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;, &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;downloads&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now open your platform dependent terminal (cmd? xterm? iterm?) and run:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-cd z-shell&quot;&gt;cd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; Whatever&#x2F;Directory&#x2F;you&#x2F;chose&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;vagrant&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; up&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Wait for a longish while, until vagrant gets its affairs into order then run:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;vagrant&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; ssh&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When we have entered the ubuntu shell we can prepare the ubuntu packages.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ubuntu-packages&quot;&gt;Ubuntu packages&lt;&#x2F;h2&gt;
&lt;p&gt;These packages need to be installed before we continue&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; apt-get install gcc-arm-linux-gnueabi&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; apt-get install make&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; apt-get install flex&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; apt-get install byacc&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;build-tcpdump&quot;&gt;Build tcpdump&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s continue in our ubuntu shell&lt;&#x2F;p&gt;
&lt;p&gt;Copy this into an executable script file or just run it line by line:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-shell&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;TCPDUMP&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;4.7.4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-shell&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;LIBPCAP&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;1.7.4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;wget&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; http:&#x2F;&#x2F;www.tcpdump.org&#x2F;release&#x2F;tcpdump-&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;TCPDUMP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.tar.gz&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;wget&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; http:&#x2F;&#x2F;www.tcpdump.org&#x2F;release&#x2F;libpcap-&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;LIBPCAP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.tar.gz&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;tar&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; zxvf tcpdump-&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;TCPDUMP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.tar.gz&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;tar&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; zxvf libpcap-&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;LIBPCAP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.tar.gz&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-shell&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;CC&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;arm-linux-gnueabi-gcc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-cd z-shell&quot;&gt;cd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; libpcap-&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;LIBPCAP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;.&#x2F;configure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;host&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-option z-shell&quot;&gt;=&lt;&#x2F;span&gt;arm-linux&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;with-pcap&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-option z-shell&quot;&gt;=&lt;&#x2F;span&gt;linux&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;make&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-cd z-shell&quot;&gt;cd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; ..&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-cd z-shell&quot;&gt;cd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; tcpdump-&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;TCPDUMP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-shell&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;ac_cv_linux_vers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-shell&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;CFLAGS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;-static&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-shell&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;CPPFLAGS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;-static&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-shell&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;LDFLAGS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;-static&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;.&#x2F;configure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;host&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-option z-shell&quot;&gt;=&lt;&#x2F;span&gt;arm-linux&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;disable-ipv6&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;make&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;arm-linux-gnueabi-strip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; tcpdump&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Source: &lt;a href=&quot;http:&#x2F;&#x2F;www.androidtcpdump.com&#x2F;android-tcpdump&#x2F;compile&quot;&gt;androidtcpdump.com&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;After you have successfully built tcpdump, copy it to the shared directory
we set up in the Vagrantfile, or if you are on your native box copy it to
any directory you like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;cp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; tcpdump-4.7.4&#x2F;tcpdump &#x2F;downloads&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On your native machine, go to the directory that &quot;&#x2F;downloads&quot; in Vagrant
(or your local machine) points to.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;install-tcpdump&quot;&gt;Install tcpdump&lt;&#x2F;h1&gt;
&lt;p&gt;Unfortunately, this is the point where you need something that I don&#x27;t
have time to explain: A rooted Android phone. Without root you can&#x27;t
push tcpdump, and consequently you can&#x27;t run tcpdump.&lt;&#x2F;p&gt;
&lt;p&gt;First let&#x27;s find a directory to push to, sdcard1 is available on some
modern Android platforms.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;adb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; shell ls&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;[...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; long list of files ...]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sdcard&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sdcard1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;[...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; probably more files ...]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As I said, I want &lt;code&gt;sdcard1&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;adb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; root&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;adb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; remount&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;adb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; push tcpdump &#x2F;sdcard1&#x2F;tcpdump&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;run-tcpdump&quot;&gt;Run tcpdump&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s drop into adb shell&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;adb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; shell&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-cd z-shell&quot;&gt;cd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; sdcard1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From here we can run tcpdump&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;tcpdump&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;i&lt;&#x2F;span&gt; any&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;s&lt;&#x2F;span&gt; 0&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;w&lt;&#x2F;span&gt; &#x2F;sdcard1&#x2F;capture.pcap&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;tcpdump:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; listening on any, link-type LINUX_SLL (Linux cooked&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;&#x2F;span&gt;)&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; capture size 65535 bytes&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will block as long as you want to do packet capture.&lt;&#x2F;p&gt;
&lt;p&gt;Press Ctrl+C to stop listening. Pressing Ctrl+C might make tcpdump miss some buffered packets, so listen a while longer than you need to (do some web surfing then press Ctrl+C).&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-compound z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Ctrl+C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; pressed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-compound z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;28220&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; packets captured&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;35119&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; packets received by filter&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;6899&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; packets dropped by kernel&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here&#x27;s some info about the tcpdump options:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-i any&lt;&#x2F;code&gt;: listen on any network interface&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;-p&lt;&#x2F;code&gt;: disable promiscuous mode (doesn&#x27;t work anyway)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;-s 0&lt;&#x2F;code&gt;: capture the entire packet&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;-w&lt;&#x2F;code&gt;: write packets to a file (rather than printing to stdout)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Drop out of the adb shell&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-exit z-shell&quot;&gt;exit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pull the file to your local machine&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;adb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; pull &#x2F;sdcard1&#x2F;capture.pcap&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;analyze-the-dump&quot;&gt;Analyze the dump&lt;&#x2F;h1&gt;
&lt;p&gt;Download &lt;a href=&quot;https:&#x2F;&#x2F;www.wireshark.org&#x2F;&quot;&gt;Wireshark&lt;&#x2F;a&gt; and install it.&lt;&#x2F;p&gt;
&lt;p&gt;Open the file &lt;code&gt;capture.pcap&lt;&#x2F;code&gt; in Wireshark. Unfortunately, how to analyze it in Wireshark
is beyond the scope of this guide, but I&#x27;ll give you some hints.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wireshark-basics&quot;&gt;Wireshark basics&lt;&#x2F;h2&gt;
&lt;p&gt;Load the file using File -&amp;gt; Open.&lt;&#x2F;p&gt;
&lt;p&gt;In the horizontal search bar &#x2F; text field that spans the entire width of
the application window, you can write queries for filtering the dump.&lt;&#x2F;p&gt;
&lt;p&gt;A simple filter query is simply the name of the protocol you want to analyze,
e.g. &lt;code&gt;http&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;After listing all &lt;code&gt;http&lt;&#x2F;code&gt; packets, you can get more information for a specific
row &#x2F; call by right clicking that row and selecting e.g. Follow &amp;gt; HTTP Stream.&lt;&#x2F;p&gt;
&lt;p&gt;After following a stream, go back to the filter list by writing &lt;code&gt;http&lt;&#x2F;code&gt; in
the search field again.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;epilogue&quot;&gt;Epilogue&lt;&#x2F;h1&gt;
&lt;p&gt;All goals (kind of) achieved!&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Authentication &amp; authorization - what gives?</title>
        <published>2016-07-04T00:00:00+00:00</published>
        <updated>2016-07-04T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/authentication-authorization/"/>
        <id>https://zkc.se/blog/authentication-authorization/</id>
        <content type="html" xml:base="https://zkc.se/blog/authentication-authorization/">&lt;p&gt;In which I discuss the basics of authentication, authorization, and OpenID Connect.
Why?&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Disclaimer: The below blog post was written by me for me, and might (and probably does!)
contain errors. Don&#x27;t rely on anything below as &lt;em&gt;fact&lt;&#x2F;em&gt;, from now you&#x27;re on your own.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-we-have&quot;&gt;What we have&lt;&#x2F;h1&gt;
&lt;p&gt;This is typically what you see when you visit pages attempting to explain
authentication &amp;amp; authorization:&lt;&#x2F;p&gt;
&lt;a class=&quot;image&quot; href=&quot;.&amp;#x2F;webflow.png&quot;&gt;
    &lt;img src=&quot;.&amp;#x2F;webflow.png&quot; style=&quot;width: 100%; object-fit: cover;&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The above image specifically covers the Google OAuth 2.0 flow, using Google as an
OpenID Connect Provider. This truly is the future, right? Right? Right.&lt;&#x2F;p&gt;
&lt;p&gt;Another way of describing the flow is from the OAuth 2.0 spec:&lt;&#x2F;p&gt;
&lt;pre&gt;
+--------+                               +---------------+
|        |--(A)- Authorization Request -&gt;|   Resource    |
|        |&lt;-(B)-- Authorization Grant ---|     Owner     |
|        |                               +---------------+
|        |                               +---------------+
|        |--(C)-- Authorization Grant --&gt;| Authorization |
| Client |&lt;-(D)----- Access Token -------|     Server    |
|        |                               +---------------+
|        |                               +---------------+
|        |--(E)----- Access Token ------&gt;|    Resource   |
|        |&lt;-(F)--- Protected Resource ---|     Server    |
+--------+                               +---------------+
&lt;&#x2F;pre&gt;
&lt;p&gt;The images leave a lot to the imagination, but on a high level they show
authentication and authorization information being exchanged.&lt;&#x2F;p&gt;
&lt;p&gt;We need to know more about all the moving parts!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;authentication&quot;&gt;Authentication&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;openid-connect&quot;&gt;OpenID Connect&lt;&#x2F;h2&gt;
&lt;p&gt;One way of authenticating is using &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;OpenID_Connect&quot;&gt;OpenID Connect&lt;&#x2F;a&gt;,
it&#x27;s the third generation of OpenID - the first two being OpenID Authentication 1.X,
and OpenID Authentication 2.0.&lt;&#x2F;p&gt;
&lt;p&gt;The two old versions are specific schemes for authenticating users, but were
&quot;unnecessarily complicated&quot;. Since everyone is using OAuth 2, OpenID Connect was
implemented to run on top of it - or as the introduction to the spec states:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;... a simple identity layer on top of the OAuth 2.0 protocol&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;A full list of OpenID specifications can be found on their
&lt;a href=&quot;http:&#x2F;&#x2F;openid.net&#x2F;developers&#x2F;specs&#x2F;&quot;&gt;Specifications &amp;amp; Developer Information&lt;&#x2F;a&gt;
site. The &lt;a href=&quot;http:&#x2F;&#x2F;openid.net&#x2F;specs&#x2F;openid-connect-core-1_0.html&quot;&gt;OpenID Connect Core 1.0&lt;&#x2F;a&gt;
specification for example.&lt;&#x2F;p&gt;
&lt;p&gt;OpenID Connect is used by a lot of organizations, which lend their authentication
service powers (called OpenID Provider - OP) to our servers (called Relying Party - RP).&lt;&#x2F;p&gt;
&lt;p&gt;Honest question: Why couldn&#x27;t they just have called it OpenID 3.0 for OAuth 2.0 or something?
When running across &quot;OpenID 2.0&quot; and then something called &quot;OpenID Connect&quot;,
naturally you&#x27;re going to think that the &quot;2.0&quot; is newer
&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=gAjR4_CbPpQ&quot;&gt;harder better faster stronger&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;other-ways&quot;&gt;Other ways&lt;&#x2F;h2&gt;
&lt;p&gt;OpenID Connect is not the only game in town,
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Facebook_Platform#Facebook_Connect&quot;&gt;Facebook Connect&lt;&#x2F;a&gt;
is another major player.&lt;&#x2F;p&gt;
&lt;p&gt;You can also try to roll your own authentication service, and if you do that you&#x27;re
not necessarily constrained to the requirements of OpenID Connect. It&#x27;s not a bad
idea to be heavily inspired by the work of &lt;em&gt;geniuses&lt;&#x2F;em&gt;, though.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;authorization&quot;&gt;Authorization&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s talk about OAuth 2.0 baby.
&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=ydrtF45-y-g&quot;&gt;Let&#x27;s talk about you and me. Let&#x27;s talk about all the good things, and the bad things.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Instead of using the terms &lt;em&gt;OpenID Provider&lt;&#x2F;em&gt; and &lt;em&gt;Relying Party&lt;&#x2F;em&gt;, the OAuth 2.0
spec uses&lt;&#x2F;p&gt;
&lt;table&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td style=&quot;font-style: italic&quot;&gt;
                Resource owner
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                Capable of granting access, sometimes an end-user
            &lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
        &lt;tr&gt;
            &lt;td style=&quot;font-style: italic&quot;&gt;
                Resource server
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                Has resources accessible after presenting an access token
            &lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
            &lt;tr&gt;
            &lt;td style=&quot;font-style: italic&quot;&gt;
                Client
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                An application (server) making requests on behalf of the resource owner
            &lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
        &lt;tr&gt;
            &lt;td style=&quot;font-style: italic&quot;&gt;
                Authorization server
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                Issues tokens after authentication and authorization
            &lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
    &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;It goes on stating &lt;a href=&quot;http:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc6749#section-1.1&quot;&gt;&quot;The interaction between the authorization server and resource server
is beyond the scope of this specification.  The authorization server
may be the same server as the resource server or a separate entity.&quot;&quot;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;authorization-grant&quot;&gt;Authorization grant&lt;&#x2F;h2&gt;
&lt;p&gt;An &lt;em&gt;authorization grant&lt;&#x2F;em&gt; is the &lt;a href=&quot;http:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc6749#section-1.3&quot;&gt;&quot;... resource
owner&#x27;s authorization (to access its protected resources) used by the
client to obtain an access token&quot;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There are four &lt;em&gt;grants types&lt;&#x2F;em&gt; defined in the spec&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Authorization Code&lt;&#x2F;li&gt;
&lt;li&gt;Implicit&lt;&#x2F;li&gt;
&lt;li&gt;Resource Owner Password Credentials&lt;&#x2F;li&gt;
&lt;li&gt;Client Credentials.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Each grant has an
associated &lt;em&gt;Flow&lt;&#x2F;em&gt;, which are ways of obtaining tokens used for authorization after
authenticating a user, the most common being authorization code flow, and
implicit flow.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;authorization-code-flow&quot;&gt;&lt;a href=&quot;http:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc6749#section-1.3.1&quot;&gt;Authorization code flow&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Typically involves a browser (user agent), a web server (client),
a resource owner (user), and an authorization server.&lt;&#x2F;p&gt;
&lt;p&gt;Explained in detail in &lt;a href=&quot;http:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc6749#section-4.1&quot;&gt;section 4.1&lt;&#x2F;a&gt;
of the spec, summarized below:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The client (server) redirects the UA to the authorization server.&lt;&#x2F;li&gt;
&lt;li&gt;The authorization server authenticates the user and asks the user to &lt;em&gt;grant&lt;&#x2F;em&gt; access.&lt;&#x2F;li&gt;
&lt;li&gt;If access is granted the authorization server redirects the user back to the client (server).&lt;&#x2F;li&gt;
&lt;li&gt;The client (server) requests an access token using the authorization code received in step 3,
the redirection URI is also sent to the authorization server for validation.&lt;&#x2F;li&gt;
&lt;li&gt;The client is authenticated on the authorization server using the authorization code and
redirect URI. If valid, the authorization gives the client an access token (and optionally
a refresh token).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;em&gt;Summarized&lt;&#x2F;em&gt; means that a lot of detail was left out. Read the spec!&lt;&#x2F;p&gt;
&lt;p&gt;In this flow, the access token never leaves the &lt;em&gt;client&lt;&#x2F;em&gt; (server), instead the
client is connected to the UA&#x2F;user via e.g. sessions.&lt;&#x2F;p&gt;
&lt;p&gt;I guess the access token can be exposed to the UA anyway, if the implementation
chooses to do that. The takeaway is
that the client uses credentials (typically client secret) issued by the authorization server,
that should NOT be used in the implicit flow. Otherwise it wouldn&#x27;t be a
&lt;em&gt;secret&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;implicit-flow&quot;&gt;&lt;a href=&quot;http:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc6749#section-1.3.2&quot;&gt;Implicit flow&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Used when there is no, or you don&#x27;t specifically have a need for, the client being involved.
The authorization server sends an access token directly to the UA in the redirect.
Typically used by Javascript clients or Android apps.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;mixin-it-up&quot;&gt;Mixin&#x27; it up&lt;&#x2F;h1&gt;
&lt;p&gt;OpenID Connect runs on top of OAuth 2.0 - always keep that in mind when reading
about these two separate specifications!&lt;&#x2F;p&gt;
&lt;p&gt;The concepts of the different specs
and auxiliary technologies like JWT are often presented as one and the same
by third parties (blogs, etc) and one needs to keep that in mind.&lt;&#x2F;p&gt;
&lt;p&gt;OpenID Connect gives you the convenient ID Token, which can be used in parallel
with the OAuth 2.0 Access Token, or separately!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;tokens&quot;&gt;Tokens&lt;&#x2F;h1&gt;
&lt;p&gt;All of these are (usually) &lt;a href=&quot;https:&#x2F;&#x2F;jwt.io&#x2F;&quot;&gt;JWTs&lt;&#x2F;a&gt;. Basically they contain claims, and (AFAIK)
those claims should only ever be trusted if they are digitally signed by the
issuer using e.g. &lt;a href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc7515&quot;&gt;JWS&lt;&#x2F;a&gt;, and that signature should
always be verified by anyone about to trust those claims (e.g. a resource server).&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s one place to &lt;a href=&quot;http:&#x2F;&#x2F;kjur.github.io&#x2F;jsjws&#x2F;tool_jwt.html&quot;&gt;play around&lt;&#x2F;a&gt; with JWTs
and different types of signatures.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jwt-signatures&quot;&gt;JWT signatures&lt;&#x2F;h2&gt;
&lt;p&gt;According to
&lt;a href=&quot;https:&#x2F;&#x2F;auth0.com&#x2F;blog&#x2F;2015&#x2F;12&#x2F;17&#x2F;json-web-token-signing-algorithms-overview&#x2F;&quot;&gt;auth0&lt;&#x2F;a&gt;
the most common types of signatures are&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;HMAC + SHA256
Creates a signature using a &lt;em&gt;key&lt;&#x2F;em&gt; and a &lt;em&gt;message&lt;&#x2F;em&gt;. The &lt;em&gt;key&lt;&#x2F;em&gt; is the same every time
and the &lt;em&gt;message&lt;&#x2F;em&gt; is the JWT. Common, but more insecure than the asymmetric algorithms below.&lt;&#x2F;li&gt;
&lt;li&gt;RSASSA-PKCS1-v1_5 + SHA256
Asymmetric signing using RSA. Usually faster than ECDSA.&lt;&#x2F;li&gt;
&lt;li&gt;ECDSA + P-256 + SHA256
Asymmetric signing using ECDSA. Smaller keys than RSA, resulting in smaller JWTs.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;id-token&quot;&gt;ID Token&lt;&#x2F;h2&gt;
&lt;p&gt;The OpenID Connect Core 1.0 specification defines the &lt;a href=&quot;http:&#x2F;&#x2F;openid.net&#x2F;specs&#x2F;openid-connect-core-1_0.html#IDToken&quot;&gt;ID Token&lt;&#x2F;a&gt; in section 2.&lt;&#x2F;p&gt;
&lt;p&gt;There are a &lt;em&gt;bunch&lt;&#x2F;em&gt; of fields, and following the spec for validating the ID Token is
a really good idea. Read the spec. Live the spec.&lt;&#x2F;p&gt;
&lt;p&gt;The ID Token contains claims and typically identifies a user in the context of the OP.&lt;&#x2F;p&gt;
&lt;p&gt;If you are building a service with e.g. Google Sign-In, the ID Token is issued by
Google and &lt;a href=&quot;https:&#x2F;&#x2F;developers.google.com&#x2F;identity&#x2F;sign-in&#x2F;android&#x2F;backend-auth&quot;&gt;according to them&lt;&#x2F;a&gt;
the RP should use the ID Token to uniquely identify a user in the RPs context
(after verifying the integrity of the token).&lt;&#x2F;p&gt;
&lt;p&gt;If you are building your own service and don&#x27;t have any use for e.g. Google APIs
but you still want to use Google accounts for signing in to your service, just
use the ID Token and forget about the Access Token.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;access-token&quot;&gt;Access token&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc6749#section-1.4&quot;&gt;&quot;Access tokens are credentials used to access protected resources.  An
access token is a string representing an authorization issued to the
client.&quot;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Typically, the access token is a JWT token, but according to the spec it doesn&#x27;t have to be.&lt;&#x2F;p&gt;
&lt;p&gt;The most important thing is, when you need access to an API (resource), use the token that
the authorization server gave you!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;access-token-types&quot;&gt;Access Token Types&lt;&#x2F;h3&gt;
&lt;p&gt;There are a &lt;a href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc6749#section-7.1&quot;&gt;number&lt;&#x2F;a&gt; of access token
types.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;bearer-token&quot;&gt;Bearer token&lt;&#x2F;h4&gt;
&lt;p&gt;Whoever presents the token shall be granted access to a resource as long as
the token is valid. This is the most common type of access token.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;mac-token&quot;&gt;MAC token&lt;&#x2F;h4&gt;
&lt;p&gt;The &lt;a href=&quot;http:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;draft-ietf-oauth-v2-http-mac-05&quot;&gt;draft&lt;&#x2F;a&gt; still isn&#x27;t
finalized, but from what I can gather, the token contains some cryptographic content
that would make it harder to forge and&#x2F;or read. A probable use case would be
using it in use-cases lacking HTTPS&#x2F;TLS capabilities.&lt;&#x2F;p&gt;
&lt;p&gt;Don&#x27;t quote me on that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;refresh-token&quot;&gt;Refresh token&lt;&#x2F;h2&gt;
&lt;p&gt;A token used to request new access tokens as they expire. Handy if one wants
to avoid going through the authorization flow once again.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;other-sources&quot;&gt;Other Sources&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;connect2id.com&#x2F;learn&#x2F;openid-connect&quot;&gt;OpenID Connect explained&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>TL;DR-time: XSS &amp; XSRF (web attack vectors)</title>
        <published>2016-06-12T00:00:00+00:00</published>
        <updated>2016-06-12T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/xss-xsrf/"/>
        <id>https://zkc.se/blog/xss-xsrf/</id>
        <content type="html" xml:base="https://zkc.se/blog/xss-xsrf/">&lt;p&gt;I&#x27;m going to explain Cross-site scripting (XSS) &amp;amp; Cross-site request forgery
(XSRF&#x2F;CSRF) to myself.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h1 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;&#x2F;h1&gt;
&lt;p&gt;Super long names like &quot;Cross-site request forgery&quot; and their scary acronyms don&#x27;t
exactly lend themselves to instant revelations about how they work.
Not like S.C.U.B.A., anyway.&lt;&#x2F;p&gt;
&lt;p&gt;Therefore we must know some things™. Welcome to the TL;DR section.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Adversary_%28cryptography%29&quot;&gt;Mallory&lt;&#x2F;a&gt; has her work cut out for her!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;xss&quot;&gt;XSS&lt;&#x2F;h3&gt;
&lt;p&gt;Basically, if your web page displays input from users, and that input is
not scrubbed by you, that input could be &lt;em&gt;weaponized&lt;&#x2F;em&gt; — e.g. if it loads (or is)
a script (yes, that was an em dash).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;XSS generally applies when the user is interacting with your page directly&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;xsrf&quot;&gt;XSRF&lt;&#x2F;h3&gt;
&lt;p&gt;Any page that you visit can load content from your web page via GET (and
possibly other means if &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Cross-origin_resource_sharing&quot;&gt;CORS&lt;&#x2F;a&gt;
is disabled, or when using XSS + &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;XMLHttpRequest&quot;&gt;XHR&lt;&#x2F;a&gt;).
All of this is perfectly valid, because many pages &lt;em&gt;want&lt;&#x2F;em&gt; to provide resources
like images.&lt;&#x2F;p&gt;
&lt;p&gt;Loading an image can be done with an &amp;lt;img&amp;gt; tag. That &amp;lt;img&amp;gt; tag may point to ANY
url on your site, and if your site uses cookies
&lt;a href=&quot;http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;3732087&#x2F;is-csrf-possible-without-cookies&quot;&gt;(or possibly other means of auth*)&lt;&#x2F;a&gt;,
and you are still logged in, Mallory might start wreaking havoc.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;XSRF generally applies when the user is not interacting with your page directly&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;combination-of-xss-xsrf&quot;&gt;Combination of XSS &amp;amp; XSRF&lt;&#x2F;h3&gt;
&lt;p&gt;Obviously, if the attackers can combine these methods, they might be more successful
than when employing just one.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;xss-in-depth-ish&quot;&gt;XSS in-depth-ish&lt;&#x2F;h1&gt;
&lt;p&gt;Some examples will be given, followed by a section on protection. No guarantees
can be given as it pertains to their efficacy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xss-as-a-script-in-query-parameters&quot;&gt;XSS as a script in query parameters&lt;&#x2F;h2&gt;
&lt;p&gt;This vector is generally called &quot;non-persistent&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;If the script is allowed to be included in a user-facing HTML the attacker can
perform any action that the user is allowed to perform. An example of this is
a query parameter &lt;code&gt;name=your%20name&lt;&#x2F;code&gt; that your page reads and displays as the
title of some page. Now the attacker crafts some url
&lt;code&gt;http:&#x2F;&#x2F;your-domain.com&#x2F;page?name=&amp;lt;script&amp;gt;alert(&#x27;xss&#x27;)&amp;lt;&#x2F;script&amp;gt;&lt;&#x2F;code&gt;, and voila you
dad just got rekt. (&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Cross-site_scripting#Exploit_examples&quot;&gt;The url can be further masked using character percent escaping&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xss-as-a-script-in-a-forum-post&quot;&gt;XSS as a script in a forum post&lt;&#x2F;h2&gt;
&lt;p&gt;This vector is generally called &quot;persistent&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;If you allow user input in a forum post, user support request ticket, etc. you
may be subject to XSS attacks. The attack happens when Mallory is allowed to post
user-facing HTML that is not sanitized using HTML escaping. Same scenario as in the
non-persistent case — Your dad is going to get rekt; only this time he gets rekt
every time he refreshes that forum post on gastrointestinal health.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;protections&quot;&gt;Protections&lt;&#x2F;h2&gt;
&lt;p&gt;Always sanitize external input. Always validate external input. Disable scripts
in your browser (you&#x27;re not going to do that though, are you, tough guy?).
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Cross-site_scripting#Emerging_defensive_technologies&quot;&gt;There&#x27;s some stuff coming in future browsers too&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;xsrf-in-depth-ish&quot;&gt;XSRF in-depth-ish&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.gnucitizen.org&#x2F;blog&#x2F;csrf-demystified&#x2F;&quot;&gt;This guy&lt;&#x2F;a&gt; made me read a lot
of text, and I&#x27;m not going to put you through that.&lt;&#x2F;p&gt;
&lt;p&gt;We love to love cookies, and Mallory &lt;em&gt;knows it&lt;&#x2F;em&gt;. That &amp;lt;img&amp;gt; tag we talked about
earlier, it might look like this:
&lt;code&gt;&amp;lt;img src=&quot;http:&#x2F;&#x2F;your-domain.com&#x2F;me&#x2F;settings?delete_account=true&quot;&#x2F;&amp;gt;&lt;&#x2F;code&gt;. (You&#x27;re
probably not going to have an API like that but
&lt;a href=&quot;https:&#x2F;&#x2F;www.google.se&#x2F;search?q=bear&quot;&gt;bear&lt;&#x2F;a&gt; with me). That resource is going to
be loaded using a GET request, and the browser is going to send your cookies right
along with it. &lt;em&gt;That&#x27;s right&lt;&#x2F;em&gt;, your dad just keeps getting rekt.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;protection&quot;&gt;Protection&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;security.stackexchange.com&#x2F;questions&#x2F;76544&#x2F;modern-browsers-safe-to-ignore-csrf&quot;&gt;This guy&lt;&#x2F;a&gt;
has a novel approach to web browser security as it pertains to XSRF attacks:
load every page that requires credentials separately and make sure no other web
pages are loaded. Sign out a soon as you are finished. Oh, and restart your browser
after signing out, who knows what might be cached? No one is going to do
that though.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;re going to help your dad out, because he&#x27;s a nice guy.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re not into TL;DR, there&#x27;s this: &lt;a href=&quot;https:&#x2F;&#x2F;www.owasp.org&#x2F;index.php&#x2F;Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet&quot;&gt;OWASP Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Don&#x27;t expose resource changing actions as GETs&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Not going to help against XSS + XHR + XSRF.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Check the header for origin &#x2F; referer&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Can be circumvented - historically by &lt;a href=&quot;https:&#x2F;&#x2F;www.google.se&#x2F;search?q=flash+sc2&quot;&gt;flash&lt;&#x2F;a&gt;, more recently by browser plugins. Also, some web proxies will strip these headers for different reasons.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;XSRF tokens&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;5207160&#x2F;what-is-a-csrf-token-what-is-its-importance-and-how-does-it-work#comment62477933_33829607&quot;&gt;Or as this guy points out, anti-XSRF tokens&lt;&#x2F;a&gt;,
are a way to validate all requests by generating unique ids and appending
them using e.g. hidden input fields in forms, or required request parameters.
Optimally the id is generated per request, but for practical reasons (web apps)
they can be per session, or alternatively cookies with a predefined, short, lifespan.&lt;&#x2F;p&gt;
&lt;p&gt;An example:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The server generates a hard to guess id, and saves it as a cookie on the client.&lt;&#x2F;li&gt;
&lt;li&gt;The client reads the cookie (the cookie needs to have httpOnly=false) and attaches it to the request (hidden input, header, queryparam).&lt;&#x2F;li&gt;
&lt;li&gt;The server has access to both the cookie and the attached parameter and only approves requests that have both.&lt;&#x2F;li&gt;
&lt;li&gt;A pure XSRF attack is thwarted because it can&#x27;t read cookies that are from another domain, and you should have made sure guessing your generated id is hard.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This attack is still subject to XSS + XSRF because the XSS would be able to read your cookie. Dad&#x27;s getting rekt again.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;cross-origin-resource-sharing-cors&quot;&gt;Cross-origin resource sharing (CORS)&lt;&#x2F;h1&gt;
&lt;p&gt;Since I mentioned CORS a few times, here&#x27;s the lowdown:&lt;&#x2F;p&gt;
&lt;p&gt;CORS is used when a site is including e.g. images from a domain outside the
domain from which the request originated. This is useful. Some servers might
set &lt;code&gt;Access-Control-Allow-Origin: *&lt;&#x2F;code&gt;, e.g. the server serving google&#x27;s fonts:
&lt;code&gt;&amp;lt;link href=&#x27;https:&#x2F;&#x2F;fonts.googleapis.com&#x2F;css?family=Open+Sans&#x27; rel=&#x27;stylesheet&#x27; type=&#x27;text&#x2F;css&#x27;&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;somewhat-related-reading&quot;&gt;Somewhat related reading&lt;&#x2F;h1&gt;
&lt;p&gt;Some stuff I stumbled across in this recent quest for knowledge:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;auth0.com&#x2F;blog&#x2F;2016&#x2F;05&#x2F;31&#x2F;cookies-vs-tokens-definitive-guide&quot;&gt;Auth0 - Cookies vs Tokens: The Definitive Guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;stormpath.com&#x2F;blog&#x2F;where-to-store-your-jwts-cookies-vs-html5-web-storage&quot;&gt;Stormpath - Where to Store your JWTs – Cookies vs HTML5 Web Storage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Furthermore, you should see what some people that are probably smarter, more structured,
and likely prettier than me had to say:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Cross-site_scripting&quot;&gt;Wikipedia: Cross-site scripting&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Cross-site_request_forgery&quot;&gt;Wikipedia: Cross-site request forgery&lt;&#x2F;a&gt; (According to this article CSRF is &quot;sometimes pronounced sea-surf&quot; - &lt;a href=&quot;https:&#x2F;&#x2F;www.google.se&#x2F;search?q=wat&quot;&gt;wat&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Necessary macOS system configuration</title>
        <published>2015-10-29T00:00:00+00:00</published>
        <updated>2015-10-29T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/macos-system-configuration/"/>
        <id>https://zkc.se/blog/macos-system-configuration/</id>
        <content type="html" xml:base="https://zkc.se/blog/macos-system-configuration/">&lt;p&gt;macOS doesn&#x27;t pull its own weight, at least not in a standard
configuration. There are a number of apps that need to be
installed. Some of them are free, others are not.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;ul&gt;
&lt;li&gt;2020-10-27 Updated this guide, added section on CursorSense,&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Take some time to read &lt;a href=&quot;https:&#x2F;&#x2F;zkc.se&#x2F;blog&#x2F;macos-keyboard-for-windows-linux&#x2F;&quot;&gt;my guide on keyboard settings for windows &amp;amp; linux users&lt;&#x2F;a&gt; first.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;goals&quot;&gt;Goals&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;Let you maximize individual windows for any app.&lt;&#x2F;li&gt;
&lt;li&gt;Send a window to a specific half, or quarter of the screen.&lt;&#x2F;li&gt;
&lt;li&gt;Turn on&#x2F;off&#x2F;tweak mouse acceleration.&lt;&#x2F;li&gt;
&lt;li&gt;Increase keyboard repeat rate.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;sizeup&quot;&gt;SizeUp&lt;&#x2F;h1&gt;
&lt;p&gt;This app is essential. It&#x27;s one of the few apps that are actually worth paying for.
In all honesty, I don&#x27;t think that a simple thing like maximize &#x2F; send to half &#x2F; send to
quarter should need a paid third party app to work.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.irradiatedsoftware.com&#x2F;sizeup&#x2F;&quot;&gt;Throw your cash at SizeUp&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Goals one &amp;amp; two achieved.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;cursorsense&quot;&gt;CursorSense&lt;&#x2F;h1&gt;
&lt;p&gt;CursorSense is really good, and I don&#x27;t mind paying for it actually.
It lets you configure acceleration and sensitivity very precisely, and
it can save a number of &quot;favorite settings&quot; per input device.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.plentycom.jp&#x2F;en&#x2F;cursorsense&#x2F;download.php&quot;&gt;Get CursorSense now&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Goal three achieved.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;keyboard-repeat-rate&quot;&gt;Keyboard repeat rate&lt;&#x2F;h1&gt;
&lt;p&gt;Change the keyboard repeat rate&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;defaults&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; write&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;g&lt;&#x2F;span&gt; KeyRepeat&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;float&lt;&#x2F;span&gt; 1.8&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;defaults&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; write&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;g&lt;&#x2F;span&gt; InitialKeyRepeat&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;int&lt;&#x2F;span&gt; 15&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You might have to sign out or restart your computer before
the settings take effect.&lt;&#x2F;p&gt;
&lt;p&gt;All goals achieved ★&lt;&#x2F;p&gt;
&lt;p&gt;Have some tea.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>macOS keyboard settings for Windows &amp; Linux users</title>
        <published>2015-10-18T00:00:00+00:00</published>
        <updated>2015-10-18T00:00:00+00:00</updated>
        
        <author>
            <name>
                
                Erik Živković
                
            </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://zkc.se/blog/macos-keyboard-for-windows-linux/"/>
        <id>https://zkc.se/blog/macos-keyboard-for-windows-linux/</id>
        <content type="html" xml:base="https://zkc.se/blog/macos-keyboard-for-windows-linux/">&lt;p&gt;If you&#x27;re like me, and you&#x27;re coming from two decades of using Windows and Linux,
you might want to keep using the keyboard shortcuts you&#x27;re used to.&lt;&#x2F;p&gt;
&lt;p&gt;You might also be a programmer. In that case: even better.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;ul&gt;
&lt;li&gt;2015-10-18: This guide was written for OSX 10.11 (El Capitan).&lt;&#x2F;li&gt;
&lt;li&gt;2017-04-14: Updated for macOS 10.12 (Sierra)&lt;&#x2F;li&gt;
&lt;li&gt;2020-10-27: Removed broken links and updated examples for macOS Catalina.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;goals&quot;&gt;Goals&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;Use a Swedish keyboard, with close-to-identical keybindings.&lt;&#x2F;li&gt;
&lt;li&gt;Use Ctrl+S (Save), Ctrl+C (Copy), Ctrl+V (Paste), etc.
(Clarification: Actually Cmd+Key but Cmd is in the same position as Ctrl).&lt;&#x2F;li&gt;
&lt;li&gt;Use the same old finger setting you&#x27;re used to, that includes AltGr
(or whatever key, but placed where AltGr used to be) for writing the usual.
characters &lt;code&gt;{}[]\|&lt;&#x2F;code&gt; etc. (I know this is very specific to the Swedish programming layout).&lt;&#x2F;li&gt;
&lt;li&gt;Use Ctrl+C to abort execution in a terminal (I&#x27;ll be using iTerm).&lt;&#x2F;li&gt;
&lt;li&gt;Improve the Alt+Tab experience.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;swedish-windows-linux-style-keyboard&quot;&gt;Swedish Windows&#x2F;Linux-style keyboard&lt;&#x2F;h1&gt;
&lt;p&gt;I built a keyboard layout using &lt;a href=&quot;http:&#x2F;&#x2F;scripts.sil.org&#x2F;ukelele&quot;&gt;Ukelele&lt;&#x2F;a&gt;.
It&#x27;s available as a &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;bes&#x2F;0b634c1f1cbb2e40d1ba91a94990f2fb&quot;&gt;GitHub gist&lt;&#x2F;a&gt;.
Just follow the instructions in the README!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;use-ctrl-c-to-copy-instead-of-command-c-etc&quot;&gt;Use Ctrl+C to copy instead of Command+C, etc.&lt;&#x2F;h1&gt;
&lt;p&gt;Our goal isn&#x27;t explicitly to use Ctrl+C, Ctrl+S, etc. It&#x27;s rather to let you use
the same old hand&#x2F;finger positions you are used to. Maybe even your trusty old windows&#x2F;linux keyboard.
That means, Command is going to be moved to Ctrl, Ctrl to Option, and Option to Command.
That way, we&#x27;re 90% there.&lt;&#x2F;p&gt;
&lt;p&gt;Now we&#x27;re going to remap the keyboard modifier keys using System Preferences.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;System Preferences&lt;&#x2F;code&gt; &amp;gt; &lt;code&gt;Keyboard&lt;&#x2F;code&gt; &amp;gt; Press &lt;code&gt;Modifier Keys&lt;&#x2F;code&gt; Button &amp;gt; Remap to:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;For an Apple keyboard&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td style=&quot;font-style: italic&quot;&gt;
                Control Key
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                &amp;#8963;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                =&gt;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                &amp;#8984; Command
            &lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
        &lt;tr&gt;
            &lt;td style=&quot;font-style: italic&quot;&gt;
                Option Key
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                &amp;#8997;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                =&gt;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                &amp;#8963; Control
            &lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
        &lt;tr&gt;
            &lt;td style=&quot;font-style: italic&quot;&gt;
                Command Key
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                &amp;#8984;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                =&gt;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                &amp;#8997; Option
            &lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
    &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;For a Windows&#x2F;Linux keyboard&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td style=&quot;font-style: italic&quot;&gt;
                &amp;#8963;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                Control Key
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                =&gt;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                &amp;#8984;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                Command
            &lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
        &lt;tr&gt;
            &lt;td style=&quot;font-style: italic&quot;&gt;
                &amp;#8997;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                Option Key
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                =&gt;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                &amp;#8997;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                Option
            &lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
        &lt;tr&gt;
            &lt;td style=&quot;font-style: italic&quot;&gt;
                &amp;#8984;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                Command Key
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                =&gt;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                &amp;#8963;
            &lt;&#x2F;td&gt;
            &lt;td&gt;
                Control
            &lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
    &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;Since macOS uses Command as the base modifier, we are one step closer to emulating
the behavior in Windows&#x2F;Linux.&lt;&#x2F;p&gt;
&lt;p&gt;Goals two and three achieved!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;use-ctrl-c-to-abort-execution-in-a-terminal&quot;&gt;Use Ctrl+C to abort execution in a terminal.&lt;&#x2F;h1&gt;
&lt;p&gt;I use iTerm2 for macOS, and you&#x27;re going to have to change around some stuff
for the key bindings.&lt;&#x2F;p&gt;
&lt;p&gt;Go to &lt;code&gt;Preferences&lt;&#x2F;code&gt; &amp;gt; &lt;code&gt;Keys&lt;&#x2F;code&gt; &amp;gt; Remap to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Control key = Left Command&lt;&#x2F;li&gt;
&lt;li&gt;Left Option key = Left Option&lt;&#x2F;li&gt;
&lt;li&gt;Right Option key = Right Option&lt;&#x2F;li&gt;
&lt;li&gt;Left Command key = Control&lt;&#x2F;li&gt;
&lt;li&gt;Right Command key = Control&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;improve-the-alt-tab-experience&quot;&gt;Improve the Alt+Tab experience&lt;&#x2F;h1&gt;
&lt;p&gt;There are two things going on. Since we&#x27;ve moved Command to Control, we can&#x27;t press
&quot;Alt+Tab&quot; anymore (Command+Tab duh), it&#x27;s Control+Tab now. We don&#x27;t want that.
Also, Command+Tab for app switching in macOS is not a good experience for multi-window apps.&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;ll need to install &lt;a href=&quot;https:&#x2F;&#x2F;bahoom.com&#x2F;hyperswitch&quot;&gt;Hyperswitch&lt;&#x2F;a&gt;.
Once installed, set Option+Tab as the Window switcher key. Alt+Tab is back!
It remembers your app history as long as you don&#x27;t click on any Dock icons.&lt;&#x2F;p&gt;
</content>
    </entry>
</feed>
