<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>eCorax</title>
        <link>https://www.ecorax.net</link>
        <description>Firmware, fiction, security.</description>
        <generator>Zola</generator>
        <language>en</language>
        <atom:link href="https://www.ecorax.net/categories/programming/rss.xml" rel="self" type="application/rss+xml"/>
        <lastBuildDate>Sat, 29 May 2021 00:00:00 +0000</lastBuildDate>
        <item>
            <title>Tightness Driven Development in Rust</title>
            <pubDate>Sat, 29 May 2021 00:00:00 +0000</pubDate>
            <link>https://www.ecorax.net/tightness/</link>
            <guid>https://www.ecorax.net/tightness/</guid>
            <description>&lt;p&gt;Forgive me, for I have sinned. I wrote a bad type.&lt;&#x2F;p&gt;
&lt;p&gt;It wasn&#x27;t just bad. It was the kind of type that knows its mom&#x27;s birthday only
from the digits of her credit card PIN number. It was sneaky, conceited,
insubordinate and churlish. It threw up all over my codebase like a drunken
guest and, despite my efforts to clean up, a bit of the stench remains.&lt;&#x2F;p&gt;
&lt;p&gt;Mind you, it&#x27;s not the first bad type I write, and it&#x27;s certainly not going to
be the last. Its badness did, however, send me on a bit of a personal journey
both to understand what exactly made it bad, and to figure out a strategy to
prevent its kind from haunting me again.&lt;&#x2F;p&gt;
&lt;p&gt;I won&#x27;t show you the type, not &lt;em&gt;only&lt;&#x2F;em&gt; out of
shame——though there&#x27;s a bit of that——but mostly because it&#x27;s pretty large and
full of extraneous detail that would just bog us down. I also think there&#x27;s little
value in me justifying the bad decisions that shaped it, and we might
even end up feeling a bit sorry for it. No mercy! Onward!&lt;&#x2F;p&gt;
&lt;p&gt;Instead, what we&#x27;ll do is craft some types &lt;em&gt;similar&lt;&#x2F;em&gt; to it, which showcase
particular aspects of its awfulness. I&#x27;ll then walk you through an
approach I have to identify and rework types like it ever since, in the hope it
will be useful to you too.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Be warned: I&#x27;m likely going to reinvent anywhere between the wheel and the
entire car in this post. I&#x27;m grazing the huge, scary world of type theory,
of which I&#x27;m definitely not an expert. As mentioned elsewhere I&#x27;m just a bit
banger that likes to punch above their weight, so please take what I say with
a grain of salt and if you know established terms for these concepts, please
leave a comment!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;let-s-write-some-bad-code&quot;&gt;Let&#x27;s write some bad code&lt;a class=&quot;zola-anchor&quot; href=&quot;#let-s-write-some-bad-code&quot; aria-label=&quot;Anchor link for: let-s-write-some-bad-code&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Alright, buckle up.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Please allow me the sweet embrace of death
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Shape {
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;is_circle: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;is_square: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;radius: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;side: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Okay, what I wrote wasn&#x27;t &lt;em&gt;quite&lt;&#x2F;em&gt; as bad. I want some bedrock of horribleness so
we can have a laugh and satisfy our primal urges——yes, I too have seen types
this bad in the wild——and mostly to start developing a bit of a shared
vocabulary.&lt;&#x2F;p&gt;
&lt;p&gt;So what makes this type so stinky? There are enough reasons that I&#x27;m tempted to
give you the headlines in bullet point form:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It&#x27;s wasteful. Either the radius or the side, at any give time, are unused
bits.&lt;&#x2F;li&gt;
&lt;li&gt;It has a lot of obviously invalid states. What if &lt;code&gt;is_circle&lt;&#x2F;code&gt; and &lt;code&gt;is_square&lt;&#x2F;code&gt;
are both true? And both false?&lt;&#x2F;li&gt;
&lt;li&gt;Signedness doesn&#x27;t make sense for its dimension variables. What&#x27;s a circle of
-1 radius?&lt;&#x2F;li&gt;
&lt;li&gt;Its fields are public, which allows careless users to create invalid objects.
It exposes its entrails to the sun like a fleeing sea cucumber; it won&#x27;t
be long until they attract flies and worms.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Anyone with Rust experience already has a solution for this problem in mind.
Yes, I can see your platonic &lt;code&gt;enum Shape { Circle(u32), Square(u32) }&lt;&#x2F;code&gt; from
here, dear hypothetical reader, slowly rotating under a beam of heavenly light. Perhaps
you&#x27;ve put some personal touches like named fields for the variants, or you&#x27;ve
gone for a &lt;code&gt;Shape&lt;&#x2F;code&gt; interface. Let&#x27;s not get ahead of ourselves though, you&#x27;ve
come here to see bad code and I&#x27;m not letting you go until your eyes bleed.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;invincible-invigorating-invariants&quot;&gt;Invincible, invigorating invariants&lt;a class=&quot;zola-anchor&quot; href=&quot;#invincible-invigorating-invariants&quot; aria-label=&quot;Anchor link for: invincible-invigorating-invariants&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Let me play devil&#x27;s advocate for a minute.&lt;&#x2F;p&gt;
&lt;p&gt;How can we make the type above not suck with the least amount of work? Well,
There is a bare minimum we have to do to make it &lt;em&gt;sound&lt;&#x2F;em&gt;. If the type isn&#x27;t
sound——i.e. it doesn&#x27;t do what it says on the tin——there&#x27;s little point
talking about high-minded things like good design.&lt;&#x2F;p&gt;
&lt;p&gt;The key operating word is &lt;em&gt;invariants&lt;&#x2F;em&gt;. I&#x27;m going to boldly assume we&#x27;ve all
seen circles and squares before, so we all share an intuitive understanding of
the invariants that our &lt;code&gt;Shape&lt;&#x2F;code&gt; has to hold:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A shape must be a square or a circle.&lt;&#x2F;li&gt;
&lt;li&gt;A shape can&#x27;t be both a square and a circle at the same time.&lt;&#x2F;li&gt;
&lt;li&gt;A shape must have a strictly positive associated dimension (respectively side and
radius).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;As &lt;code&gt;u&#x2F;IshKebab&lt;&#x2F;code&gt; rightfully pointed out in Reddit, zero-radius circles are
mathematically valid! Apologies to any of my readers that also happen to be
circles; I did not mean to discriminate. That said, invariants are going to
depend on the specific application, so for the purposes of this post we&#x27;ll
pretend zero-radius circles are not valid.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It is &lt;em&gt;possible&lt;&#x2F;em&gt;, though not ideal, to encode all of these invariants in the
API. In fact, as long as we make sure to encapsulate the type properly, encoding
the invariants in the API is all that&#x27;s needed to make the type &lt;em&gt;sound&lt;&#x2F;em&gt;, and for
all intents and purposes immune to misuse:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; I&amp;#39;m still horrible, but at least my awfulness is hidden!
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Shape {
   is_circle: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
   is_square: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
   radius: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
   side: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Shape {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;circle&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;radius&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;static str&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; radius &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;Must have positive radius&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)
        } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
                is_circle: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
                is_square: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
                radius,
                side: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
            })
        }
    }

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;side&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;static str&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; side &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;Must have positive side&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)
        } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
                is_circle: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
                is_square: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
                side,
                radius: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
            })
        }
    }

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;is_circle&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ self.is_circle }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;is_square&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ self.is_square }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;radius&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;static str&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.is_circle {
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(self.radius)
        } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;Only circles have a radius&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)
        }
    }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;side&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;static str&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.is_square {
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(self.side)
        } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;Only squares have sides&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)
        }
    }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above is a perfectly safe, completely sound type. Thanks to the strength of
Rust&#x27;s type system, that rotting corpse of an abstraction is allowed to spend
its miserable existence unnoticed, tightly sealed behind limited construction
and access rules.&lt;&#x2F;p&gt;
&lt;p&gt;Still, even if we leave compactness aside (which is an easy fix anyway, by just using a
common &lt;code&gt;dimension&lt;&#x2F;code&gt; field that doubles as radius and side), it&#x27;s clearly a
very poor type. Its bad design radiates outward polluting everything it touches,
and has forced us to write an awkward, clunky API to allow the external world to
interface with it.&lt;&#x2F;p&gt;
&lt;p&gt;The reason why this example is interesting to me is that &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;statuscode&#x2F;invariant-driven-development-8231add95e33&quot;&gt;invariant driven
development&lt;&#x2F;a&gt;,
as I&#x27;ve seen it called, is not enough to prevent this kind of design mishap. It
does help tremendously to identify potential bugs and build safe abstractions at
the API level, but it doesn&#x27;t necessarily help &lt;em&gt;drive&lt;&#x2F;em&gt; the design of a module.&lt;&#x2F;p&gt;
&lt;p&gt;In a limited example like this the better path is obvious, but as is often the
case with restricted examples, the entire point is to put the spotlight on an
issue that may appear in subtle, insidious forms, so it can be fought
effectively when encountered. A mental vaccine, if you will, to use a
contemporary hot analogy.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;quantifying-badness&quot;&gt;Quantifying badness&lt;a class=&quot;zola-anchor&quot; href=&quot;#quantifying-badness&quot; aria-label=&quot;Anchor link for: quantifying-badness&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s have a bit of a palate cleanser:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Boy, I sure feel bad for that *other* Shape
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Shape { Square(Square), Circle(Circle) }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Circle(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Square(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Circle {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;from_radius&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(r) }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;radius&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Square {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;from_side&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(s) }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;side&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
}

&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Convenience fallible API
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Shape {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;radius&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;static str&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self {
            Shape::Square(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;Only circles have a radius&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;),
            Shape::Circle(c) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(c.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;radius&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()),
        }
    }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;side&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;static str&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self {
            Shape::Square(s) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;side&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()),
            Shape::Circle(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;Only squares have sides&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;),
        }
    }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;is_circle&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ matches!(self, Shape::Circle(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)) }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;is_square&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ matches!(self, Shape::Square(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)) }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This shape seems a lot better than the one before. Not ideal, but better. It
&lt;em&gt;feels&lt;&#x2F;em&gt; habitable, methods are short and to the point. However, to play devil&#x27;s
advocate again, those benefits are vague and subjective. Believe it or not, this
one is &lt;em&gt;less&lt;&#x2F;em&gt; safe than the one before. Can you spot why? That&#x27;s right, in the pursuit of
elegance we&#x27;ve dropped the invariant that shapes must have a &lt;em&gt;strictly
positive&lt;&#x2F;em&gt; dimension. Degenerate squares and circles——with &lt;code&gt;side&lt;&#x2F;code&gt; and &lt;code&gt;radius&lt;&#x2F;code&gt; of
0, respectively——are now possible. Whoops!&lt;&#x2F;p&gt;
&lt;p&gt;Wouldn&#x27;t it be cool, then, if we could come up with a quantifiable, objective
metric of badness, that we could dispassionately apply to both the types above?&lt;&#x2F;p&gt;
&lt;p&gt;Enter &lt;strong&gt;tightness&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The &lt;em&gt;tightness&lt;&#x2F;em&gt; of a type is the proportion of invariants that are upheld in the
type &lt;em&gt;definition&lt;&#x2F;em&gt; as opposed to its &lt;em&gt;methods&lt;&#x2F;em&gt;.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;NOTE: I&#x27;ve asked the few type-theory people I know that still talk to me,
looking for a preexisting term to define this. I don&#x27;t think such a word
exists, so I figure I might as well coin one. If it turns out there&#x27;s one
though I&#x27;m happy to defer to it for clarity.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;There is a way to indirectly measure tightness and give it a very concrete
number: Simply work out the proportion of &lt;em&gt;representable states&lt;&#x2F;em&gt; of your type
that are valid. Let&#x27;s apply it to our shapes.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Why do you keep dragging me into this? I just want to live a quiet life...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Shape {
   is_circle: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
   is_square: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
   radius: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
   side: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s look at the fields in turn. We have two booleans for a total of four possible
permutations, of which only two are valid (&lt;code&gt;is_circle XOR is_square&lt;&#x2F;code&gt;). This cuts
our representable space in half, so we are already down to a tightness of &lt;code&gt;50%&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We then get to radius and side. Only one of them is meaningful at any given
time, so for the purposes of this informal heuristic we can simply ignore the
other. This leaves us with &lt;code&gt;2^32&lt;&#x2F;code&gt; states for the dimension, of which half (give
or take the zero) are valid. Multiplying the two together, we get a total
tightness of around &lt;code&gt;25%&lt;&#x2F;code&gt;. Only one fourth of the values that our type can
hold correspond to meaningful circles and squares.&lt;&#x2F;p&gt;
&lt;p&gt;How does our second candidate fare?&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Ha, I&amp;#39;m sure I&amp;#39;m going to get a perfect score
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Shape { Square(Square), Circle(Circle) }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Circle(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Square(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It certainly seems promising. It&#x27;s a sum type, and we know
by definition that both sides (squares and circles) are valid. Then each branch
has &lt;code&gt;2^32&lt;&#x2F;code&gt; representable states, of which everything but 0 is valid. That leaves
us with a tightness of &lt;code&gt;100 * (1 - 1 &#x2F; 2^32)&lt;&#x2F;code&gt;, which is... &lt;code&gt;99.99999997671694%&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Hey, what do you mean 99, you jerk?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Shape { Square(Square), Circle(Circle) }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Uhh... Let me double check my math, but I&#x27;m pretty sure it&#x27;s correct. You&#x27;re
&lt;em&gt;nearly&lt;&#x2F;em&gt; perfectly tight, but not quite.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Double check your $%$#@#. I&amp;#39;m pure elegance and perfection!
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Shape { Square(Square), Circle(Circle) }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Why am I talking to a type? Anyway, the problem is that you can represent
exactly one invalid circle, and one invalid square, see? You can be
&lt;code&gt;Shape::Square(Square(0))&lt;&#x2F;code&gt; or &lt;code&gt;Shape::Circle(Circle(0))&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; And how is that my problem? It&amp;#39;s not my fault that some dumb coder
&#x2F;&#x2F; forgot to make my constructor safe. Can&amp;#39;t you just assert that `radius &amp;gt; 0`
&#x2F;&#x2F; and `side &amp;gt; 0`? Even I can think of that, and I&amp;#39;m four bytes long. You should
&#x2F;&#x2F; be ashamed.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Shape { Square(Square), Circle(Circle) }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But you&#x27;re missing the point. If I did that, you&#x27;d indeed be safe to use, but
you wouldn&#x27;t be any &lt;em&gt;tighter&lt;&#x2F;em&gt;. My metric of tightness only cares about the
representable states encoded &lt;em&gt;in your definition&lt;&#x2F;em&gt;, not your methods.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; That&amp;#39;s idiotic. How is anything tight, then? A boolean is one byte long,
&#x2F;&#x2F; which means 256 different variants. Only two are correct, so is every boolean
&#x2F;&#x2F; less than 1% tight?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Shape { Square(Square), Circle(Circle) }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s not what I mean. I&#x27;m not talking about bitwise representation
literally. I&#x27;m only talking about &lt;em&gt;well defined&lt;&#x2F;em&gt; states for your fields, those
that you can only reach by correctly interacting with their API.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; So what am I supposed to do, then? Come on, my methods
&#x2F;&#x2F; must do *some* of the work, right? It&amp;#39;s not my responsibility to be always
&#x2F;&#x2F; correct. There isn&amp;#39;t even a way to promise to be positive in my definition!
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Shape { Square(Square), Circle(Circle) }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Actually, there is. It&#x27;s even in the standard library. Come on, try this on for
u-size! Har har har.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Uh... I feel a bit queasy
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Shape { Square(Square), Circle(Circle) }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Circle(NonZeroU32);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Square(NonZeroU32);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s just the feeling of perfect tightness. NonZeroU32 promises to be
nonzero, and since we only care about its valid states, we know that every one
of its possible values corresponds to a valid shape. Welcome to the 100% club!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-two-rules-of-tightness&quot;&gt;The two rules of tightness&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-two-rules-of-tightness&quot; aria-label=&quot;Anchor link for: the-two-rules-of-tightness&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;There are two rules that apply to this idea of tightness, that I&#x27;ll informally
define now and attempt to justify in the sections to follow.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rule 1: Unless your type&#x27;s sole responsibility is to restrict the values of
its fields, it can &lt;em&gt;always&lt;&#x2F;em&gt; be 100% tight (in Rust)&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Rule 2: All other factors being equal, tighter types are better&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And as a corollary:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;You should strive to make your types 100% tight&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;giving-it-your-100&quot;&gt;Giving it your 100%&lt;a class=&quot;zola-anchor&quot; href=&quot;#giving-it-your-100&quot; aria-label=&quot;Anchor link for: giving-it-your-100&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The first claim is already a bit dubious. Is it really &lt;em&gt;always&lt;&#x2F;em&gt; possible? What
about limited integer ranges? What about types with a gigantic representable
space like strings, hash maps, linked lists? With the current limitations of
const generics, there&#x27;s no way to guarantee at compile time that their values
will be in the appropriate ranges.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s a valid question, and to answer that I have to highlight that
tightness has nothing to do with compile time decisions. Sure, pulling safety
checks back into compile time is great——if you&#x27;ve read more of my blog you&#x27;ll
know I&#x27;m a huge fan of typestate programming——and you should certainly strive to
do as much of the heavy lifting as you can before the program actually runs.
However, tightness is more about defining responsibilities. Let&#x27;s look at an example:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; I despair at my looseness.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Account {
   &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Must be alphabetical and less than 8 characters long.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;   username: String,
   &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Must be alphanumeric and between 8 and 16 characters.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;   password: String,
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s... Just not tight. In fact, it&#x27;s nearly &lt;em&gt;infinitely&lt;&#x2F;em&gt; loose, as there are
an uncountable amount of character combinations that don&#x27;t comply with the restrictions
expressed in the comments. We could, of course, carefully write the API so that
the invariants are maintained at every point, but that would do nothing to
increase this particular type&#x27;s tightness. Let&#x27;s then be infinitely lazy and just delegate it to
a second type that will solve all of our problems.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Ahh! Such a weight off my shoulders.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Account {
   username: Username,
   password: Password,
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Password(String);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Username(String);

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Password {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;raw&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; {
        (raw.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;8 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; raw.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;16 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; raw.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;all&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::is_alphanumeric))
            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;then_some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(raw.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;to_owned&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()))
    }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;str &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Username {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;raw&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; {
        (raw.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;8 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; raw.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;all&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::is_alphabetic))
            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;then_some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(raw.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;to_owned&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()))
    }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;str &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Tada! Our &lt;code&gt;Account&lt;&#x2F;code&gt; type is now 100% tight. It doesn&#x27;t matter that &lt;code&gt;Username&lt;&#x2F;code&gt;
and &lt;code&gt;Password&lt;&#x2F;code&gt; enforce the invariants at runtime. What matters is that, given
they&#x27;re soundly implemented and properly defined, they are completely
responsible for maintaining the invariants that &lt;code&gt;Account&lt;&#x2F;code&gt; requires. None of
their representable states make for an invalid &lt;code&gt;Account&lt;&#x2F;code&gt;, and thus &lt;code&gt;Account&lt;&#x2F;code&gt; is
tighter than submarine rivets.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately, it&#x27;s also grown a bit
of boilerplate, and these new types aren&#x27;t really all that comfortable to use.
Wouldn&#x27;t it be cool if a skilled, humble and &lt;em&gt;very handsome&lt;&#x2F;em&gt; coder had come up
with a library to make this problem a lot simpler?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;tightness&quot;&gt;Ahem...&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;... Yeah, unfortunately it was written by me instead, but we&#x27;ll have to do. I
wrote the &lt;code&gt;tightness&lt;&#x2F;code&gt; crate as a companion to this article, to provide a
one-size-fits-all solution to encoding invariants as part of types. It&#x27;s
naturally less expressive and powerful than specialized types like
&lt;code&gt;NonZeroUSize&lt;&#x2F;code&gt;, but serves as a good fallback for the general case.&lt;&#x2F;p&gt;
&lt;p&gt;This crate also provides an answer to the question &amp;quot;Can &lt;em&gt;all&lt;&#x2F;em&gt; my types be completely tight?&amp;quot; I
mentioned that the only exception holding us back from a resounding &amp;quot;yes&amp;quot; is the
case where our type&#x27;s responsibility is to restrict the values of its
fields. Thankfully, that&#x27;s exactly the case this library takes care of in a
general way, so it ensures everything can be taken to 100% tightness.&lt;&#x2F;p&gt;
&lt;p&gt;Using this library, we can rework our &lt;code&gt;Account&lt;&#x2F;code&gt; type to be a lot shorter:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Account {
   username: Username,
   password: Password,
}

&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; NOTE: For maximum safety, you&amp;#39;d probably want these to be on a separate
&#x2F;&#x2F; module so their internals aren&amp;#39;t reachable by the methods in `Account`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
bound!(Username: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;String &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;where |&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
   s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;8 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;all&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::is_alphabetic)
});

bound!(Password: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;String &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;where |&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
   s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;8 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;16 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;all&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::is_alphanumeric)
});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By definition, the &lt;code&gt;Username&lt;&#x2F;code&gt; and &lt;code&gt;Password&lt;&#x2F;code&gt; types &lt;em&gt;always&lt;&#x2F;em&gt; fulfill these
conditions, which means the &lt;code&gt;Account&lt;&#x2F;code&gt; type is 100% tight. You could argue that
this is all pointless, and that all we&#x27;ve done is move invariant checks from
the methods of &lt;code&gt;Account&lt;&#x2F;code&gt; into the methods of these new types instead. And while
you&#x27;re absolutely correct, imaginary strawman, I&#x27;ll argue that it brings many
benefits of varying degrees of subtlety, which I&#x27;ll try to defend in the next
section.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The takeaway of this post should not be that you should use my library, this
is a technical piece, not an ad. Still, if you want to experiment and write some code
following this approach, I&#x27;ve written it to make it as simple as possible to
apply the concept of 100% tight types. Let me know any thoughts or pain points
you have when messing with it!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;reaping-the-benefits-of-perfect-tightness&quot;&gt;Reaping the benefits of perfect tightness&lt;a class=&quot;zola-anchor&quot; href=&quot;#reaping-the-benefits-of-perfect-tightness&quot; aria-label=&quot;Anchor link for: reaping-the-benefits-of-perfect-tightness&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;So what does all of this nonsense afford us? Why go through the trouble of
thinking of type tightness first, and developing the API later? Here are the
benefits I&#x27;ve found when applying this approach:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-pushes-you-towards-the-right-abstractions&quot;&gt;1 - Pushes you towards the right abstractions&lt;a class=&quot;zola-anchor&quot; href=&quot;#1-pushes-you-towards-the-right-abstractions&quot; aria-label=&quot;Anchor link for: 1-pushes-you-towards-the-right-abstractions&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;When you define a structured type with multiple interrelated fields, held together by
a bunch of logic, it&#x27;s generally a sign that there are missing abstractions.
Take this silly example:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Fleet {
   number_of_cars: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Must be less than 4*cars
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;   total_wheels: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
   monthly_revenue: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using the &lt;code&gt;tightness&lt;&#x2F;code&gt; crate, the only way to enforce invariants across two
fields would be to define a type that wraps them. The process of solving that
problem would naturally lead to the missing &lt;code&gt;Car&lt;&#x2F;code&gt; abstraction, with an invariant
over its number of wheels.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-more-expressiveness-from-safely-exposed-internals&quot;&gt;2 - More expressiveness from safely exposed internals&lt;a class=&quot;zola-anchor&quot; href=&quot;#2-more-expressiveness-from-safely-exposed-internals&quot; aria-label=&quot;Anchor link for: 2-more-expressiveness-from-safely-exposed-internals&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s go back to our Account example, with a twist:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Woah, why is everyone looking at me?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Account {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;username: Username,
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;password: Password,
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You&#x27;ll notice we&#x27;ve made both fields public. If all invariants are held by the
type definition and not its methods, this means it&#x27;s &lt;em&gt;always&lt;&#x2F;em&gt; safe to expose the
internals to the users. This has a bunch of practical benefits, such as allowing
them to use expressive tools like destructuring, pattern matching and split
borrows.  The alternative of offering &lt;code&gt;getters&lt;&#x2F;code&gt; and &lt;code&gt;setters&lt;&#x2F;code&gt; for fields can be
rigid and limiting in comparison.&lt;&#x2F;p&gt;
&lt;p&gt;The flexibility extends to giving the user tools to store, process and
manipulate the invariant holders in whichever way they see fit. Rather than go
to Account&#x27;s module documentation and methods to ensure they&#x27;re building a
&lt;code&gt;String&lt;&#x2F;code&gt; the right way, their attention can be limited to the single point of
&lt;code&gt;Username&lt;&#x2F;code&gt; and &lt;code&gt;Password&lt;&#x2F;code&gt; definition.&lt;&#x2F;p&gt;
&lt;p&gt;This doesn&#x27;t mean that everything &lt;em&gt;should&lt;&#x2F;em&gt; be public all the time, though
wanting a field of a 100% tight type be private can be a smell test. If the
field is truly irrelevant to the user, does it have to be there?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-apis-are-cleaner-with-fewer-error-returns&quot;&gt;3 - APIs are cleaner, with fewer error returns&lt;a class=&quot;zola-anchor&quot; href=&quot;#3-apis-are-cleaner-with-fewer-error-returns&quot; aria-label=&quot;Anchor link for: 3-apis-are-cleaner-with-fewer-error-returns&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Typically, invariants will be reflected in the API in one way or another. At
worst, methods will panic when fed invalid input. At best, there will be some
&lt;code&gt;Result&lt;&#x2F;code&gt; returns with expressive &lt;code&gt;Error&lt;&#x2F;code&gt; types. Why not just do away with all
that?&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Old `Account`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Account {
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_password&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: String) -&amp;gt; PasswordError { &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;*...*&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; }
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_username&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;username&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: String) -&amp;gt; UsernameError { &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;*...*&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; }
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;PasswordError {
    PasswordTooShort,
    PasswordTooLong,
    PasswordNotAlphanumeric,
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;UsernameError {
    UsernameTooLong,
    UsernameNotAlphabetical
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Uh, so many ways to go wrong. By tightening &lt;code&gt;Account&lt;&#x2F;code&gt;, we can outright remove
not only the error variants, but the functions themselves. Even if we keep the
fields private for whatever reason, they&#x27;d become significantly simpler:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; New `Account`. Look Ma, no errors!
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Account {
   &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; It&amp;#39;s probaby best to not have these methods at all, but still
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_password&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: Password) { &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;*...*&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; }
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_username&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;username&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: Username) { &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;*...*&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;4-no-regressions-when-adding-functionality&quot;&gt;4 - No regressions when adding functionality&lt;a class=&quot;zola-anchor&quot; href=&quot;#4-no-regressions-when-adding-functionality&quot; aria-label=&quot;Anchor link for: 4-no-regressions-when-adding-functionality&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;When working with a &amp;quot;loose&amp;quot; type, it doesn&#x27;t matter if the current behaviour
perfectly respects invariants; We have to remain ever vigilant that new methods
don&#x27;t invalidate all our previous work. Let&#x27;s say that in a day of drunken
coding we decide to add a new method to make our passwords UBER SECURE.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Something feels off...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Account {
   username: String,
   password: String,
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Account {
   &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Rotates each character a number of positions in the ascii table
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;rotate_password&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;amount&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) {
      self.password &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.password.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| (c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; amount) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;();
   }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Spot the problem? Yeah, we&#x27;ve blown a huge hole in the invariants of our struct.
Even if our setters and getters enforce the Password rules, we&#x27;ve now made it
possible to create a password that isn&#x27;t alphanumeric. With our &lt;code&gt;tightness&lt;&#x2F;code&gt;
based type, this wouldn&#x27;t have been possible:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Account {
   username: Username,
   password: Password,
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Account {
   &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Rotates each character a number of positions in the ascii table
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;rotate_password&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;amount&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) {
       &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; This will panic!!!
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;       self.password.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;mutate&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;p &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;p).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| (c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; amount) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;());
   }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Delegating the invariants to our type definition saves the day: our
&lt;code&gt;rotate_password&lt;&#x2F;code&gt; method is caught red handed (in this case with a panic, but
&lt;code&gt;tightness&lt;&#x2F;code&gt; also offers less explosive ways to mutate your bounded types).&lt;&#x2F;p&gt;
&lt;p&gt;In a similar way to how &lt;code&gt;unsafe&lt;&#x2F;code&gt; helps us focus our attention on the critical
bits during code review, making our types tight means we only have to worry
about invariants when working on the type definition, and not so much during
methods.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Again, I don&#x27;t claim to be treading new ground here. It&#x27;s likely that the ideas
behind this approach have been expressed in other terms many times before,
and I wouldn&#x27;t be surprised if the exact concept I&#x27;m talking about is old news
to people who really know what they&#x27;re doing with types.&lt;&#x2F;p&gt;
&lt;p&gt;My attempt with this post is to give you a set of simple tools and heuristics to
experiment with that have helped me design better types and, as a result, safer
and more elegant code.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;ve enjoyed the read and think there&#x27;s some merit to it,
I challenge you to a game: Write your next small project with a
tightness-first approach. Before writing a single &lt;code&gt;impl&lt;&#x2F;code&gt; block, ensure your type
is incapable by construction of holding invalid data. You&#x27;re welcome to use my
&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;tightness&quot;&gt;tightness&lt;&#x2F;a&gt; crate or create your own
types. Then when you&#x27;re done, &lt;em&gt;please&lt;&#x2F;em&gt; let me know how it went via
&lt;a href=&quot;mailto:cuervo@ecorax.net&quot;&gt;email&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;nofrp5&#x2F;tightness_driven_development_in_rust&#x2F;&quot;&gt;reddit comment&lt;&#x2F;a&gt; or discord DM (Corax#0426).
Even if you hate my guts at the end of it, I&#x27;ll be glad to hear it!&lt;&#x2F;p&gt;
&lt;p&gt;As always, thanks for sticking around. Happy rusting!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>The GPIO war: macro bunkers for typestate explosions (2)</title>
            <pubDate>Mon, 12 Apr 2021 00:00:00 +0000</pubDate>
            <link>https://www.ecorax.net/macro-bunker-2/</link>
            <guid>https://www.ecorax.net/macro-bunker-2/</guid>
            <description>&lt;p&gt;After managing to shake off the impostor&#x27;s syndrome long enough for
another post, I&#x27;m back with the follow-up to &lt;a href=&quot;https:&#x2F;&#x2F;www.ecorax.net&#x2F;macro-bunker-1&#x2F;&quot;&gt;last month&#x27;s GPIO war
stories&lt;&#x2F;a&gt;. In the previous entry we looked at the
horror of
GPIO registers, and managed to assuage the fears of the borrow checker with the
promises of a clean, pure, typestate-powered pin representation. That&#x27;s well
and good, but it&#x27;s time to make those platonic pins drive some &lt;em&gt;real, honest
hardware&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;A word of warning: This entry contains copious amounts of &lt;code&gt;unsafe&lt;&#x2F;code&gt;. We&#x27;re
entering the sinister world of arbitrary memory dereferences, so please consult
your physician, priest, or board of directors before attempting to replicate
anything you&#x27;re about to see. That said, not all &lt;code&gt;unsafe&lt;&#x2F;code&gt; blocks are made equal,
and a theme through this entry will be to choose the ones least likely to come
back and bite us. Onward!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;a-naive-freestyle-approach&quot;&gt;A naive, freestyle approach&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-naive-freestyle-approach&quot; aria-label=&quot;Anchor link for: a-naive-freestyle-approach&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Last time, partly for dramatic effect, partly to segue into the clever typestate
bits, we introduced a rather crude way of driving pins that is all too familiar to
people who know that &lt;em&gt;Misra&lt;&#x2F;em&gt; is not a town in Final Fantasy VII:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_gpio&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) {
    assert!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;in_range&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(port, index));
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; register &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; port {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;A&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x0001000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;*...*&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
    } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;*mut u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;register &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;|= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; index;
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yeah, don&#x27;t do that.&lt;&#x2F;p&gt;
&lt;p&gt;Why am I bringing it up? Because now that we have some
scaffolding in the form of unique, managed &lt;code&gt;Pin&lt;&#x2F;code&gt; structs, it doesn&#x27;t really seem
that bad to fill them in with implementations like the above, right? This is where we left
off:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; PORT: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; INDEX: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; OutputPin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Pin&amp;lt;Output, PORT, INDEX&amp;gt; {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_low&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) { unimplemented!() }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_high&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) { unimplemented!() }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Putting them both together, we could envision something like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; PORT: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; INDEX: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; OutputPin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Pin&amp;lt;Output, PORT, INDEX&amp;gt; {
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_high&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) {
       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; port_base_address &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PORT_BASE_ADDRESS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PORT &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;A&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;];
       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; register &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(port_base_address &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SET_REGISTER_OFFSET&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;*mut u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;register &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;|= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;; }
   }
   &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Is this wrong? Well...&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d say it&#x27;s the code equivalent of &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;scBY3cVyeyA?t=205&quot;&gt;that chair scene in
&lt;em&gt;Contact&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;, and it makes me uneasy for
two reasons. The immediate one is that you can&#x27;t guarantee the compiler won&#x27;t
mess with the write——&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;core&#x2F;ptr&#x2F;fn.write_volatile.html&quot;&gt;core::ptr::write_volatile&lt;&#x2F;a&gt;
exists for that——but even if we were to solve that by calling the right
core library function we&#x27;d face deeper problems. Lets look at the questions we
asked ourselves last time, and wonder if this approach provides good
responses.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Is the pin correctly configured? - &lt;em&gt;Yes, enforced by the typestate&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Is the read + write operation atomic? - &lt;em&gt;Nope&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;What if something else is writing to the same port register? - &lt;em&gt;Horror&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Am I the only one writing to a specific pin? - &lt;em&gt;Yes, enforced by the limited
constructor&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We get two out of four, so we&#x27;re off the mark. Even if we scored better against
that checklist, the reality is that writing modules this way doesn&#x27;t scale.
Conveniently hiding out of view, the &lt;code&gt;PORT_BASE_ADDRESS&lt;&#x2F;code&gt; and
&lt;code&gt;SET_REGISTER_OFFSET&lt;&#x2F;code&gt; constants would have to be manually written, likely copied
from the datasheet. Each module would depend on dozens of these
constants, gated behind feature flags for chip variants. Manual duplication
breeds errors, the kind that are difficult to find and diagnose. So how do we
fix this?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-big-blob-of-xml&quot;&gt;A big blob of XML&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-big-blob-of-xml&quot; aria-label=&quot;Anchor link for: a-big-blob-of-xml&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Enter &lt;a href=&quot;https:&#x2F;&#x2F;www.keil.com&#x2F;pack&#x2F;doc&#x2F;CMSIS&#x2F;SVD&#x2F;html&#x2F;index.html&quot;&gt;CMSIS-SVD&lt;&#x2F;a&gt;
files——If you&#x27;re using Cortex-M, of course, or at the very least an architecture for
which an SVD file can be generated. If you aren&#x27;t, I wish you good luck and
godspeed, and ask that you bring back some nice souvenirs from your travels.&lt;&#x2F;p&gt;
&lt;p&gt;SVD files are big chunks of XML that define exactly how and where to access a
microcontroller&#x27;s collection of peripherals. When I say big, I mean it:
efm32gg11&#x27;s one stands at an impressive 200k lines. If we
dig for the GPIO &amp;quot;data out&amp;quot; section we saw on a screenshot in the last entry, it
looks like this:&lt;&#x2F;p&gt;
&lt;figure class=&quot;center&quot;&gt;
      &lt;img src=&quot;svd.png&quot; alt=&quot;Data Out Register in SVD&quot; class=&quot;center&quot; &#x2F;&gt;
      &lt;figcaption class=&quot;center&quot;&gt;Data Out
Register in SVD file&lt;&#x2F;figcaption&gt;
   &lt;&#x2F;figure&gt;
&lt;p&gt;All the information required to interface with this peripheral is neatly
contained in these tags. Great! Now all we need is a way to access this
information from our &lt;code&gt;gpio&lt;&#x2F;code&gt; module.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-is-a-pac-man&quot;&gt;What is a PAC, man?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-is-a-pac-man&quot; aria-label=&quot;Anchor link for: what-is-a-pac-man&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Since CMSIS-SVD is XML, and hence easy to parse, there &lt;a href=&quot;https:&#x2F;&#x2F;www.keil.com&#x2F;pack&#x2F;doc&#x2F;CMSIS&#x2F;SVD&#x2F;html&#x2F;svd_SVDConv_pg.html&quot;&gt;tools out
there&lt;&#x2F;a&gt; to
convert all that information to C header files, and fortunately, also &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;svd2rust&#x2F;0.17.0&#x2F;svd2rust&#x2F;&quot;&gt;to Rust
modules&lt;&#x2F;a&gt;. Many microcontrollers
already have such modules available as published crates, but don&#x27;t be
discouraged if yours doesn&#x27;t: The instructions in the &lt;code&gt;svd2rust&lt;&#x2F;code&gt; crate are
pretty easy to follow and the process surprisingly painless.&lt;&#x2F;p&gt;
&lt;p&gt;Following the steps in the documentation will turn your SVD file into a shiny
PAC (Peripheral Access Crate). I&#x27;m not going to lie to you, the source you&#x27;ll get
is a bit crowded and robotic, with the metallic taste of auto-generated code.
Thankfully &lt;code&gt;cargo doc&lt;&#x2F;code&gt; packages it in a fairly digestible form, with all the
vendor-provided explanatory notes copied over as docstring comments. Clever!&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;NOTE: Through this entry I will often refer to &lt;code&gt;GPIO&lt;&#x2F;code&gt; (note the
capitalization), which is the name of the &lt;code&gt;PAC&lt;&#x2F;code&gt; object granting us low-level
access to GPIO peripherals. This is as opposed to &lt;code&gt;Gpio&lt;&#x2F;code&gt;, which is the type
we defined in the last entry, which constructs &lt;code&gt;Pin&lt;&#x2F;code&gt; structs.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The &lt;code&gt;svd2rust&lt;&#x2F;code&gt; crate documentation covers how to use its &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;svd2rust&#x2F;0.17.0&#x2F;svd2rust&#x2F;#peripheral-api&quot;&gt;peripheral API&lt;&#x2F;a&gt; to read, write and
modify registers. While last post was all about writing the &lt;em&gt;rules&lt;&#x2F;em&gt; of
peripheral access, missing the &lt;em&gt;mechanics&lt;&#x2F;em&gt;, it seems we get the mechanics for
free, so it should just be a matter of putting them together. Easy! Rust is
great!&lt;&#x2F;p&gt;
&lt;p&gt;Hold on a moment.&lt;&#x2F;p&gt;
&lt;p&gt;There are no happy endings in embedded. This is a bleak, lifeless word of
suffering and datasheet squinting. The few happy endings we get are
hard-fought, not the kind where we save Earth but those in which
it explodes and we find another planet to repopulate or something. So let&#x27;s
give our problem a first stab, and find out exactly what dangers await us.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; INDEX: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; OutputPin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Pin&amp;lt;Output, &amp;#39;A&amp;#39;, INDEX&amp;gt; {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_high&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) {
        cortex_m::interrupt::free(|_| {
           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
              (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;GPIO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::ptr()).pa_dout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;modify&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| { w.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(r.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)) })
           }
        }
    }

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_low&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) {
        cortex_m::interrupt::free(|_| {
           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
              (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;GPIO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::ptr()).pa_dout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;modify&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| { w.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(r.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)) })
           }
        }
    }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Jeez, that&#x27;s some high-density symbol soup. Let&#x27;s break it down.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;anatomy-of-a-write&quot;&gt;Anatomy of a write&lt;a class=&quot;zola-anchor&quot; href=&quot;#anatomy-of-a-write&quot; aria-label=&quot;Anchor link for: anatomy-of-a-write&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; INDEX: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; OutputPin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Pin&amp;lt;Output, &amp;#39;A&amp;#39;, INDEX&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above reads &amp;quot;we&#x27;re implementing the OutputPin trait for any
output-configured pin in port A&amp;quot;. This is not how we want things
to look in the final implementation——if we did, we&#x27;d have to replicate this code
block for ports &#x27;B&#x27;, &#x27;C&#x27;, &#x27;D&#x27;...——but we&#x27;re doing it this way for now for the sake of
simplicity.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;   (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;GPIO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::ptr()).pa_dout
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This scary looking bit means that we&#x27;re stealing the &lt;em&gt;data out&lt;&#x2F;em&gt; register off the
hierarchy that our PAC enforces. We&#x27;re unsafely bypassing the ownership rules of
the PAC and getting a &amp;quot;back door&amp;quot; into the GPIO struct member. So early, and we&#x27;re
already breaking the rules! For most other peripherals, we&#x27;d want to respect
the PAC hierarchy and build a wrapper around the PAC type:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Flash {
    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; MSC stands for Memory System Controller
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    msc: efm32pac::MSC,
}

&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;... Somewhere in our entry point:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; peripherals &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;efm32pac::Peripherals::take().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; We pass ownership of the unique PAC object to our wrapper
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; mcu_flash &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;flash::Flash::new(peripherals.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;MSC&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then simply access the specific registers through it:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; We access the `status` register directly through the owned PAC object.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;is_busy&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ self.msc.status.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;busy&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bit_is_set&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Look at how tame and sane that looks! But that wouldn&#x27;t make for a good blog
entry, because we&#x27;ve come here to suffer. This approach doesn&#x27;t work for the
&lt;code&gt;gpio&lt;&#x2F;code&gt; module, because of the split responsibility problem we covered in the first
entry——we want &lt;code&gt;Pin&lt;&#x2F;code&gt;s to reside in completely different, independent
sections of the application, without the need to worry about interactions at a distance.&lt;&#x2F;p&gt;
&lt;p&gt;We could try to make each pin hold a reference to its associated port register,
but then they&#x27;d have to hold a pointer all the way back to their &lt;code&gt;Gpio&lt;&#x2F;code&gt; parent, which is
heavy and unnecessary. It also wouldn&#x27;t solve the main problem of calling &lt;code&gt;modify&lt;&#x2F;code&gt;
from different contexts, which is a method defined on a &lt;code&gt;!Sync&lt;&#x2F;code&gt; type. If we want to interface
with a &lt;code&gt;!Sync&lt;&#x2F;code&gt; type from different contexts we&#x27;re going to need the full power
of &lt;code&gt;unsafe&lt;&#x2F;code&gt; anyway, so at that stage we might as well just steal the registers from the
&lt;code&gt;PAC&lt;&#x2F;code&gt; with &lt;code&gt;GPIO::ptr()&lt;&#x2F;code&gt; and save us the cost of a reference.&lt;&#x2F;p&gt;
&lt;p&gt;If we&#x27;re lucky, we may be able to ignore the synchronization problem altogether
if our implementation only calls &lt;code&gt;read&lt;&#x2F;code&gt; and &lt;code&gt;write&lt;&#x2F;code&gt; (for example, in the case
our microcontroller offers &lt;code&gt;set&lt;&#x2F;code&gt; and &lt;code&gt;clear&lt;&#x2F;code&gt; registers). &lt;code&gt;read&lt;&#x2F;code&gt; and &lt;code&gt;write&lt;&#x2F;code&gt; are
typically atomic operations and thus we don&#x27;t need to worry about preemption. If
we plan to call &lt;code&gt;modify()&lt;&#x2F;code&gt; however, we need to provide an answer to the question
&amp;quot;What happens if I&#x27;m halfway through a &lt;code&gt;modify()&lt;&#x2F;code&gt; and an interrupt triggers
another &lt;code&gt;modify()&lt;&#x2F;code&gt; call on the same register?&amp;quot;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This may seem obvious, but note that marking our &lt;code&gt;Pin&lt;&#x2F;code&gt; structs &lt;code&gt;!Sync&lt;&#x2F;code&gt; doesn&#x27;t
help since they share internal references to a single &lt;code&gt;!Sync&lt;&#x2F;code&gt; object. If
&lt;code&gt;Pa0&lt;&#x2F;code&gt; and &lt;code&gt;Pa1&lt;&#x2F;code&gt; exist in different contexts and they can both call
&lt;code&gt;modify&lt;&#x2F;code&gt; on the same register, we&#x27;re in trouble.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;making-port-access-safe-and-polite&quot;&gt;Making port access safe and polite&lt;a class=&quot;zola-anchor&quot; href=&quot;#making-port-access-safe-and-polite&quot; aria-label=&quot;Anchor link for: making-port-access-safe-and-polite&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The first instinct of an experienced rustacean could be to reach for the
typical synchronization toolkit and concoct a mix of &lt;code&gt;Arc&lt;&#x2F;code&gt;, &lt;code&gt;Rc&lt;&#x2F;code&gt;, &lt;code&gt;Mutex&lt;&#x2F;code&gt;,
&lt;code&gt;RwLock&lt;&#x2F;code&gt; so each pin can hold a well-behaved reference to its port register.
This won&#x27;t work for us for a few different reasons.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Most of what I&#x27;ve mentioned isn&#x27;t available in &lt;code&gt;no_std&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We&#x27;d be burdening our pins, which are thus far nicely
zero-sized, with heavy machinery.&lt;&#x2F;li&gt;
&lt;li&gt;You really, really, &lt;em&gt;really&lt;&#x2F;em&gt; don&#x27;t want to lock a mutex from within an
interrupt context, and we want interrupt service routines to be able to drive
and read pins.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The root of the problem is that the &lt;code&gt;modify&lt;&#x2F;code&gt; call is not atomic. If it were
impossible to preempt, we could just spread the pins far and wide without having
to worry about data races. So the simplest solution to the problem seems to be
to disable preemption during the brief read-write cycle required to update the
value of a register. And thus, after a
long detour, we come to understand this line:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;cortex_m::interrupt::free(|_| { &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;* ... *&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; })
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The closure we pass will be executed inside a critical section, guaranteeing* that
our &lt;code&gt;modify&lt;&#x2F;code&gt; operation will behave atomically. Since most methods in our &lt;code&gt;Pin&lt;&#x2F;code&gt;
structs are one-liners with a single register operation, this approach will
serve us well enough for the entire module.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;* This guarantee only holds for single-core scenarios,
which is thankfully our case. The only source of data races we have to worry
about is interrupts. If we have to consider multiple cores, the problem
becomes significantly more complicated and beyond the scope of this post.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;removing-the-last-footgun&quot;&gt;Removing the last footgun&lt;a class=&quot;zola-anchor&quot; href=&quot;#removing-the-last-footgun&quot; aria-label=&quot;Anchor link for: removing-the-last-footgun&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Alright, we&#x27;ve made it impossible for the &lt;code&gt;Pin&lt;&#x2F;code&gt; structs to cause trouble to each
other, no matter how far their travels take them. However, there remains one
risk: What if the user decides to play with the PAC &lt;code&gt;GPIO&lt;&#x2F;code&gt; struct
themselves? They can do this safely through the PAC hierarchy, and it could
lead to unsoundness, given that we unsafely steal that reference with our dirty
&lt;code&gt;ptr()&lt;&#x2F;code&gt; trick. This means we need to lock the user away from touching the PAC &lt;code&gt;GPIO&lt;&#x2F;code&gt; struct:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Gpio {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: efm32pac::GPIO) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
        matrix! { construct_gpio [a b c d e f g h i j k l] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;] }
    }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the very same &lt;code&gt;Gpio&lt;&#x2F;code&gt; struct we defined last entry, which you&#x27;ll remember
is the only thing in the universe capable of generating objects of type &lt;code&gt;Pin&lt;&#x2F;code&gt;.
By taking a &lt;code&gt;efm32pac::GPIO&lt;&#x2F;code&gt; by value, we throw away the only safe key to the
PAC &lt;code&gt;GPIO&lt;&#x2F;code&gt; peripheral. Now &lt;code&gt;Gpio&lt;&#x2F;code&gt;, and &lt;em&gt;only&lt;&#x2F;em&gt; &lt;code&gt;Gpio&lt;&#x2F;code&gt;, can drive these registers.&lt;&#x2F;p&gt;
&lt;p&gt;Incidentally, this addition also fulfills one of the requirements from last entry:
it forces the &lt;code&gt;Gpio&lt;&#x2F;code&gt; struct to be unique. By requiring the ownership of a
PAC &lt;code&gt;GPIO&lt;&#x2F;code&gt; in order to construct our &lt;code&gt;Gpio&lt;&#x2F;code&gt; wrapper, we guarantee both safety
and uniqueness.&lt;&#x2F;p&gt;
&lt;p&gt;Continuing on with another bit of our &lt;code&gt;set_high&lt;&#x2F;code&gt; function...&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ah, our good, misunderstood friend &lt;code&gt;unsafe&lt;&#x2F;code&gt;. We need it here for two reasons.
One is the dereference of a raw pointer &lt;code&gt;GPIO::ptr()&lt;&#x2F;code&gt; as discussed. The second
is subtler but also worth highlighting; writing multiple bits to a register at
once is considered unsafe by the PAC, simply because the
SVD file isn&#x27;t expressive enough to guarantee every combination of bits written
to a register is valid.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, all that&#x27;s left is the operation itself:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;modify&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| { w.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(r.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)) })
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A closure is passed that reads the register, toggles on a specific bit and
writes the result back.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;expanding-our-horizons&quot;&gt;Expanding our horizons&lt;a class=&quot;zola-anchor&quot; href=&quot;#expanding-our-horizons&quot; aria-label=&quot;Anchor link for: expanding-our-horizons&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Now that we have a working &lt;code&gt;set_high&lt;&#x2F;code&gt; method, it isn&#x27;t too difficult to imagine
the rest. Pin reads, toggles and mode changes are pretty similar to what we&#x27;ve
written, and you can check them out in the &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;PabloMansanet&#x2F;5d6da2ff4e1725dc46fe6767fec6cbee&quot;&gt;finished module
source&lt;&#x2F;a&gt;
linked at the end of this entry. Our next step is, then, to address the
limitation we mentioned at the start: Our &lt;code&gt;set_high&lt;&#x2F;code&gt; function is only
implemented for port &lt;code&gt;A&lt;&#x2F;code&gt;, and we want it defined on every port.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s give it a try, shall we?&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; INDEX: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; PORT: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; OutputPin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Pin&amp;lt;Output, PORT, INDEX&amp;gt; {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_high&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) {
        cortex_m::interrupt::free(|_| {
           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
              (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;GPIO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::ptr()).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;?????&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;modify&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| { w.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(r.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)) })
           }
        }
    }

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_low&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) {
        cortex_m::interrupt::free(|_| {
           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
              (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;GPIO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::ptr()).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;?????&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;modify&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| { w.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(r.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)) })
           }
        }
    }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So far so good. We&#x27;ve expanded the &lt;code&gt;impl&lt;&#x2F;code&gt; block to be generic not only over the
index, but also over the port. All that&#x27;s necessary now is fill those question marks so
that &lt;code&gt;set_high&lt;&#x2F;code&gt; and &lt;code&gt;set_low&lt;&#x2F;code&gt; write to the appropriate register depending
on the port they&#x27;re defined on.&lt;&#x2F;p&gt;
&lt;p&gt;Alright, let&#x27;s take a look at the PAC &lt;code&gt;GPIO&lt;&#x2F;code&gt; register block in more detail. In
particular, the types of its registers named &lt;code&gt;pa_dout&lt;&#x2F;code&gt;, &lt;code&gt;pb_dout&lt;&#x2F;code&gt;, etc:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub type &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;PA_DOUT &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= crate&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::Reg&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, _PA_DOUT&amp;gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;_PA_DOUT;

&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; ...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub type &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;PB_DOUT &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= crate&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::Reg&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, _PB_DOUT&amp;gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;_PB_DOUT;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ha, that looks familiar, doesn&#x27;t it? Looks like the PAC is also typestate
based, nice! Surely, this will make it very easy to interface with those types.
We just need to find a common trait that allows us to refer to a &amp;quot;writable&amp;quot;
register generically. In fact, we could summarize our last requirement as a
function of the form you see below, where &lt;code&gt;?????&lt;&#x2F;code&gt; is some trait that allows us
to write bits to a register:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;get_data_out_register&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; PORT: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;gpio&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;GPIO) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;dyn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;????? &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PORT &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;A&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;gpio.pa_dout,
      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;B&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;gpio.pb_dout,
      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;   }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Well... About that...&lt;&#x2F;p&gt;
&lt;p&gt;Look, the &lt;code&gt;svd2rust&lt;&#x2F;code&gt; crate is very smart. It&#x27;s capable of understanding each
register&#x27;s unique rules of access and generating a precise API for it. However,
it isn&#x27;t smart enough to notice when groups of registers are closely
related enough to be treated in a common way. There is a common &lt;code&gt;Writable&lt;&#x2F;code&gt;
trait, but it&#x27;s just a marker. For all intents and purposes every register is
its own unique type, no matter how frustratingly similar they may seem.&lt;&#x2F;p&gt;
&lt;p&gt;It seems then that our approach above is not going to work. Bummer. What do we
do when we have multiple things that behave very similarly——in fact, identically
in terms of syntax——but are seen as different by the
compiler? That&#x27;s right, we reach for our powerful friend the macro.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;As far as I&#x27;m aware there&#x27;s no better solution than reaching for macros
here——and every HAL crate I&#x27;ve seen does it——but there&#x27;s a chance I&#x27;m missing
a cleaner way to solve the problem. If you know it, please let me know via
email or reddit! (Links at the end).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;With macros, it&#x27;s often a good idea to start at the point of usage with an ideal
syntax. We want to be able to modify registers in a generic
and compact way, so let&#x27;s draft it:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; PORT: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; INDEX: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; OutputPin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Pin&amp;lt;Output, PORT, INDEX&amp;gt; {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_low&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ gpio_modify!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, dout, |&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| { w.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(r.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)) }) }
    }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_high&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ gpio_modify!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, dout, |&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| { w.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(r.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)) }) }
    }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note how we&#x27;ve kept &lt;code&gt;unsafe&lt;&#x2F;code&gt;, but not the critical section. Hiding &lt;code&gt;unsafe&lt;&#x2F;code&gt; in a
macro would be all kinds of yucky, but an irrelevant detail like the
&lt;code&gt;::cortex_m::interrupt::free&lt;&#x2F;code&gt; invocation can be conveniently swept under the
rug, especially in the case an outer &lt;code&gt;unsafe&lt;&#x2F;code&gt; block is already calling the
user&#x27;s attention to this area of the code.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s build our macro from top to bottom:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;macro_rules! &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;gpio_modify {
    (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$port&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$register_name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, |&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$read&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$write&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$block&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
        gpio_modify_inner!(
            [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;A&amp;#39; &amp;#39;B&amp;#39; &amp;#39;C&amp;#39; &amp;#39;D&amp;#39; &amp;#39;E&amp;#39; &amp;#39;F&amp;#39; &amp;#39;G&amp;#39; &amp;#39;H&amp;#39; &amp;#39;I&amp;#39; &amp;#39;J&amp;#39; &amp;#39;K&amp;#39; &amp;#39;L&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;]
            [a b c d e f g h i j k l]
            $port, $register_name, |$read, $write| $block
        );
    };
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Macro syntax can be intimidating, but this one isn&#x27;t really doing much. It just takes a set of arguments
(most importantly &lt;code&gt;$port&lt;&#x2F;code&gt; and &lt;code&gt;$register_name&lt;&#x2F;code&gt;) and passes them down to an inner
macro, alongside a big blob of letters from A to L in two different formats. All
the meat is in &lt;code&gt;gpio_modify_inner&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;macro_rules! &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;gpio_modify_inner {
    ([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;($character:literal)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$letter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$port&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$register_name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, |&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$read&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$write&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$block&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
        paste::item&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;! &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
            ::cortex_m::interrupt::free(|_| {
                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PORT &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;($character &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;GPIO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::ptr()).[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;p $letter &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;_ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;$register_name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;modify&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|$read, $write| $block) })&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+
                    _ =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;core::panic&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;Unexpected port&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;),
                }
            })
        }
    };
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Again, we have to thank our local hero David Tolnay for the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dtolnay&#x2F;paste&quot;&gt;paste&lt;&#x2F;a&gt; crate, which allows us to conjure
identifiers out of nothing. The best way to understand what the macro above is
doing is to expand it manually:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;gpio_modify!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, dout, |&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| { w.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(r.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)) })

&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; The above expands into...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::cortex_m::interrupt::free(|_| {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PORT &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;A&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;GPIO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::ptr()).pa_dout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;modify&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| { w.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(r.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)) }) }
       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;B&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;GPIO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::ptr()).pb_dout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;modify&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| { w.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(r.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)) }) }
       &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; ...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;_ =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;core::panic&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;Unexpected port&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;),
    }
})
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since &lt;code&gt;PORT&lt;&#x2F;code&gt; is known at compile time, we have the guarantee that the &lt;code&gt;match&lt;&#x2F;code&gt;
statement will be optimized away. The match statement is simply a trick which
allows us to select an operation on a completely different type for each value
of a compile time constant.&lt;&#x2F;p&gt;
&lt;p&gt;Whew, we&#x27;re done! All that&#x27;s left is replicating the approach above for the
&lt;code&gt;read&lt;&#x2F;code&gt; and &lt;code&gt;write&lt;&#x2F;code&gt; calls, then fill the obvious blanks. We&#x27;re finally free!&lt;&#x2F;p&gt;
&lt;p&gt;You may have noticed a significant drop in the amount and quality of banter in
this last section, for which I deeply apologize——I really racked my brain to
make it as understandable as I could. I&#x27;ll make sure to include twice the
colourful analogies in the next entry!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;conclusions-and-source&quot;&gt;Conclusions and source&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusions-and-source&quot; aria-label=&quot;Anchor link for: conclusions-and-source&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I&#x27;m once again aware that this kind of code is not what most people need to do
on the regular, but I&#x27;m hoping that regardless of your background you were able
to take with you something of value. All the source for this module is
&lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;PabloMansanet&#x2F;5d6da2ff4e1725dc46fe6767fec6cbee&quot;&gt;available here&lt;&#x2F;a&gt;,
and it will of course be part of &lt;code&gt;Loadstone&lt;&#x2F;code&gt; as soon as we&#x27;re ready to open
source it.&lt;&#x2F;p&gt;
&lt;p&gt;In the next entry, I&#x27;ll address all reader questions——I have a neat list of
comments from various sources on the first entry, which haven&#x27;t gone unnoticed,
I promise——and finally take a look at pin alternate functions, as well as how to
limit peripheral drivers to only be able to take supported pins. Stay tuned!&lt;&#x2F;p&gt;
&lt;p&gt;As always, looking forward to your feedback in the rust subreddit, community
discord (I&#x27;m Corax over there) and over at my &lt;a href=&quot;mailto:cuervo@ecorax.net&quot;&gt;email&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Happy rusting!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>The GPIO war: macro bunkers for typestate explosions</title>
            <pubDate>Sat, 20 Mar 2021 00:00:00 +0000</pubDate>
            <link>https://www.ecorax.net/macro-bunker-1/</link>
            <guid>https://www.ecorax.net/macro-bunker-1/</guid>
            <description>&lt;p&gt;As most embedded developers I&#x27;m addled by a disease: code vertigo. I like my
code flush to the earth, where I can take an ear to the ground and hear the
fuzzy rumble of electrons and the crackle of dodgy solder joints. When code at
that level collapses it makes a hell of a noise but it doesn&#x27;t fall too
far; digging through datasheets is often enough to put the pieces back together.&lt;&#x2F;p&gt;
&lt;p&gt;When code rests on layers I don&#x27;t fully understand I get all nauseous.  Suddenly
all winds seem strong and I feel the need to inch away from the windows. &lt;em&gt;They
told me there&#x27;s rebar in there but I don&#x27;t know man, it seems like bare concrete
to me.  Hey, what&#x27;s that little inscription in the beam... &amp;quot;Certified Misra C&amp;quot;?
AHHH RUN! TAKE THE EMERGENCY EXIT!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Anyway. The consequence is often an inordinate amount of time spent
understanding the layers beneath my code and, when not satisfied,
building them from scratch. Working with Rust has done a lot to alleviate this
sickness; it&#x27;s the guarantee that beams are carbon steel and all asbestos is
confined to tidy &lt;em&gt;unsafe&lt;&#x2F;em&gt; boxes. However the instinct prevails, not necessarily
out of mistrust for these layers but the need to understand the techniques
involved.&lt;&#x2F;p&gt;
&lt;p&gt;When I started work on the &lt;code&gt;Loadstone&lt;&#x2F;code&gt; bootloader at Bluefruit
Software, I stood on the shoulders of giants even
at the relative shallows of bare metal code. To support our first target, an
&lt;a href=&quot;https:&#x2F;&#x2F;www.st.com&#x2F;en&#x2F;evaluation-tools&#x2F;32f412gdiscovery.html&quot;&gt;STM32F412ZGT6 Discovery
Kit&lt;&#x2F;a&gt;, we worked
on top of three major layers:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;1-The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-embedded&#x2F;cortex-m-rt&quot;&gt;Cortex-M minimal runtime&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;2-The &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;stm32f4&#x2F;0.13.0&#x2F;stm32f4&#x2F;index.html&quot;&gt;svd2rust generated stm32f4 PAC&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;3-The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;stm32-rs&#x2F;stm32f4xx-hal&quot;&gt;stm32f4xx-hal&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Loadstone, along with other Rust components developed in-house at Bluefruit,
will be open sourced soon! I&#x27;ll link to them from this blog as soon as I have
the green light.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;These worked beautifully and didn&#x27;t warrant any inquiry or turning up of
anyone&#x27;s nose. Foundations proved solid, but a bit of vertigo still kicked in.
The claim that the PAC is fully machine-generated from a &lt;a href=&quot;https:&#x2F;&#x2F;www.keil.com&#x2F;pack&#x2F;doc&#x2F;CMSIS&#x2F;SVD&#x2F;html&#x2F;svd_Format_pg.html&quot;&gt;SVD
file&lt;&#x2F;a&gt; seemed
too good to be true——seriously, peripheral access has killer ergonomics——and some
of the macro-powered HAL modules were a tough sell for my team in terms of
readability.&lt;&#x2F;p&gt;
&lt;p&gt;We recently had the chance to port Loadstone to a
&lt;a href=&quot;https:&#x2F;&#x2F;www.silabs.com&#x2F;wireless&#x2F;wi-fi&#x2F;wgm160-series-1-modules&quot;&gt;WGM160P&lt;&#x2F;a&gt;. The
brains on this thing are a Cortex-M4 powered &lt;a href=&quot;https:&#x2F;&#x2F;www.silabs.com&#x2F;mcu&#x2F;32-bit&#x2F;efm32-giant-gecko&quot;&gt;EFM32GG (giant gecko)&lt;&#x2F;a&gt;. This chip is
significantly less supported than the ubiquitous stm32 family, so I took the
opportunity to dig a bit deeper on layers two and three.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s not much to say about &lt;code&gt;svd2rust&lt;&#x2F;code&gt;; it was painless to use and it did
generate a PAC crate nearly identical to the stm32 one, only requiring a quick
rename of a register named &lt;code&gt;async&lt;&#x2F;code&gt; which the compiler didn&#x27;t like for
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;keywords.html&quot;&gt;obvious reasons&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Layer three, the &lt;code&gt;hal&lt;&#x2F;code&gt; implementation, is where the fun began. I couldn&#x27;t find
much out there for this particular microcontroller, so I took it to
progressively develop the parts that we&#x27;d need for the project, with the
intention of making them conform to the universal embedded hal and releasing them
publicly.&lt;&#x2F;p&gt;
&lt;p&gt;This article will take us on a journey through the process of writing
a Rust module as low level as it gets. Brace for impact!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;gpio-the-borrow-checker-s-nemesis&quot;&gt;GPIO: The Borrow Checker&#x27;s nemesis&lt;a class=&quot;zola-anchor&quot; href=&quot;#gpio-the-borrow-checker-s-nemesis&quot; aria-label=&quot;Anchor link for: gpio-the-borrow-checker-s-nemesis&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The first question a microcontroller
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hardware_abstraction&quot;&gt;hal&lt;&#x2F;a&gt; needs to answer is how
to drive GPIOs. &lt;em&gt;GPIO&lt;&#x2F;em&gt; stands for &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;General-purpose_input&#x2F;output#:%7E:text=A%20general-purpose%20input%2Foutput,and%20are%20unused%20by%20default.&quot;&gt;general purpose
input&#x2F;output&lt;&#x2F;a&gt;,
and it&#x27;s the soul of most embedded applications. GPIOs are what lights the LEDs,
what reads the button presses, what drives serial communications, what
controls a motor&#x27;s speed via pulse-width modulation. If a feature physically
touches the external world a GPIO is probably involved. And like most
foundational pieces, it&#x27;s one you better get right.&lt;&#x2F;p&gt;
&lt;p&gt;GPIOs also happen to be Rust&#x27;s worst nightmare.&lt;&#x2F;p&gt;
&lt;p&gt;If you show the borrow checker the GPIO section of a typical MCU datasheet, it
will lunge for the closest corner, curl up in fetal position, and cry. The way
GPIOs are driven in most MCUs I&#x27;ve worked with is anathema to the borrow
checker, and the reason is the harsh contrast between how we perceive pin
ownership and how it&#x27;s actually implemented in hardware.&lt;&#x2F;p&gt;
&lt;p&gt;We like to assign pins to different software modules with
clear boundaries. &lt;code&gt;PB6&lt;&#x2F;code&gt; is passed to &lt;code&gt;led.c&lt;&#x2F;code&gt;, which is the LED pin.
&lt;code&gt;button.c&lt;&#x2F;code&gt;gets &lt;code&gt;PC12&lt;&#x2F;code&gt;, which is the button pin. All is good in our abstract
software model, but beneath the surface lurks horror, corruption and pain.&lt;&#x2F;p&gt;
&lt;p&gt;GPIOs are typically organized in ports. Notice the arbitrary pin names in the
previous paragraph; the port would be the &lt;code&gt;B&lt;&#x2F;code&gt; in &lt;code&gt;PB6&lt;&#x2F;code&gt;, and the &lt;code&gt;C&lt;&#x2F;code&gt; in &lt;code&gt;PC12&lt;&#x2F;code&gt;.
Each port is further subdivided in pins. How these pins are configured and
driven differs between specific vendors and chip families, but typically
involves writing and reading certain memory mapped &lt;em&gt;port registers&lt;&#x2F;em&gt;, which
aggregate a particular action for all of that port&#x27;s pins.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Yes, I say &amp;quot;typically&amp;quot; a lot. We embedded developers are terrified of making
sweeping architectural statements because there&#x27;s &lt;em&gt;very crazy stuff out
there&lt;&#x2F;em&gt;. Did you know not all bytes are 8 bits long?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Let&#x27;s look at an example of such a port register, from the MCU&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.silabs.com&#x2F;documents&#x2F;public&#x2F;reference-manuals&#x2F;EFM32GG-RM.pdf&quot;&gt;reference
manual&#x27;s&lt;&#x2F;a&gt;
section 32.5.4:&lt;&#x2F;p&gt;
&lt;figure class=&quot;center&quot;&gt;
      &lt;img src=&quot;gpio_px_dout.png&quot; alt=&quot;Data Out Register&quot; class=&quot;center&quot; &#x2F;&gt;
      &lt;figcaption class=&quot;center&quot;&gt;Data Out
Register for port X&lt;&#x2F;figcaption&gt;
   &lt;&#x2F;figure&gt;
&lt;p&gt;This is how your typical &amp;quot;data out&amp;quot; register looks like. This sits somewhere in
your memory map, and you write 16-bit words to its lower half to dictate whether
the pins in this port get all excited and full of electrons. Note a few things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;There is a &lt;code&gt;x&lt;&#x2F;code&gt; in the name. That&#x27;s a placeholder for the port, which means
there is one of these for each GPIO port. &lt;code&gt;GPIO_PA_DOUT&lt;&#x2F;code&gt;, &lt;code&gt;GPIO_PD_DOUT&lt;&#x2F;code&gt;, and
so forth.&lt;&#x2F;li&gt;
&lt;li&gt;The top half of the register is unused, as there are only 16 bits per port.&lt;&#x2F;li&gt;
&lt;li&gt;Not reflected in the image, but writing to this register only makes sense for
pins that are configured as output. Configuring pins happens through registers
similar to the one above.&lt;&#x2F;li&gt;
&lt;li&gt;Doing things to a pin configured in the wrong mode ranges from silently
failing to venting the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Magic_smoke&quot;&gt;fabled
smoke&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;An experienced embedded dev will see the &lt;code&gt;RW&lt;&#x2F;code&gt; access and notice an important
implication: If you&#x27;re only interested in setting a specific pin, you must
respect the rest of the register! Clumsily slamming
a &lt;code&gt;0x1 &amp;lt;&amp;lt; 5&lt;&#x2F;code&gt; on that register will light up pin five, but will also shut
all the others down. I highlight this because vendor register naming can be
inconsistent, and &amp;quot;data out&amp;quot; may have stood for a different style of &lt;em&gt;set&lt;&#x2F;em&gt; register
where you simply write &lt;code&gt;1&lt;&#x2F;code&gt; to each pin you want to raise, without disturbing
the rest.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The specifics of how these registers work differ from MCU to MCU. Even something
as simple as setting the logic level of a pin can come in a few different
flavors. You may have to write a &lt;code&gt;1&lt;&#x2F;code&gt; to the appropriate bit of a &amp;quot;clear&amp;quot;
register to bring the pin low, or you may be offered the option to toggle a pin
regardless of the initial state.&lt;&#x2F;p&gt;
&lt;p&gt;Specifics aside, the attentive, paranoid and scarred reader probably notices the
problem already. These register &amp;quot;bit soups&amp;quot; care nothing about our abstract
separation of pin functions. All pins are claustrophobically close in the
hardware world. &lt;code&gt;PB5&lt;&#x2F;code&gt; may drive a lowly LED, while &lt;code&gt;PB6&lt;&#x2F;code&gt; controls your safety
critical, &lt;em&gt;please-don&#x27;t-toggle-or-everything-explodes&lt;&#x2F;em&gt; vacuum valve relay, and they
are &lt;em&gt;one bit apart in your memory map&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Thankfully, as the practice software development is built on pure, solid ground, a
problem as old as this has long been solved by serious engineers and is unlikely
to cause any trouble in practice... Right?&lt;&#x2F;p&gt;
&lt;p&gt;Why am I doing this to myself.&lt;&#x2F;p&gt;
&lt;p&gt;Yeah, no. Pin mishaps are an embedded classic and they come up in many forms,
with consequences ranging from the silent to the explosive. The
typical approach in the C world is to rely on vendor-provided libraries that
boil down to walls of &lt;code&gt;#define __SOME_UNREADABLE_THING  = (0b1 &amp;lt;&amp;lt; _DAYS_IN_A_LEAP_YEAR &amp;amp;= !~WEIGHT_OF_A_HUMAN_SOUL | _MASK_OF_EL_ZORRO)&lt;&#x2F;code&gt;. These can
do the trick, but you&#x27;re often one typo away from frobbing the wrong bit, or
frobbing the right bit wrong.&lt;&#x2F;p&gt;
&lt;p&gt;Surely we can do better.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;building-gpios-on-rust&quot;&gt;Building GPIOs on Rust&lt;a class=&quot;zola-anchor&quot; href=&quot;#building-gpios-on-rust&quot; aria-label=&quot;Anchor link for: building-gpios-on-rust&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Last section probably gave you an idea why our anthropomorphic borrow checker
wouldn&#x27;t want to touch GPIOs with a ten foot pole. Tiny chunks of memory gating
wide, potentially undefined, potentially catastrophic effects bound to entirely
different software modules. So what can we do to appease it?&lt;&#x2F;p&gt;
&lt;p&gt;I mean... We &lt;em&gt;could&lt;&#x2F;em&gt; bypass it altogether. Children, please close your eyes:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_gpio&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) {
    assert!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;in_range&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(port, index));
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; register &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; port {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;A&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x0001000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;*...*&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
    } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;*mut u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;register &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;|= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; index;
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ugh. Beyond answering the frequent question &amp;quot;Can Rust replace C word for word&amp;quot;,
this doesn&#x27;t really help. Marking the function unsafe is almost a moral
imperative given how many things can go wrong:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Is the pin correctly configured?&lt;&#x2F;li&gt;
&lt;li&gt;Is the read + write operation atomic?&lt;&#x2F;li&gt;
&lt;li&gt;What if something else is writing to the same port register?&lt;&#x2F;li&gt;
&lt;li&gt;Am I the only one writing to a specific pin?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;What and what not to mark unsafe is an interesting question in
embedded, since we&#x27;re dealing with resources beyond raw memory.  I
like to mark as unsafe any functions that may, through misuse, lead to a MCU
peripheral being left in an undefined state.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;While an approach like the above &amp;quot;works&amp;quot;, it shifts the burden of correctness to
the layers above. In order to do better, we need to rescue our friend the borrow
checker from its despair and teach it how to manage GPIOs. In the next section,
we&#x27;ll completely leave aside the &lt;em&gt;mechanics&lt;&#x2F;em&gt; of pin writes, reads and modes,
and we&#x27;ll instead focus solely on modeling pins in a way the borrow checker can
understand.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;a-pin-ownership-model&quot;&gt;A pin ownership model&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-pin-ownership-model&quot; aria-label=&quot;Anchor link for: a-pin-ownership-model&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The borrow checker reasons about the ownership of variables. We want only a
single pin of each index and port combination to exist, and thus we need to
define a type to model those pins so the borrow checker can track them. Here&#x27;s a
first stab:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Pin {
    port: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
    index: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
    mode: Mode,
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This... Eh. I mean, it&#x27;s not &lt;em&gt;wrong&lt;&#x2F;em&gt;, but it isn&#x27;t great. In the world of C,
this kind of structure is what you&#x27;d reach for if you wanted to step away from
relying solely on the preprocessor. The problem with a foundation like this is
that we have to answer all of the important questions &lt;em&gt;at runtime&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Do I have the right pin? -&amp;gt; check the pin member variables at runtime.&lt;&#x2F;li&gt;
&lt;li&gt;Am I on the right mode -&amp;gt; Again, I check the pin members. This also raises the
uncomfortable question of what to do when the user calls an invalid function,
like &lt;code&gt;set_high()&lt;&#x2F;code&gt; on an input pin. Does the program crash? Do we burden the API
with &lt;code&gt;Result&lt;&#x2F;code&gt; returns in all functions?&lt;&#x2F;li&gt;
&lt;li&gt;Is there a single owner of a &lt;code&gt;Pin&lt;&#x2F;code&gt; with a given &lt;code&gt;port&lt;&#x2F;code&gt;+&lt;code&gt;index&lt;&#x2F;code&gt; combination? -&amp;gt;
Probably rely on some runtime constructor logic that refuses to produce more
than one of the same pin.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The above questions will typically require runtime computation, complication of
the API——pin methods need to be fallible to account for being called in the
wrong mode——and a memory footprint. Spending three bytes plus padding to earmark
a MCU pin doesn&#x27;t seem like much, but every stack byte counts when you&#x27;re
resource limited.&lt;&#x2F;p&gt;
&lt;p&gt;The borrow checker is not crying anymore, but is still brooding in the corner,
judging us. We need to do better. And to do better we need
&lt;a href=&quot;http:&#x2F;&#x2F;cliffle.com&#x2F;blog&#x2F;rust-typestate&#x2F;&quot;&gt;typestates&lt;&#x2F;a&gt;. Following our building analogy typestates are aerospace grade titanium alloy. A
resource modeled properly via typestates just &lt;em&gt;cannot be used wrong&lt;&#x2F;em&gt;, and this
is enforced at compile time.&lt;&#x2F;p&gt;
&lt;p&gt;When we use typestates a resource is represented by multiple related types,
as opposed to a single type with fields reflecting its state. Methods are
only defined for typestates where they make sense, which means invalid operations
cannot be expressed. The typestate approach is what most popular Rust HAL crates
use and it looks roughly like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Pin&amp;lt;MODE, PORT, PIN&amp;gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;* *&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, a set of marker structs specify pin characteristics and
classify behaviour. A block starting with &lt;code&gt;impl&amp;lt;PORT, PIN&amp;gt; Pin&amp;lt;Output, PORT, PIN&amp;gt;&lt;&#x2F;code&gt; would only describe behaviour available to output pins, while one that
begins with &lt;code&gt;impl&amp;lt;MODE&amp;gt; Pin&amp;lt;MODE, PortB, Pin1&amp;gt;&lt;&#x2F;code&gt; would only apply to &lt;code&gt;PB1&lt;&#x2F;code&gt;,
regardless of mode.&lt;&#x2F;p&gt;
&lt;p&gt;In the ancient times of four months ago this was the only approach to
describing pin typestates, and hence most popular embedded-hal crates look
vaguely like the above. However, now we can make it even nicer thanks to the
recent stabilization of
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;79135&quot;&gt;min_const_generics&lt;&#x2F;a&gt;, noting that
port and index can be represented by scalars:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Pin&amp;lt;MODE, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; PORT: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; INDEX: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; { &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;* ... *&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And with this, we arrive to the pin representation that &lt;code&gt;Loadstone&lt;&#x2F;code&gt; uses in its
&lt;code&gt;hal&lt;&#x2F;code&gt; for the &lt;code&gt;efm32gg&lt;&#x2F;code&gt; pins:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub mod &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;typestate {
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;NotConfigured;
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Input;
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Output;
}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;typestate::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Pin&amp;lt;MODE, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; PORT: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; INDEX: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; {
   _marker: PhantomData&amp;lt;MODE&amp;gt;,
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s take inventory of where we are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I like giving typestates their own namespace——even though it&#x27;s immediately
pulled in——just to have a bit of hygiene when looking at this GPIO module from
the outside world.&lt;&#x2F;li&gt;
&lt;li&gt;If you haven&#x27;t come across &lt;code&gt;PhantomData&lt;&#x2F;code&gt; before, it can be a bit of a head
scratcher. Zero sized and weightless, it&#x27;s a ghost that exists only to tell
the type system &amp;quot;Hey, &lt;em&gt;pretend&lt;&#x2F;em&gt; there is something here of type &lt;code&gt;MODE&lt;&#x2F;code&gt;&amp;quot;.
&lt;code&gt;PhantomData&lt;&#x2F;code&gt; is cool and shows up often in very good code, so don&#x27;t get
spooked.&lt;&#x2F;li&gt;
&lt;li&gt;Since the only field in the pin is zero-sized, we arrive at the first positive
consequence of using typestates: our pin representations don&#x27;t take any space
in the stack (or the heap, if you&#x27;re fancy enough to afford one, look at you
with all that memory to spare!). Any decisions made around these types
will ultimately be compiled down to direct writes and reads to the adequate
registers, and all trace of the struct will vanish from the final binary.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now that we have a pin representation, we can start to classify behaviour based
on the typestates:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; PORT: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; INDEX: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; OutputPin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Pin&amp;lt;Output, PORT, INDEX&amp;gt; {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_low&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) { unimplemented!() }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;set_high&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) { unimplemented!() }
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; PORT: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; INDEX: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; TogglePin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Pin&amp;lt;Output, PORT, INDEX&amp;gt; {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;toggle&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) { unimplemented!() }
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; PORT: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; INDEX: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; InputPin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Pin&amp;lt;Input, PORT, INDEX&amp;gt; {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;is_high&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ unimplemented!() }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;is_low&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;is_high&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;OutputPin&lt;&#x2F;code&gt;, &lt;code&gt;TogglePin&lt;&#x2F;code&gt; and &lt;code&gt;InputPin&lt;&#x2F;code&gt; come from the layer above and are meant
to abstract away the board, manufacturer and MCU details. For now we have no
need to treat the pins any differently based on their port or index, though
we&#x27;ll revisit that assumption in later blog entries. For now, all we&#x27;ve
expressed is that toggling and setting are only possible on pins that are
configured as output, and reading makes sense exclusively for pins configured as
input.&lt;&#x2F;p&gt;
&lt;p&gt;How do we transform these types? Skimming the datasheet shows us that there&#x27;s no
hidden gotcha when reconfiguring pins between different modes, so let&#x27;s keep it
simple and make a few universal conversion methods:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;MODE, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; PORT: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; INDEX: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; Pin&amp;lt;MODE, PORT, INDEX&amp;gt; {
    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Private constructor to ensure there only exists one of each pin.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ _marker: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::default() } }

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as_input&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; Pin&amp;lt;Input, PORT, INDEX&amp;gt; { unimplemented!() }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as_output&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; Pin&amp;lt;Output, PORT, INDEX&amp;gt; { unimplemented!() }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as_disabled&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; Pin&amp;lt;NotConfigured, PORT, INDEX&amp;gt; { unimplemented!() }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The snippet above is pretty unassuming, but I&#x27;d like to spend a moment here as
it encapsulates a lot of what makes Rust amazing. None of this will be all that
exciting to Haskell veterans or anyone with functional programming background,
but I come from a background of just banging bits together so this is all still
pretty magical:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A common first concern when dealing with unbounded typestates is that it&#x27;s
very easy to conjure concrete types that don&#x27;t make sense. Yes, you can name a
&lt;code&gt;Pin&amp;lt;Potato, &#x27;W&#x27;, 42&amp;gt;&lt;&#x2F;code&gt;; the compiler will look at you funny but won&#x27;t judge.
Thankfully there&#x27;s no way you can ever actually &lt;em&gt;construct&lt;&#x2F;em&gt; one, thanks to
the private constructor.&lt;&#x2F;li&gt;
&lt;li&gt;This &lt;code&gt;impl&lt;&#x2F;code&gt; block exposes public methods capable of returning pins. In most
other languages this would clash directly with the requirement of only
holding one single pin of each port-index combination. However, the borrow
checker comes to our rescue by enforcing that for every &lt;code&gt;A2&lt;&#x2F;code&gt; pin that gets
generated, an &lt;code&gt;A2&lt;&#x2F;code&gt; gets destroyed and forgotten——note the &lt;code&gt;self&lt;&#x2F;code&gt; parameter.
Thus, uniqueness is maintained in a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Ship_of_Theseus&quot;&gt;Ship of
Theseus&lt;&#x2F;a&gt; kind of way.&lt;&#x2F;li&gt;
&lt;li&gt;There is, and there will only be, a single way to create a pin from nothing,
and that&#x27;s the &lt;code&gt;new&lt;&#x2F;code&gt; function. We&#x27;ve made that function private so we have
full control over when it is called. Notice how the user can&#x27;t simply
construct their own pins because of the private &lt;code&gt;PhantomData&lt;&#x2F;code&gt; field, which is
doing a great job spooking type thieves away——another of its valuable roles in
zero-sized types.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So thus far we have a typestate powered pin struct, a way to convert between
different configurations, and a few methods. I left them all as
&lt;code&gt;unimplemented()&lt;&#x2F;code&gt; as we&#x27;re only focusing on the &lt;em&gt;rules&lt;&#x2F;em&gt; of access. Later in this
blog series we&#x27;ll put the spotlight on the &lt;em&gt;mechanics&lt;&#x2F;em&gt; of access, where we&#x27;ll
have Fun with a capital F writing wrappers around the PAC crate.&lt;&#x2F;p&gt;
&lt;p&gt;We mentioned that the only way pins are created is through the &lt;code&gt;new&lt;&#x2F;code&gt; associated
function. Well, we then have to figure out how and when this function gets
called. Our main requirement is that it must only be called once per pin and
port combination. Let&#x27;s find a way to enforce that.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;rationing-for-the-war-you-only-get-one-pin&quot;&gt;Rationing for the war: You only get one pin!&lt;a class=&quot;zola-anchor&quot; href=&quot;#rationing-for-the-war-you-only-get-one-pin&quot; aria-label=&quot;Anchor link for: rationing-for-the-war-you-only-get-one-pin&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The immediately obvious drawback of typestates is that no matter how
closely related the pins, in the eyes of the compiler they are different
types. This means you&#x27;re not going to have an easy time collecting them into an
array or iterating over them unless you want to bring dynamic dispatch into the
mix, which at this level... Let&#x27;s just say it&#x27;s a bit of a bull in a china shop situation.&lt;&#x2F;p&gt;
&lt;p&gt;So what can we do? If you&#x27;re looking to ration a limited resource, a very natural instinct is to
write a list of the elements you have, and cross out the ones that have already
been assigned:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Gpio {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;claim&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; PORT: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; INDEX: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)
       -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Pin&amp;lt;NotConfigured, PORT, INDEX&amp;gt;&amp;gt;
    {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;already_claimed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) {
            self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;mark_as_claimed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(Pin::new())
        } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;None
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
    }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;Gpio&lt;&#x2F;code&gt; struct in this example would contain a &amp;quot;claimed&amp;quot; data
structure (imagine an array of bools, for simplicity) to
regulate construction. Thus, guaranteeing the uniqueness of our pins would be
reduced to guaranteeing the uniqueness of the &lt;code&gt;Gpio&lt;&#x2F;code&gt; struct which dispenses them.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s nothing fundamentally wrong about this——in fact, we will keep the idea
of guaranteeing pin uniqueness by enforcing a single &lt;code&gt;Gpio&lt;&#x2F;code&gt; struct——but the
details are a bit off. There has been a recurring theme in this blog entry: It
is a good idea to ask ourselves if there&#x27;s a way to pull decisions from runtime
to compile time. A runtime approach like the above is questionable for a few
reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Forces the library user to decide, also at runtime, how they want to deal with
the possibility of a failed pin claim.&lt;&#x2F;li&gt;
&lt;li&gt;A failed claim happens by definition only through API misuse, which is a
compile time mistake. Therefore, by failing at runtime this approach &lt;em&gt;fails
later than it needs to&lt;&#x2F;em&gt;. Fail often, fail early: words to live by.&lt;&#x2F;li&gt;
&lt;li&gt;Even if you want to flex your embedded skills and write the &lt;code&gt;claimed&lt;&#x2F;code&gt; table as
a compact bitset, using it still takes some bytes and some cycles when it
could take zero bytes and zero cycles, which is infinitely fewer bytes and
cycles!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So how do we go about it? Thankfully there&#x27;s no need to reinvent the wheel; the
language already comes with a system to enforce limited collections of
heterogeneous types. Good old struct composition.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Gpio {
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa0: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 0&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa1: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 1&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb0: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 0&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb1: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 1&amp;gt;,
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Gpio {
   &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; We&amp;#39;ll talk later about how to ensure this gets called only once.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
          pa0: Pin::new(),
          pa1: Pin::new(),
          pb0: Pin::new(),
          pb1: Pin::new(),
      }
   }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perfect! Just by constructing a Gpio struct, we get a public field for each pin
that we can just break off. We know they&#x27;re zero-sized, so we aren&#x27;t even being
wasteful. All done; pack it up and ship it!&lt;&#x2F;p&gt;
&lt;p&gt;... What?&lt;&#x2F;p&gt;
&lt;p&gt;What do you mean too long? They don&#x27;t take any space on the stack, they don&#x27;t
impact the code size... Oh, the source code? Come on, don&#x27;t tell me you are
afraid of a bit of copy paste, how bad can it be? Here, let me help you...&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Gpio {
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa0: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 0&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa1: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 1&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa2: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 2&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa3: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 3&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa4: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 4&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa5: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 5&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa6: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 6&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa7: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 7&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa8: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 8&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa9: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 9&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa10: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 10&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa11: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 11&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa12: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 12&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa13: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 13&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa14: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 14&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pa15: Pin&amp;lt;NotConfigured, &amp;#39;A&amp;#39;, 15&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb0: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 0&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb1: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 1&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb2: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 2&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb3: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 3&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb4: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 4&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb5: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 5&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb6: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 6&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb7: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 7&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb8: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 8&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb9: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 9&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb10: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 10&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb11: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 11&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb12: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 12&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb13: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 13&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb14: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 14&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pb15: Pin&amp;lt;NotConfigured, &amp;#39;B&amp;#39;, 15&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc0: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 0&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc1: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 1&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc2: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 2&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc3: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 3&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc4: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 4&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc5: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 5&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc6: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 6&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc7: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 7&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc8: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 8&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc9: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 9&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc10: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 10&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc11: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 11&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc12: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 12&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc13: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 13&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc14: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 14&amp;gt;,
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pc15: Pin&amp;lt;NotConfigured, &amp;#39;C&amp;#39;, 15&amp;gt;,
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ugh, okay, point taken. I&#x27;m only down to the third port and my &lt;code&gt;y&lt;&#x2F;code&gt; and &lt;code&gt;p&lt;&#x2F;code&gt; keys
are worn out. Our typestates have exploded, and we need to take cover. Against
weapons of this caliber we have no recourse but to build a bunker, and for that
we need macros.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Unfortunately, walls of text like the above are pretty common sights in
embedded development. I don&#x27;t know what it is about low level coders but we
seem to love these imposing code blocks. They feel... industrial?
Anyway, be the change you want to see in the world!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I have to admit I was stuck at this spot for some time, trying to wrap my head
around generating identifiers that expand two dimensions; in this case ports and
indices. Fortunately, &lt;em&gt;Yandros&lt;&#x2F;em&gt; from the Rust community discord came to my aid
with an amazing macro suggestion, that I later tweaked into a general purpose
&amp;quot;matrix&amp;quot; generator. Shoutout to Yandros for their constant help and guidance!&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;#[macro_export]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;macro_rules! &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;matrix {
    ( &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$inner_macro&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;tt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$ms&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;tt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;( matrix! { $inner_macro &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;($n $ms)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;});
    ( &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$inner_macro&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;ident &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;( &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;tt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; [$(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$m&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;tt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;] )* ) =&amp;gt;
        ( $inner_macro! { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;( $( $n $m )&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)* } );
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I don&#x27;t have enough blood in my caffeine system to walk through macro syntax
today, so I&#x27;ll keep it simple: &lt;code&gt;matrix&lt;&#x2F;code&gt; takes an inner macro as a
parameter, followed by two sequences of tokens——or &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;proc_macro&#x2F;enum.TokenTree.html&quot;&gt;token
trees&lt;&#x2F;a&gt; to be
specific——and expands them in pairs. So, for example:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;matrix!(my_macro, [a b c] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 2 3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;]);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;... expands into ...&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;my_macro!(a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can see how this can be pretty convenient for our GPIO module, as nearly
everything we do is expressed in port-index pairs we&#x27;d rather not spell out
manually. This reduces our &lt;code&gt;Gpio&lt;&#x2F;code&gt; struct definition to this rather compact form:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;macro_rules! &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;gpio_struct {
    (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;( (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$letter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;tt &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$character&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;tt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$number&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;tt &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)*) =&amp;gt; { paste::item! {
        pub struct Gpio {
            $(
                pub [&amp;lt;p $letter $number&amp;gt;]: Pin&amp;lt;NotConfigured, $character, $number&amp;gt;,
            )+
        }
    }}
}

&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Define a Gpio struct with 15 pins and ports A to L
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;matrix! {
    gpio_struct
    [(a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;A&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;B&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;C&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;D&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;E&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (f &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;F&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (g &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;G&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (h &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;H&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;I&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (j &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;J&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (k &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;K&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (l &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;L&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)]
    [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;]
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There&#x27;s some secret, powerful sauce in the snippet above. Rust macros-by-example
don&#x27;t like you messing with identifiers, so we need to borrow some
procedural magic from the &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;paste&quot;&gt;paste&lt;&#x2F;a&gt; crate in order
to synthesize the field names——&lt;code&gt;pa0&lt;&#x2F;code&gt;, &lt;code&gt;pa1&lt;&#x2F;code&gt;, etc. The wall of text in &lt;code&gt;new()&lt;&#x2F;code&gt;
can be tackled in a similar way:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;macro_rules! &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;construct_gpio {
    (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$letter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;ident&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; $number: literal)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ paste::item&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;! &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;p $letter $number&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;]: Pin::new(),)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
    }}
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Gpio {
   &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; We&amp;#39;ll talk later about how to ensure this gets called only once.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
        matrix! { construct_gpio [a b c d e f g h i j k l] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;] }
    }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Explosion averted! We safely ducked under our macro bunker, and while it is built
out of alien materials and the inscriptions are a mix of cuneiform and ancient
Egyptian, a roof is a roof.&lt;&#x2F;p&gt;
&lt;p&gt;As a neat bonus, here&#x27;s an aliasing macro so we get less wordy analogues to our
pin types, so for example &lt;code&gt;Pin&amp;lt;Output, &#x27;B&#x27;, 3&amp;gt;&lt;&#x2F;code&gt; can be exported as
&lt;code&gt;Pb3&amp;lt;Output&amp;gt;&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;macro_rules! &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pin_aliases {
    (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;( (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$letter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;tt &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$character&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;tt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;$number&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;tt &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)*) =&amp;gt; { paste::item! {
        $(
            pub type [&amp;lt;P $letter $number&amp;gt;]&amp;lt;MODE&amp;gt; = Pin&amp;lt;MODE, $character, $number&amp;gt;;
        )*
    } }
}

matrix! {
    pin_aliases
    [(a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;A&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;B&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;C&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;D&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;E&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (f &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;F&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (g &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;G&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (h &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;H&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;I&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (j &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;J&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (k &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;K&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) (l &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;L&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)]
    [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;]
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;conclusions&quot;&gt;Conclusions&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusions&quot; aria-label=&quot;Anchor link for: conclusions&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Writing drivers at this level may not be something you have any intention of
doing, so I&#x27;d hope you at least take away something of general value as a
consolation for sticking with me through awful analogies and meandering
snippets. Here are some assorted thoughts that came up while writing this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;When building a system for maximum safety, it helps to separate the &lt;em&gt;rules&lt;&#x2F;em&gt;
and the &lt;em&gt;mechanics&lt;&#x2F;em&gt; of access, so you can focus on one thing at a time. Often
the specifics of how resources must be managed get in the way of the design,
and safety suffers as a consequence.&lt;&#x2F;li&gt;
&lt;li&gt;Don&#x27;t fear solutions that pull decisions to compile time at the expense of
readability and source explosion. Source can always be transformed with
macros and readability can be constantly improved. The risks of low
readability are way smaller anyway when all your problems are caught at compile
time!&lt;&#x2F;li&gt;
&lt;li&gt;Typestates are plenty useful even if you have no way to restrict them to a
subset of &amp;quot;correct&amp;quot; types and values. Note how I didn&#x27;t have to specify anywhere
that the &lt;code&gt;INDEX&lt;&#x2F;code&gt; constant must be lower than &lt;code&gt;16&lt;&#x2F;code&gt;; it&#x27;s enforced through our
full control over instantiation.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;discord.com&#x2F;invite&#x2F;aVESxV8&quot;&gt;community discord&lt;&#x2F;a&gt; is great. I
bother people there for help all the time and I&#x27;m constantly humbled by the
quality of code they can produce on a whim. Come over!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is shaping up to be a three part entry. Next, we&#x27;ll talk about how to
actually drive these pins; the PAC crate exposes each register as a unique type
with a fairly complex API, so we&#x27;ll have break our brains mapping those types to
our access model above. Last, we&#x27;ll look at making our access rules even more
powerful by managing which pins can be used by each peripheral to perform
alternate functions, which is a common question during MCU driver development.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;thanks-for-reading&quot;&gt;Thanks for reading!&lt;a class=&quot;zola-anchor&quot; href=&quot;#thanks-for-reading&quot; aria-label=&quot;Anchor link for: thanks-for-reading&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;As always, I welcome feedback of all kinds and shapes, so I&#x27;ll be around on the
rust subreddit, community discord (I&#x27;m Corax over there) and over at my
&lt;a href=&quot;mailto:cuervo@ecorax.net&quot;&gt;email&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Happy rusting!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>As above, so below: Bare metal Rust generics 2&#x2F;2</title>
            <pubDate>Mon, 31 Aug 2020 00:00:00 +0000</pubDate>
            <link>https://www.ecorax.net/as-above-so-below-2/</link>
            <guid>https://www.ecorax.net/as-above-so-below-2/</guid>
            <description>&lt;p&gt;During &lt;a href=&quot;https:&#x2F;&#x2F;www.ecorax.net&#x2F;as-above-so-below-1&#x2F;&quot;&gt;last episode&lt;&#x2F;a&gt;, we went on a tour of the
pleasantly boring world of flash memory, drafted some driver interfaces, and
toyed with the idea of generics at both levels of crate visibility. What&#x27;s
conspicuously absent is, well, &lt;em&gt;working code.&lt;&#x2F;em&gt; It&#x27;s one thing to lay down data
structures, and another entirely to weave generics between the raw ones and
zeros of bare metal firmware. Today we&#x27;ll gaze long into the void*, and,
hopefully, the void* won&#x27;t gaze back into us.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;a-thoroughly-unnecessary-warmup&quot;&gt;A thoroughly unnecessary warmup&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-thoroughly-unnecessary-warmup&quot; aria-label=&quot;Anchor link for: a-thoroughly-unnecessary-warmup&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;In the &lt;a href=&quot;https:&#x2F;&#x2F;www.ecorax.net&#x2F;as-above-so-below-1&#x2F;#what-is-flash-memory&quot;&gt;section about flash
memory&lt;&#x2F;a&gt; we
explored, with the help of a dodgy analogy, how it&#x27;s possible to directly
overwrite a &lt;code&gt;1&lt;&#x2F;code&gt; with a &lt;code&gt;0&lt;&#x2F;code&gt; but not the reverse. This quirk is what makes
writing efficient flash writers a bit tricky. When asked to write over a memory
range, a naive driver would simply erase every sector overlapped by it, then
write back the original data &amp;quot;merged&amp;quot; with the desired bytes. We want our driver
a bit smarter than that; it should first check whether it&#x27;s possible to write
the bytes directly. In other words, we want to ensure that every &lt;code&gt;1&lt;&#x2F;code&gt; in our
intended write is also a &lt;code&gt;1&lt;&#x2F;code&gt; in the target space.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;BitSubset {
    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Check that every &amp;#39;1&amp;#39; bit is a &amp;#39;1&amp;#39; on the right hand side.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;is_subset_of&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;rhs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That looks like a straightforward, simple trait to express the condition we want
to check. Here comes the unnecessary part: We&#x27;re going to implement it
generically. Let&#x27;s be honest, we &lt;em&gt;both&lt;&#x2F;em&gt; know we want to implement this for
&lt;code&gt;[u8]&lt;&#x2F;code&gt;. There shouldn&#x27;t be much use for it other than slices of bytes. However,
doing it this way will help flex our generic muscles and illustrate a couple of
important points.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;T: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Copy &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Eq &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;BitOr&amp;lt;Output=T&amp;gt;&amp;gt; BitSubset &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; [T] {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;is_subset_of&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;rhs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; rhs.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() {
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;false
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
            self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;zip&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(rhs.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;all&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)| (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;| *&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;b) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;== *&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;b)
        }
    }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yes, I feel that dread too. There are enough sigils up there to summon half
the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;The_Lesser_Key_of_Solomon&quot;&gt;Lesser Key of
Solomon&lt;&#x2F;a&gt;. We have
&lt;strong&gt;five&lt;&#x2F;strong&gt; types of brackets (&lt;code&gt;&amp;lt;(|[{&lt;&#x2F;code&gt;) and we&#x27;re barely getting started.
Fortunately symbols are much like ant invasions—live with them long enough and
you&#x27;ll stop noticing. They can even be endearing.&lt;&#x2F;p&gt;
&lt;p&gt;When I started playing with Rust generics a few years ago, it often helped me to
approach functions by parts; focusing first on the constraints, moving to
the implementation only when I&#x27;ve painted a clear picture of the elements involved.
I find there&#x27;s a bit of ritual in deciphering constraints, not unlike the
infamous &lt;a href=&quot;http:&#x2F;&#x2F;c-faq.com&#x2F;decl&#x2F;spiral.anderson.html&quot;&gt;spiral rule&lt;&#x2F;a&gt; for C
declarations. For me, it takes the form of describing them in a
manner of plain English pseudocode. For the above it would look like this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We have &lt;em&gt;something&lt;&#x2F;em&gt; that can be copied and compared.&lt;&#x2F;li&gt;
&lt;li&gt;It can be bitwise or&#x27;d with itself.&lt;&#x2F;li&gt;
&lt;li&gt;We are implementing over an array of it.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For more complex lists I&#x27;d sing these conditions in my head a few times until
the abstract types coalesce into something more manageable, at which point it
becomes possible to push the sigil soup away and focus on behaviour.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;All&lt;&#x2F;strong&gt; the behaviour of these type parameters is summarized in these
constraints. Nothing is implicit. That&#x27;s &lt;em&gt;very cool&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In this case, all that&#x27;s left is a bit of iterator magic and bit wrangling.
&lt;code&gt;self.iter().zip(rhs.iter()).all(Condition)&lt;&#x2F;code&gt; &amp;quot;zips&amp;quot; two iterators together in
pairs, then verifies that every pair satisfies a condition. In our case the
condition is the closure &lt;code&gt;|(a, b)| (*a | *b) == *b&lt;&#x2F;code&gt;. For the condition to hold,
all &lt;code&gt;1&lt;&#x2F;code&gt; bits in element &lt;code&gt;*a&lt;&#x2F;code&gt; must also be &lt;code&gt;1&lt;&#x2F;code&gt; in &lt;code&gt;*b&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll use this later to compare, as we anticipated, slices of bytes. What have
we gained from doing it generically?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Even though &lt;code&gt;T: Copy + Eq + BitOr&amp;lt;Output=T&amp;gt;&lt;&#x2F;code&gt; is certainly a lot wordier
than &lt;code&gt;u8&lt;&#x2F;code&gt;, it&#x27;s also &lt;strong&gt;purer&lt;&#x2F;strong&gt; in some sense, because it more accurately
summarizes what we care about. Weirdly,
the shorter &lt;code&gt;u8&lt;&#x2F;code&gt; carries a lot more extraneous, distracting baggage:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It is 8 bits long, which is a hardware detail we don&#x27;t care about.&lt;&#x2F;li&gt;
&lt;li&gt;It is unsigned, which is a mathematical detail we don&#x27;t care about.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In contrast, our platonic &lt;code&gt;T&lt;&#x2F;code&gt; is refreshingly simple: only does the things
that the implementation needs. And as such, the implementation &lt;em&gt;will be
correct now and forever after&lt;&#x2F;em&gt;, which leads to the next point:&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;When our constraints match the requirements of the implementation so tightly,
we can resort to blanket implementations, knowing that future users will opt
into this behaviour automatically if they define a type that matches these
requirements. Crates like the impressively elegant
&lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;&quot;&gt;Bevy&lt;&#x2F;a&gt; take this idea further, using their prelude to
bring blanket implementations over a wide range of types without exposing the
user to the trait. This leads, I think, to very ergonomic APIs.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Not that we&#x27;d have any reason to suspect otherwise, but the
&lt;a href=&quot;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;5abac4&quot;&gt;concrete&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;nxMW57&quot;&gt;generic&lt;&#x2F;a&gt; versions produce identical assembly.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;We&#x27;ve increased our sigil count, getting closer to summoning
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Kimaris&quot;&gt;Kimaris&lt;&#x2F;a&gt;, Marquis of Hell, ruler of 20
demonic legions, teacher of grammar, logic and rhetoric. Maybe he&#x27;ll finally
produce an intuitive definition of a
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Monad_(functional_programming)&quot;&gt;monad&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;turning-up-the-heat-generic-buffer-overlaps&quot;&gt;Turning up the heat: generic buffer overlaps&lt;a class=&quot;zola-anchor&quot; href=&quot;#turning-up-the-heat-generic-buffer-overlaps&quot; aria-label=&quot;Anchor link for: turning-up-the-heat-generic-buffer-overlaps&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;At &lt;a href=&quot;https:&#x2F;&#x2F;www.ecorax.net&#x2F;as-above-so-below-1&#x2F;#taking-a-step-back&quot;&gt;the end of the last
entry&lt;&#x2F;a&gt;, we sketched out the
constraints on our minimal concept of address and region:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Address: Ord + Copy + Add&amp;lt;usize, Output = Self&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Region&amp;lt;A: Address&amp;gt; {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: A) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;But cuervo&lt;&#x2F;em&gt;, you ask, &lt;em&gt;that&#x27;s not how it looked like last week. You added an&lt;&#x2F;em&gt;
&lt;code&gt;Add&lt;&#x2F;code&gt; &lt;em&gt;constraint.&lt;&#x2F;em&gt; Okay, hypothetical attentive reader, you got me. I may have
forgotten to copy that as I was curating the code examples. Yes, the
&lt;code&gt;core::ops::Add&lt;&#x2F;code&gt; bound will be necessary, as we&#x27;ll see in a bit. This gives us
an excuse to sing the generics song, which works just as well for supertrait
definitons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;code&gt;Address&lt;&#x2F;code&gt; is &lt;em&gt;something&lt;&#x2F;em&gt; that can be sorted and copied. It can be added
together with an offset, yielding another address.&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;code&gt;Region&lt;&#x2F;code&gt; is &lt;em&gt;something&lt;&#x2F;em&gt; that may contain an address.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;What can we build with this? We know that one of the goals of our flash driver
is to smartly negotiate the different write and erase granularities, so that for
any given buffer write, only the required regions are erased. In order to do
this, there&#x27;s a requirement we can accurately summarize in this way:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;For a buffer of given length, and for a base address in the target memory map,
we need to relate each buffer segment to every region it overlaps with.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here rendered through the power of ASCII:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;0    5    10   15   20   25   30   35
-----|ooooooooooooooooooooooooooooo|------ : Buffer of length 30 at address 5
----------|====|====|====|====|----------- : Four regions of length 5 at address 10
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Given the two inputs above, we need to produce the following four views into the
buffer:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;
0    5      10      15      20      25      30   35
-----|ooooo [ooooo] [ooooo] [ooooo] [ooooo] ooooo|-----
             view1   view2   view3   view4
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Our goal in this section is to &lt;em&gt;define such operation generically&lt;&#x2F;em&gt;, and
&lt;em&gt;implement it generically&lt;&#x2F;em&gt;, in such a way that it will work with
last week&#x27;s sectors, subsectors and pages from both drivers.&lt;&#x2F;p&gt;
&lt;p&gt;Now, if you&#x27;re allergic to symbols, be warned: Here be dragons. Henceforth be
dragon turtles, all the way down. We are about to reach &lt;em&gt;ancient Egyptian
shopping in &lt;a href=&quot;https:&#x2F;&#x2F;www.ecorax.net&#x2F;as-above-so-below-2&#x2F;akihabara.jpeg&quot;&gt;Akihabara&lt;&#x2F;a&gt;&lt;&#x2F;em&gt; levels of symbol overload. Believe me
that after some time none of them will feel superfluous or overwrought. As
with human language, precise definitions lead to better understanding.&lt;&#x2F;p&gt;
&lt;p&gt;Okay, let&#x27;s take a deep breath.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Iterator producing block-region pairs,
&#x2F;&#x2F;&#x2F; where each memory block maps to each region
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;OverlapIterator&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, A, R, I&amp;gt;
where
    A: Address,
    R: Region&amp;lt;A&amp;gt;,
    I: Iterator&amp;lt;Item = R&amp;gt;,
{
    memory: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;],
    regions: I,
    base_address: A,
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;IterableByOverlaps&amp;lt;&amp;#39;a, A, R, I&amp;gt;
where
    A: Address,
    R: Region&amp;lt;A&amp;gt;,
    I: Iterator&amp;lt;Item = R&amp;gt;,
{
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;overlaps&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;base_address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: A) -&amp;gt; OverlapIterator&amp;lt;A, R, I&amp;gt;;
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Hmm. Not too bad thus far. We have the tools necessary to break down the &lt;em&gt;where&lt;&#x2F;em&gt;
clause, which is identical for both the struct and the trait. We are dealing
with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Some&lt;&#x2F;em&gt; address &lt;code&gt;A&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Some&lt;&#x2F;em&gt; region &lt;code&gt;R&lt;&#x2F;code&gt; which contains such addresses.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Some&lt;&#x2F;em&gt; iterator &lt;code&gt;I&lt;&#x2F;code&gt; that yields such regions.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The explicit lifetime, a requisite of all structs containing references, simply
denotes that the &lt;code&gt;memory&lt;&#x2F;code&gt; field is a reference to data stored elsewhere, and
guarantees said data will exist &lt;strong&gt;at least&lt;&#x2F;strong&gt; as long as our struct.&lt;&#x2F;p&gt;
&lt;p&gt;What we&#x27;ve defined above is an iterator struct, and a trait for types that can
be iterated in a certain way. If you come from C, iterators can be a bit of a
mind bender. They &lt;em&gt;feel&lt;&#x2F;em&gt; heavy, but ultimately they&#x27;re very
simple. I like to think of iterator structs as bookmarks for physical books;
progress trackers with just enough state to find your position in a sequence.&lt;&#x2F;p&gt;
&lt;p&gt;Looking at our iterator struct above, we see we can track our progress through
the inner &lt;code&gt;regions&lt;&#x2F;code&gt; iterator, until we run out of regions. We also have a means
of producing this kind of iterator—the &lt;code&gt;overlaps&lt;&#x2F;code&gt; function in the
&lt;code&gt;IterableByOverlaps&lt;&#x2F;code&gt; trait—so all that&#x27;s left is to define the &lt;em&gt;rules&lt;&#x2F;em&gt; of
iteration. The implementation I&#x27;m going to show you can do with some manual
optimization, and indeed it doesn&#x27;t look exactly like this in the final
&lt;code&gt;Loadstone&lt;&#x2F;code&gt; code. I went with the slightly more readable option to better
illustrate the points in this article.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, A, R, I&amp;gt; Iterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;OverlapIterator&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, A, R, I&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;where&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
    A: Address,
    R: Region&amp;lt;A&amp;gt;,
    I: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Iterator&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Item = R&amp;gt;,
{
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Item &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;], R, A);

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Item&amp;gt; {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(region) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.regions.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() {
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; block_range &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.memory.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;())
                .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;skip_while&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;region.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(self.base_address &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ *&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;index))
                .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;take_while&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| region.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(self.base_address &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ *&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;index));
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(start) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; block_range.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() {
                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; end &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; block_range.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;last&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;unwrap_or&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(start) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.memory[start&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;end], region, self.base_address &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; start));
            }
        }
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;None
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, A, R, I&amp;gt; IterableByOverlaps&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, A, R, I&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;I
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;where&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
    A: Address,
    R: Region&amp;lt;A&amp;gt;,
    I: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Iterator&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Item = R&amp;gt;,
{
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;overlaps&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;base_address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: A) -&amp;gt; OverlapIterator&amp;lt;A, R, I&amp;gt; {
        OverlapIterator { memory, regions: self, base_address }
    }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Wow, it&#x27;s getting real. Let&#x27;s break it down piece by piece.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, A, R, I&amp;gt; Iterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;OverlapIterator&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, A, R, I&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;where&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
    A: Address,
    R: Region&amp;lt;A&amp;gt;,
    I: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Iterator&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Item = R&amp;gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So far our struct was an iterator in name only. Here we&#x27;re actually implementing
the
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;core&#x2F;iter&#x2F;trait.Iterator.html&quot;&gt;core::iter::Iterator&lt;&#x2F;a&gt;
trait for it. We&#x27;re already familiar with the generics here, the where clause is
the same one we&#x27;ve seen in the iterator struct and trait definition. Moving
on!&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Item &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;], R, A);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the associated type we&#x27;ll be iterating over. Our iterator will yield
tuples of three elements:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A subslice with the already familiar lifetime &lt;code&gt;&#x27;a&lt;&#x2F;code&gt;. That is, a &lt;em&gt;view&lt;&#x2F;em&gt; over the
memory buffer we want to write.&lt;&#x2F;li&gt;
&lt;li&gt;A region &lt;code&gt;R&lt;&#x2F;code&gt;, corresponding to that view.&lt;&#x2F;li&gt;
&lt;li&gt;An address &lt;code&gt;A&lt;&#x2F;code&gt; at the start of that view.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Item&amp;gt; {
     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(region) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.regions.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() {
         &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; [...]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;     }
     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;None
 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above is a common pattern when wrapping an internal iterator. It means  that
we&#x27;ll greedily consume the &lt;code&gt;regions&lt;&#x2F;code&gt; iterator, finally yielding &lt;code&gt;None&lt;&#x2F;code&gt; only when
we run out of regions.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; block_range &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.memory.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;())
    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;skip_while&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;region.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(self.base_address &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ *&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;index))
    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;take_while&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| region.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(self.base_address &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ *&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;index));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here&#x27;s the naive bit, which works well enough for our exploration. We deduce the
range in buffer indices for our slice by skipping all addresses outside the region,
and taking all addresses within the region.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(start) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; block_range.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() {
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; end &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; block_range.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;last&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;unwrap_or&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(start) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.memory[start&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;end], region, self.base_address &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; start));
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally, we yield a slice on those indices, with some provisioning for edge
cases. Next time this &lt;code&gt;next&lt;&#x2F;code&gt; function is called, it will pick up where it left
off.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, A, R, I&amp;gt; IterableByOverlaps&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, A, R, I&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;I
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;where&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
    A: Address,
    R: Region&amp;lt;A&amp;gt;,
    I: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Iterator&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Item = R&amp;gt;,
{
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;overlaps&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;base_address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: A) -&amp;gt; OverlapIterator&amp;lt;A, R, I&amp;gt; {
        OverlapIterator { memory, regions: self, base_address }
    }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the part that glues it all together: a blanket implementation for &lt;em&gt;any&lt;&#x2F;em&gt;
iterator over regions. This is what makes it possible to convert your maps, your
zips and your chains to the iterator of tuples we care about. All this
functionality becomes available just from implementing the much, much simpler
&lt;code&gt;Region&lt;&#x2F;code&gt; and &lt;code&gt;Address&lt;&#x2F;code&gt; traits.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;There was some weeping and gnashing of teeth from my colleagues at the
single-letter type parameter names. On our usual languages of choice at
&lt;a href=&quot;https:&#x2F;&#x2F;www.bluefruit.co.uk&#x2F;&quot;&gt;Bluefruit Software&lt;&#x2F;a&gt;, we always prefer descriptive and
thorough to terse and abbreviated. However, I believe there is a strong
argument for keeping type parameters short: it highlights their flexible,
incorporeal nature and draws attention to the &lt;code&gt;where&lt;&#x2F;code&gt; clause and trait bounds.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;putting-the-pieces-together&quot;&gt;Putting the pieces together&lt;a class=&quot;zola-anchor&quot; href=&quot;#putting-the-pieces-together&quot; aria-label=&quot;Anchor link for: putting-the-pieces-together&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Writing a flash driver that respects bit subsets, transparently merges data and
erases sectors only when required in C is pretty finicky. It often involves
multiple nested loops, off-by-one-prone operations, confusion, pain, dread and
hardfault. This time, we have crafted enough generic glue that tackling the
&lt;code&gt;write&lt;&#x2F;code&gt; method on both our flash drivers is going to be a comparative pleasure.&lt;&#x2F;p&gt;
&lt;p&gt;Going back to last week&#x27;s trait definition, we&#x27;re looking to implement this
function for both of our drivers:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Address, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;]) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Error&amp;gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;ll start with the internal MCU flash, which &lt;a href=&quot;https:&#x2F;&#x2F;www.ecorax.net&#x2F;as-above-so-below-1&#x2F;#descending-into-the-concrete-world&quot;&gt;you&#x27;ll
remember&lt;&#x2F;a&gt; has
a memory map encoded as a &lt;code&gt;const&lt;&#x2F;code&gt; array of sectors of this form:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;#[derive(Copy, Clone, Debug, PartialEq)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Sector {
    block: Block,
    location: Address,
    size: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the MCU flash context, this is the concrete type for our &lt;code&gt;Region&lt;&#x2F;code&gt; trait. We
get &lt;code&gt;Address&lt;&#x2F;code&gt; for free via blanket implementation, so let&#x27;s manually implement
&lt;code&gt;Region&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Region&amp;lt;Address&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Sector {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: Address) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
        (self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; address) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; address)
    }
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Sector {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; Address { self.location }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; Address { Address(self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s all we need to do to have access to all the powerful iterator stuff we
wrote before. The write method unfolds cleanly:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: Address, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;]) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Error&amp;gt; {
     &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; [..] Some boring boundary&#x2F;range&#x2F;alignment checks here
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(block, sector, address) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;MemoryMap::sectors().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;overlaps&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(bytes, address) {
         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; merge_buffer &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;max_sector_size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()][&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;sector.size];
         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; offset_into_sector &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; address.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;saturating_sub&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(sector.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;

         self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(sector.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(), merge_buffer)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; block.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;is_subset_of&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;merge_buffer[offset_into_sector&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;sector.size]) {
             self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;write_bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(block, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;sector, address)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
         } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
             self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;erase&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;sector)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
             merge_buffer
                 .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;iter_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()
                 .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;skip&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(offset_into_sector)
                 .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;zip&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(block)
                 .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;byte &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= *&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;input);
             self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;write_bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(merge_buffer, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;sector, sector.location)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
         }
     }

     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(())
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Some clarifications and notes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;write_bytes&lt;&#x2F;code&gt;, &lt;code&gt;erase&lt;&#x2F;code&gt; and &lt;code&gt;read&lt;&#x2F;code&gt; are very low level, chip-specific functions
that handle the commands and register writes required to actually operate the
flash. There&#x27;s not much to gain from attempting to approach them generically,
so I won&#x27;t expand them here.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;max_sector_size()&lt;&#x2F;code&gt; is a &lt;code&gt;const fn&lt;&#x2F;code&gt; that loops over all sectors in the
memory map, rather than a &lt;code&gt;const&lt;&#x2F;code&gt; value which could go out of sync with the
memory map or be at risk of copy-paste error.&lt;&#x2F;li&gt;
&lt;li&gt;The other functions from our &lt;code&gt;ReadWrite&lt;&#x2F;code&gt; trait are a lot simpler than
&lt;code&gt;write&lt;&#x2F;code&gt;, where all the fun read-write-cycle logic happens, so they don&#x27;t
deserve much analysis.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;different-chip-not-so-different-world&quot;&gt;Different chip, not so different world&lt;a class=&quot;zola-anchor&quot; href=&quot;#different-chip-not-so-different-world&quot; aria-label=&quot;Anchor link for: different-chip-not-so-different-world&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Now that we&#x27;ve assembled our &lt;code&gt;write&lt;&#x2F;code&gt; function, let&#x27;s move back to the external
&lt;a href=&quot;https:&#x2F;&#x2F;www.micron.com&#x2F;-&#x2F;media&#x2F;client&#x2F;global&#x2F;documents&#x2F;products&#x2F;data-sheet&#x2F;nor-flash&#x2F;serial-nor&#x2F;n25q&#x2F;n25q_128mb_1_8v_65nm.pdf&quot;&gt;Micron
N25Q128&lt;&#x2F;a&gt;.
Last week, we modeled this driver&#x27;s memory map pretty differently, as a
collection of functions returning existential iterator types. Another departure
is that we don&#x27;t care about &lt;em&gt;sectors&lt;&#x2F;em&gt; anymore, we care about &lt;em&gt;subsectors&lt;&#x2F;em&gt; and
&lt;em&gt;pages&lt;&#x2F;em&gt; (our new erase and write granularities, respectively), which we modeled
like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Subsector(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Page(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Well, fret not! They may look very different, but deep down they&#x27;re a &lt;code&gt;Region&lt;&#x2F;code&gt;
waiting to happen. Let&#x27;s make it so:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Region&amp;lt;Address&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Subsector {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: Address) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; start &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; Address((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SUBSECTOR_SIZE &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
        (address &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; start) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(address &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; start &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SUBSECTOR_SIZE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)
    }
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Region&amp;lt;Address&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Page {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: Address) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; start &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; Address((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PAGE_SIZE &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
        (address &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; start) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(address &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; start &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PAGE_SIZE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)
    }
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once again, that implementation is all that&#x27;s needed to unlock our generic
powers. With this, we can finally approach the write method:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: Address, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;]) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Error&amp;gt; {
     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(block, subsector, address) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;MemoryMap::subsectors().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;overlaps&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(bytes, address) {
         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; offset_into_subsector &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; address.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;saturating_sub&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(subsector.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; merge_buffer &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x00&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SUBSECTOR_SIZE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;];
         self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(subsector.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; merge_buffer)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; block.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;is_subset_of&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;merge_buffer[offset_into_subsector&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;]) {
             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(block, page, address) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; subsector.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;pages&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;overlaps&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(block, address) {
                 self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;write_page&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;page, block, address)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
             }
         } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
             self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;erase_subsector&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;subsector)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
             merge_buffer
                 .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;iter_mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()
                 .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;skip&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(offset_into_subsector)
                 .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;zip&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(block)
                 .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;byte &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= *&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;input);
             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(block, page, address) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
                 subsector.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;pages&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;overlaps&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;merge_buffer, subsector.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;())
             {
                 self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;write_page&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;page, block, address)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
             }
         }
     }

     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(())
 }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;As you can see, this method looks a lot like the one for our MCU flash. However,
there are a few differences. This time our write granularity is different to our
erase granularity, so rather than writing subsectors directly, there is an inner
iteration of the form &lt;code&gt;for (block, page, address) in subsector.pages().overlaps(block, address)&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Again, &lt;code&gt;write_page&lt;&#x2F;code&gt;, &lt;code&gt;erase_subsector&lt;&#x2F;code&gt; and &lt;code&gt;read&lt;&#x2F;code&gt; are low level, chip specific
functions (in this case sending a few commands over &lt;code&gt;QSPI&lt;&#x2F;code&gt;), beyond the scope
of this series.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Here we see the real benefit of a concrete&#x2F;generic mixed approach. We&#x27;re
seamlessly weaving chip specific logic—the &lt;code&gt;subsector.pages()&lt;&#x2F;code&gt; cascading
memory map style—with our generic &lt;code&gt;overlaps&lt;&#x2F;code&gt; function, without sacrificing
expressiveness in either side.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;That&#x27;s it. We&#x27;ve done it. We&#x27;ve fought demons, dragons, turtles, increased our
tolerance for brackets of multiple shapes, and grown a little bit more generic.
I hope we came out of this with more sanity than we&#x27;ve lost.&lt;&#x2F;p&gt;
&lt;p&gt;I realize I left many details out. This is, after all, a tiny slice of a much
bigger project, and I unapologetically ignored module visibility, dozens of
helper functions, and the justification for many small decisions. I also
suspect—or rather, I &lt;em&gt;know&lt;&#x2F;em&gt;—that I&#x27;ve done many things suboptimally. There&#x27;s
always so much to learn, so let me know in any of the links at the end! Speaking
of which, here&#x27;s a little appendix covering some of the questions I received
after last entry:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;questions-from-last-week&quot;&gt;Questions from last week&lt;a class=&quot;zola-anchor&quot; href=&quot;#questions-from-last-week&quot; aria-label=&quot;Anchor link for: questions-from-last-week&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;If you get the chance, can you include a post on your environment and tooling?
It&#x27;s been a while since I dipped my toes into embedded development, and I&#x27;m
curious what the process and development environment for embedded rust looks
like. - &#x2F;u&#x2F;ricree&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In case my references to demon summoning haven&#x27;t made it abundantly clear I&#x27;m a
bit of a nerd, so I like to stick to &lt;code&gt;neovim&lt;&#x2F;code&gt; with
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fannheyward&#x2F;coc-rust-analyzer&quot;&gt;coc-rust-analyzer&lt;&#x2F;a&gt; for
editing (works amazingly), and raw command line &lt;code&gt;gdb&lt;&#x2F;code&gt; for debugging with an SVD
reader plugin. The debugging experience is not ideal, so I&#x27;m working on my own
rust TUI debugger called beak. I&#x27;ll talk about it more in the future, but here&#x27;s
a sneak peek into what it looks like (if the embed looks too small, try
following &lt;a href=&quot;https:&#x2F;&#x2F;asciinema.org&#x2F;a&#x2F;hKHTrim8aKK21LJdOw3bBD6Tr&quot;&gt;this link&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;script src=&quot;https:&#x2F;&#x2F;asciinema.org&#x2F;a&#x2F;hKHTrim8aKK21LJdOw3bBD6Tr.js&quot;
id=&quot;asciicast-hKHTrim8aKK21LJdOw3bBD6Tr&quot; async&gt;&lt;&#x2F;script&gt;
&lt;blockquote&gt;
&lt;p&gt;Can you add RSS? - multiple people&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I kid you not, last week I had no idea what RSS was. Thankfully uncle Google
did, so now I have a global RSS feed (linked at the bottom of the main page) and
a per-category RSS feed in case you want to filter out any awful fiction I write
in the future. You can find the rust feed under the
&lt;a href=&quot;&#x2F;categories&#x2F;rust&#x2F;&quot;&gt;categories&#x2F;rust&lt;&#x2F;a&gt; section.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Why not make the &lt;code&gt;KB!&lt;&#x2F;code&gt; macro a &lt;code&gt;const fn&lt;&#x2F;code&gt; instead? - multiple people&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It did start that way, actually! I ended up making it a macro as I wanted to
throw in literals of various types without worrying about conversions, i.e:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; bytes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; bytes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; bytes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;i64&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;thanks-for-reading&quot;&gt;Thanks for reading!&lt;a class=&quot;zola-anchor&quot; href=&quot;#thanks-for-reading&quot; aria-label=&quot;Anchor link for: thanks-for-reading&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Again, thanks for sticking around and for your encouraging comments. I&#x27;ll
come back with more Rust programming when I find something exciting to talk
about. Thanks especially to my colleagues at
&lt;a href=&quot;https:&#x2F;&#x2F;www.bluefruit.co.uk&#x2F;&quot;&gt;Bluefruit&lt;&#x2F;a&gt; for sharing my &lt;a href=&quot;https:&#x2F;&#x2F;www.bluefruit.co.uk&#x2F;quality&#x2F;is-rust-ready-for-embedded-software&#x2F;&quot;&gt;enthusiasm about
Rust&lt;&#x2F;a&gt;.
As always, I intend this to be a conversation so I&#x27;ll be happy to answer your
comments on the &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;ijwrxd&#x2F;as_above_so_below_part_2_bare_metal_rust_generics&#x2F;&quot;&gt;reddit
thread&lt;&#x2F;a&gt;
and over &lt;a href=&quot;mailto:cuervo@ecorax.net&quot;&gt;email&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Happy rusting!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>As above, so below: Bare metal Rust generics 1&#x2F;2</title>
            <pubDate>Sun, 23 Aug 2020 00:00:00 +0000</pubDate>
            <link>https://www.ecorax.net/as-above-so-below-1/</link>
            <guid>https://www.ecorax.net/as-above-so-below-1/</guid>
            <description>&lt;p&gt;I&#x27;ve had the pleasure to work with very experienced firmware developers; the
kind of people who know the size of their &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Red_zone_(computing)&quot;&gt;red
zones&lt;&#x2F;a&gt; and routinely
transform coffee into linker scripts and pointer dereferences. In other words,
the &lt;a href=&quot;http:&#x2F;&#x2F;www.catb.org&#x2F;%7Eesr&#x2F;jargon&#x2F;html&#x2F;story-of-mel.html&quot;&gt;Mels&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;system&#x2F;files&#x2F;1311_05-08_mickens.pdf&quot;&gt;Zeus
Hammers&lt;&#x2F;a&gt; of the
world.&lt;&#x2F;p&gt;
&lt;p&gt;When it comes to the tools of our trade, many of them are curious and
experimental. Some of them—very much myself included—explore far enough to leave
pragmatism behind and veer into idealism, stubbornly forcing beautiful round
pegs into industrial square holes. Hey, maybe they&#x27;re square for a reason, but
it doesn&#x27;t hurt to try.&lt;&#x2F;p&gt;
&lt;p&gt;The majority of them aren&#x27;t like that. Your average battle-tested firmware
developer has accrued a healthy distrust of the abstract, probably born of
watching shiny platonic constructs crash and burn with painfully &lt;em&gt;real&lt;&#x2F;em&gt; and
&lt;em&gt;concrete&lt;&#x2F;em&gt; error traces. It is sobering, having to chase a hardfault on a tiny
MCU across enough vtables and templated code to make Herb Sutter puke angle
brackets. No wonder modern approaches are met with some resistance unless the
LOADs and the STOREs are in clear view.&lt;&#x2F;p&gt;
&lt;p&gt;I felt this way too when someone suggested to me, back in 2014, that an
up-and-coming language called &lt;a href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;&quot;&gt;Rust&lt;&#x2F;a&gt; showed promise
in the embedded field. &lt;em&gt;Surely not&lt;&#x2F;em&gt;, I thought, &lt;em&gt;too high level.&lt;&#x2F;em&gt; Even though I
had been playing with it already, my profoundly ingrained bit-twiddling
instincts told me not to trust a language that supported functional programming,
or one that dared to have an &lt;em&gt;opinion&lt;&#x2F;em&gt; on how I managed my memory. Bah! That&#x27;s
how you get philosophers to run out of forks, and your forks to turn into
SIGSEGVs.&lt;&#x2F;p&gt;
&lt;p&gt;I was wrong.&lt;&#x2F;p&gt;
&lt;p&gt;Through the past five years of experimentation, I&#x27;ve gone from intrigued, to
optimistic, to &lt;em&gt;convinced&lt;&#x2F;em&gt; that Rust is an ideal language to build industrial
grade, bulletproof bare metal software. Beyond that, I&#x27;ve come to realize that
even the highest level constructs that the base language offers are applicable
to firmware development, very much unlike other languages that span a wide range
of paradigms (I&#x27;m looking at you, C++). There are a few reasons I felt this way:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Rust&#x27;s safety guarantees and general strictness bring the debug time down
significantly, so there&#x27;s less need to spend time developing mental maps of
how high level constructs correspond to hardware primitives.&lt;&#x2F;li&gt;
&lt;li&gt;The type system is &lt;em&gt;great&lt;&#x2F;em&gt; at enforcing local reasoning and preventing leaky
abstractions. Building decoupled systems with no runtime cost is easy.&lt;&#x2F;li&gt;
&lt;li&gt;The compiler error messages are worthy of an AI assistant with &lt;em&gt;concerning&lt;&#x2F;em&gt;
mind-reading abilities.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Lately, I&#x27;ve had the chance to work on a Rust
&lt;a href=&quot;https:&#x2F;&#x2F;www.st.com&#x2F;en&#x2F;microcontrollers-microprocessors&#x2F;stm32f412.html&quot;&gt;STM32F412&lt;&#x2F;a&gt;
project in a professional setting, with one of the goals being to foster a Rust
knowledge pool at my company. The project, &lt;code&gt;Loadstone&lt;&#x2F;code&gt;, is a 32kb secure
bootloader targeting bare metal devices for the medical industry.&lt;&#x2F;p&gt;
&lt;p&gt;While it would&#x27;ve been easier—and much less of a headache to my colleagues—to
stick to a subset of Rust more familiar to C developers, with your &lt;code&gt;for&lt;&#x2F;code&gt;s, your
&lt;code&gt;*mut u8&lt;&#x2F;code&gt;s and your &lt;code&gt;unsafe&lt;&#x2F;code&gt;s, I instead decided not to pull any punches and
make liberal use of generics, iterator adapters, typestate programming and other
stuff that would&#x27;ve made 2010&#x27;s cuervo cry blood and hug the closest copy of
Kernighan and Ritchie.&lt;&#x2F;p&gt;
&lt;p&gt;The pressures of a real collaborative project have taught me a lot, and many
assumptions have been refined thanks to the criticism of several skilled
outsiders who, as outsiders often do, had a privileged view on things I took for
granted.&lt;&#x2F;p&gt;
&lt;p&gt;A topic that came up frequently in code review is
&lt;a href=&quot;https:&#x2F;&#x2F;thume.ca&#x2F;2019&#x2F;07&#x2F;14&#x2F;a-tour-of-metaprogramming-models-for-generics&#x2F;&quot;&gt;generics&lt;&#x2F;a&gt;.
Perhaps still recovering from a SFINAE nightmare, some colleagues were
unsure about the use of generics to group behaviour that we&#x27;d normally write
separate implementations for. The concerns tended to fall in one of three
categories:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Runtime performance.&lt;&#x2F;li&gt;
&lt;li&gt;Binary size bloat.&lt;&#x2F;li&gt;
&lt;li&gt;Habitability and readability.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The first is easy to dispel, as it often comes from unfamiliarity with static
dispatch. No vtables or heap allocations in anything we&#x27;re doing, promise! The
second concern is valid but I&#x27;ve found it to be negligible in practice; I have
plans for another blog post giving some concrete benchmarks.&lt;&#x2F;p&gt;
&lt;p&gt;The last concern is the most subjective and thus the hardest to argue, so I
decided to focus on it in this blog series. I&#x27;ll go over the design process of
two similar flash memory drivers, and hopefully show how generic programming can
make the job easier and the result more habitable, even in the barren, heapless,
rugged world of bare metal firmware.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Compile times are another common—and very valid—argument against liberal use
of generics. However, it is not a big problem for low footprint embedded
projects like this one.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;what-is-flash-memory&quot;&gt;What is Flash Memory?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-is-flash-memory&quot; aria-label=&quot;Anchor link for: what-is-flash-memory&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Flash_memory&quot;&gt;Flash memory&lt;&#x2F;a&gt; is electronic
non-volatile storage. It&#x27;s ubiquitous in consumer electronics; any time you
switch a small device off and it &lt;em&gt;remembers something&lt;&#x2F;em&gt;—whether it&#x27;s settings,
songs, documents, even its own program—chances are you have flash memory to
thank. We&#x27;ll be looking at two different &lt;em&gt;NOR&lt;&#x2F;em&gt; flash chips, since the first demo
port of &lt;code&gt;Loadstone&lt;&#x2F;code&gt; requires us to operate both:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The embedded
&lt;a href=&quot;https:&#x2F;&#x2F;www.st.com&#x2F;en&#x2F;microcontrollers-microprocessors&#x2F;stm32f412.html&quot;&gt;STM32F412&lt;&#x2F;a&gt;
1MB MCU flash.&lt;&#x2F;li&gt;
&lt;li&gt;The external 128MB &lt;a href=&quot;https:&#x2F;&#x2F;www.micron.com&#x2F;-&#x2F;media&#x2F;client&#x2F;global&#x2F;documents&#x2F;products&#x2F;data-sheet&#x2F;nor-flash&#x2F;serial-nor&#x2F;n25q&#x2F;n25q_128mb_1_8v_65nm.pdf&quot;&gt;Micron
N25Q128&lt;&#x2F;a&gt;
flash chip present in the &lt;a href=&quot;https:&#x2F;&#x2F;www.st.com&#x2F;en&#x2F;evaluation-tools&#x2F;32f412gdiscovery.html&quot;&gt;STM32F412ZGT6 Discovery
Kit&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You probably knew what flash memory is used for already, but what non-firmware
developers may not know is that flash memory is &lt;em&gt;quirky&lt;&#x2F;em&gt;. You cannot simply
write a byte to a NOR flash address, sir, that would be rude. While a blob of
flash memory will happily turn a &lt;code&gt;1&lt;&#x2F;code&gt; into a &lt;code&gt;0&lt;&#x2F;code&gt;, the opposite operation will
fail silently.&lt;&#x2F;p&gt;
&lt;p&gt;You can think of every &lt;code&gt;1&lt;&#x2F;code&gt; bit (NOR flash&#x27;s &lt;em&gt;erased&lt;&#x2F;em&gt; state) as a lit candle you
can blow out. However, in this metaphor you don&#x27;t get a lighter
to light them back up; you get a flamethrower. Without getting into the hardware
principles involved, the design of NOR flash memory requires that you erase
(i.e. set to &lt;code&gt;1&lt;&#x2F;code&gt;) memory &lt;em&gt;in bulk&lt;&#x2F;em&gt;, in chunks often orders of magnitude bigger
than the minimum addressable memory. On most chips you even have a three way
mismatch: your read, write and erase sizes aren&#x27;t equal. Ugh.&lt;&#x2F;p&gt;
&lt;p&gt;As you can imagine, this makes writing flash drivers a bit of a pain,
particularly because even the smallest write operations turn into &lt;em&gt;read&#x2F;write
cycles&lt;&#x2F;em&gt;. Writing a single byte requires reading the minimum erasable block
surrounding the targeted address (which may itself require multiple reads),
potentially erasing the entire block, then writing back the original data merged
with the desired byte.&lt;&#x2F;p&gt;
&lt;p&gt;As you can also imagine, nobody but the person writing this driver &lt;em&gt;wants to
care about this&lt;&#x2F;em&gt;. Even in the minimalistic world of bare metal software,
productive collaboration depends on developers filing away these sharp edges,
presenting interfaces that uniformize or hide any aspects of hardware irrelevant
to the bigger design. As such, a first stab at a flash memory interface should
simply offer a way to read and write ranges of memory.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s look at some code:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;ReadWrite {
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Error;
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Address;
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Address, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;]) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Error&amp;gt;;
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Address, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;]) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Error&amp;gt;;
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;range&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Address, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Address);
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;erase&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Error&amp;gt;;
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above is what I converged on as a generic interface to a flash
driver. If you&#x27;re unfamiliar with Rust generics, the above isn&#x27;t a type, or a
parent class to inherit from. It&#x27;s more like a Haskell typeclass; a set of
requirements for a concrete type to implement, described in this case in the
form of associated types (&lt;code&gt;Error&lt;&#x2F;code&gt; and &lt;code&gt;Address&lt;&#x2F;code&gt;) and method signatures (&lt;code&gt;read&lt;&#x2F;code&gt;,
&lt;code&gt;write&lt;&#x2F;code&gt;, &lt;code&gt;range&lt;&#x2F;code&gt; and &lt;code&gt;erase&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Even at this early step, some tradeoffs have to be made. The keen,
hardfault-traumatized reader will notice that this interface doesn&#x27;t lend itself
well to timing sensitive problems. All methods are blocking, and abstracting the
read&#x2F;write cycle away will naturally lead to non-deterministic write times; a
write may take very little if it only requires toggling bits off, or it might
take very long if it straddles two big sectors requiring erase operations. The
&lt;code&gt;bytes&lt;&#x2F;code&gt; output parameter in &lt;code&gt;read&lt;&#x2F;code&gt; might also strike you as not too rusty, where
returning a &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt; is often idiomatic. Unfortunately we have no heap to work
with, so if you want to take your bytes home you&#x27;ll have to bring your own bag.&lt;&#x2F;p&gt;
&lt;p&gt;Indeed, it&#x27;s hard to write the universal interface. This one made sense for the
problems we&#x27;re solving, but make sure to keep in mind the requirements of your
project!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;why-not-simply-write-a-concrete-type&quot;&gt;Why not simply write a concrete type?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-not-simply-write-a-concrete-type&quot; aria-label=&quot;Anchor link for: why-not-simply-write-a-concrete-type&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Ah, the word &amp;quot;simply&amp;quot; is tricky. Datasheet in hand, it may have been easier to
write. It might even save us a few bytes down the line. But altogether I think
the benefits of starting here are well worth the drawbacks:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Makes it easy to write test doubles and leverage static dispatch for unit
testing. This kind of approach is what I miss the most when writing C, where
I&#x27;m forced to resort to link time substitution or to do things with the
preprocessor too vile to even mention here.&lt;&#x2F;li&gt;
&lt;li&gt;Decouples your design from the get go and makes collaboration easy. Another
developer can immediately start working against this interface, and it&#x27;s
abstract enough to give you confidence it won&#x27;t need to be changed as more
knowledge of the hardware emerges.&lt;&#x2F;li&gt;
&lt;li&gt;Going abstract first forces you to think long and hard about what behaviour is
common to each implementation and what behaviour isn&#x27;t, which helps to &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Don%27t_repeat_yourself&quot;&gt;not
repeat yourself&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But the biggest reason, and one where C++ and Rust diverge, is the fact that
&lt;em&gt;you can reason about this interface locally&lt;&#x2F;em&gt;. This stems from a non-obvious
difference between the C++ template system and Rust traits. Where C++ templates
type check at the point of instantiation, Rust traits type check at the point of
definition.&lt;&#x2F;p&gt;
&lt;p&gt;What does this mean? It means that the inscrutable, seven-feet-deep-in-a-library
C++ template errors are impossible in Rust, because the compiler doesn&#x27;t need to
go beyond the interface to prove it is used correctly.&lt;&#x2F;p&gt;
&lt;p&gt;A similar interface using C++ templates could send two developers on separate
paths, one working on a concrete flash driver implementation, and another on a
higher level structure that relies on flash memory, only for the walls between
them to come crashing down when a subtle incompatibility creeps up on either
side, leaking details of one developer&#x27;s work into the other&#x27;s error messages.
Rust&#x27;s walls here are, in contrast, solid.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Yes, I&#x27;m aware that C++20 concepts and constraints help encode some of these
requirements and make errors nicer. Unfortunately they can&#x27;t enforce &lt;strong&gt;all&lt;&#x2F;strong&gt;
behaviour to be constrained, so the C++ template system remains duck typed. If
your duck doesn&#x27;t quack, you get angle bracket error soup.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;descending-into-the-concrete-world&quot;&gt;Descending into the concrete world&lt;a class=&quot;zola-anchor&quot; href=&quot;#descending-into-the-concrete-world&quot; aria-label=&quot;Anchor link for: descending-into-the-concrete-world&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Now that we&#x27;re happy with our interface, it&#x27;s time to roll up our sleeves and go
datasheet diving. We&#x27;ll start with the &lt;a href=&quot;https:&#x2F;&#x2F;www.st.com&#x2F;resource&#x2F;en&#x2F;reference_manual&#x2F;dm00180369-stm32f412-advanced-armbased-32bit-mcus-stmicroelectronics.pdf&quot;&gt;stm32f412 MCU
reference&lt;&#x2F;a&gt;.
First thing we want to know are our write, read and erase sizes. Thankfully, we
find it front and center at the start of section 3.3.&lt;&#x2F;p&gt;
&lt;figure class=&quot;center&quot;&gt;
      &lt;img src=&quot;mcu_flash_sizes.png&quot; alt=&quot;MCU Flash sizes&quot; class=&quot;center&quot; &#x2F;&gt;
      &lt;figcaption class=&quot;center&quot;&gt;MCU flash
sizes&lt;&#x2F;figcaption&gt;
   &lt;&#x2F;figure&gt;
&lt;p&gt;Okay, so our minimum write is one byte, our maximum read is four 32 bit words,
and our minimum erase is a (so far undefined) sector. Next step is to find the
memory map, to work out what a sector &lt;em&gt;is&lt;&#x2F;em&gt;, as well as its size.&lt;&#x2F;p&gt;
&lt;figure class=&quot;center&quot;&gt;
      &lt;img src=&quot;mcu_memory_map.png&quot; alt=&quot;MCU Flash memory map&quot; class=&quot;center&quot; &#x2F;&gt;
      &lt;figcaption class=&quot;center&quot;&gt;MCU flash memory map&lt;&#x2F;figcaption&gt;
   &lt;&#x2F;figure&gt;
&lt;p&gt;As you can see, we have somewhat lopsided sector sizes. This is common in MCU
flash chips, where you&#x27;re likely to store smaller amounts of miscellaneous data.
There are three special purpose sectors at the end we don&#x27;t care about. We know
enough to start laying the groundwork of our driver:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;#[derive(Default, Copy, Clone, Debug, PartialOrd, PartialEq, Ord, Eq)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Address(pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;McuFlash {
    stm32f4::stm32f412::FLASH,
}

#[derive(Copy, Clone, Debug, PartialEq)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Block {
    Main,
    SystemMemory,
    OneTimeProgrammable,
    OptionBytes,
}

#[derive(Copy, Clone, Debug, PartialEq)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Sector {
    block: Block,
    location: Address,
    size: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;NUMBER_OF_SECTORS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;15&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;MemoryMap {
    sectors: [Sector; NUMBER_OF_SECTORS],
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;MEMORY_MAP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: MemoryMap &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; MemoryMap {
    sectors: [
        Sector::new(Block::Main, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x0800_0000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)),
        Sector::new(Block::Main, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x0800_4000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)),
        Sector::new(Block::Main, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x0800_8000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)),
        Sector::new(Block::Main, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x0800_C000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)),
        Sector::new(Block::Main, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x0801_0000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;64&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)),
        Sector::new(Block::Main, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x0802_0000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)),
        Sector::new(Block::Main, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x0804_0000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)),
        Sector::new(Block::Main, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x0806_0000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)),
        Sector::new(Block::Main, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x0808_0000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)),
        Sector::new(Block::Main, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x080A_0000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)),
        Sector::new(Block::Main, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x080C_0000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)),
        Sector::new(Block::Main, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x080E_0000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)),
        Sector::new(Block::SystemMemory, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x1FFF_0000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;KB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)),
        Sector::new(Block::OneTimeProgrammable, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x1FFF_7800&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;528&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;),
        Sector::new(Block::OptionBytes, Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x1FFF_C000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;),
    ],
};

&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A few notes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;KB&lt;&#x2F;code&gt; is just a tiny helper macro that multiplies by 1024.&lt;&#x2F;li&gt;
&lt;li&gt;The FLASH type inside our McuFlash struct is part of the svd2rust-generated
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;stm32f4&#x2F;0.11.0&#x2F;stm32f4&#x2F;index.html&quot;&gt;Peripheral Access Crate&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;While it would&#x27;ve been more correct to say that blocks &lt;em&gt;contain&lt;&#x2F;em&gt; sectors, we
define blocks as a property of sectors as there isn&#x27;t much use for them beyond
classifying the sector type.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;const&lt;&#x2F;code&gt; marks the &lt;code&gt;MEMORY_MAP&lt;&#x2F;code&gt; struct as a compile time construct. This means
the compiler is free to inline it or place in static memory based on your
optimization criteria, and it becomes available in constant expressions.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now we hit a fork in the road. My usual instinct would be to fully develop and
test this driver, and then move on to the next one. However, we&#x27;re experimenting
with an abstraction-first approach, so let&#x27;s take an early detour and take our
external Micron driver to a similar spot.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Generics aren&#x27;t only useful at the interface level! Private behaviour internal
to your library can also benefit. For this project, it paid off to be
proactive and spot possible sources of duplication early.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;measuring-the-external-flash&quot;&gt;Measuring the external flash&lt;a class=&quot;zola-anchor&quot; href=&quot;#measuring-the-external-flash&quot; aria-label=&quot;Anchor link for: measuring-the-external-flash&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Here&#x27;s what the &lt;a href=&quot;https:&#x2F;&#x2F;www.micron.com&#x2F;-&#x2F;media&#x2F;client&#x2F;global&#x2F;documents&#x2F;products&#x2F;data-sheet&#x2F;nor-flash&#x2F;serial-nor&#x2F;n25q&#x2F;n25q_128mb_1_8v_65nm.pdf&quot;&gt;Micron N25Q128&lt;&#x2F;a&gt; technical documentation has to say:&lt;&#x2F;p&gt;
&lt;figure class=&quot;center&quot;&gt;
      &lt;img src=&quot;external_flash_sizes.png&quot; alt=&quot;Micron Flash sizes&quot; class=&quot;center&quot; &#x2F;&gt;
      &lt;figcaption class=&quot;center&quot;&gt;Micron flash
sizes&lt;&#x2F;figcaption&gt;
   &lt;&#x2F;figure&gt;
&lt;p&gt;Okay, so far so good. For our current purposes, we can ignore the sector
granularity and consider 4kb our minimal erase size. Looking around the
reference, we find that there&#x27;s no maximum read size, but our writes are limited
to one page at a time:&lt;&#x2F;p&gt;
&lt;figure class=&quot;center&quot;&gt;
      &lt;img src=&quot;page_program.png&quot; alt=&quot;Micron page writes&quot; class=&quot;center&quot; &#x2F;&gt;
      &lt;figcaption class=&quot;center&quot;&gt;Page program&lt;&#x2F;figcaption&gt;
   &lt;&#x2F;figure&gt;
&lt;p&gt;All that&#x27;s left then is to look at the memory map:&lt;&#x2F;p&gt;
&lt;figure class=&quot;center&quot;&gt;
      &lt;img src=&quot;external_memory_map.png&quot; alt=&quot;Micron Memory Map&quot; class=&quot;center&quot; &#x2F;&gt;
      &lt;figcaption class=&quot;center&quot;&gt;Micron memory map&lt;&#x2F;figcaption&gt;
   &lt;&#x2F;figure&gt;
&lt;p&gt;That&#x27;s... Wow. That&#x27;s a lot of sectors.&lt;&#x2F;p&gt;
&lt;p&gt;We can immediately see how the approach we used for the MCU flash is not going
to work; we can&#x27;t simply inline 256 sectors in a table. There&#x27;s also a lot
more &lt;em&gt;structure&lt;&#x2F;em&gt; to this one—sectors and subsectors are evenly spaced—which
lends itself to a programmatic representation.&lt;&#x2F;p&gt;
&lt;p&gt;There are a few ways we can encode this. I tried to define the array using a
constant expression at first, but the limited expressiveness of constant
expressions at this time made the code a bit inelegant. Instead, I settled on
an iterator solution:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;#[derive(Default, Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Address(pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;MemoryMap {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Sector(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Subsector(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Page(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;BASE_ADDRESS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: Address &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0x0000_0000&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PAGES_PER_SUBSECTOR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SUBSECTORS_PER_SECTOR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PAGES_PER_SECTOR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PAGES_PER_SUBSECTOR &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SUBSECTORS_PER_SECTOR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PAGE_SIZE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;256&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SUBSECTOR_SIZE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PAGE_SIZE &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PAGES_PER_SUBSECTOR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SECTOR_SIZE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SUBSECTOR_SIZE &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SUBSECTORS_PER_SECTOR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;MEMORY_SIZE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;NUMBER_OF_SECTORS &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SECTOR_SIZE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;NUMBER_OF_SECTORS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;256&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;NUMBER_OF_SUBSECTORS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;NUMBER_OF_SECTORS &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SUBSECTORS_PER_SECTOR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;NUMBER_OF_PAGES&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;NUMBER_OF_SUBSECTORS &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PAGES_PER_SUBSECTOR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;MemoryMap {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;sectors&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() -&amp;gt; impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Iterator&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Item = Sector&amp;gt; {
        (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;NUMBER_OF_SECTORS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(Sector)
    }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;subsectors&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() -&amp;gt; impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Iterator&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Item = Subsector&amp;gt; {
        (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;NUMBER_OF_SUBSECTORS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(Subsector)
    }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;pages&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() -&amp;gt; impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Iterator&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Item = Page&amp;gt; {
        (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;NUMBER_OF_PAGES&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(Page)
    }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() -&amp;gt; Address { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;BASE_ADDRESS &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() -&amp;gt; Address { Address(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;BASE_ADDRESS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;MEMORY_SIZE &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;MEMORY_SIZE &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Sector {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;subsectors&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Iterator&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Item = Subsector&amp;gt; {
        ((self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SUBSECTORS_PER_SECTOR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SUBSECTORS_PER_SECTOR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(Subsector)
    }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;pages&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Iterator&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Item = Page&amp;gt; {
        ((self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PAGES_PER_SECTOR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PAGES_PER_SECTOR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(Page)
    }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; Address { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;BASE_ADDRESS &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::size() }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; Address { self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::size() }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: Address) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt; {
        MemoryMap::sectors().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;find&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(address))
    }
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;SECTOR_SIZE &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
 }

&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; [..] Similar implementations for subsector and page
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Again, a few notes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Existential types as make the signature clearer, as nobody consuming this
function cares about the iterator adapters used internally.&lt;&#x2F;li&gt;
&lt;li&gt;Iterator syntax makes it very easy to express memory location conditions, e.g.
&lt;code&gt;memory_map.sectors().nth(5)?.pages().find(|p| p.contains(address))&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;I like to think that at some point in the far future when we have Rust-powered
flying cars, we&#x27;ll be able to make all the functions you see under the
&lt;code&gt;MemoryMap&lt;&#x2F;code&gt; implementation &lt;code&gt;const&lt;&#x2F;code&gt;.
Unfortunately iterators aren&#x27;t fair game in &lt;code&gt;const fn&lt;&#x2F;code&gt; yet, let alone
existential types.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;taking-a-step-back&quot;&gt;Taking a step back&lt;a class=&quot;zola-anchor&quot; href=&quot;#taking-a-step-back&quot; aria-label=&quot;Anchor link for: taking-a-step-back&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;It seems like we aren&#x27;t doing well in our quest to develop both drivers in
parallel. We&#x27;ve barely started and we already have two fundamentally different
memory map representations. Besides, erase granularities are also different; the
MCU flash erases by sector while the Micron chip is happy to go down to
subsectors.&lt;&#x2F;p&gt;
&lt;p&gt;Should we give up, and buckle up for two fully separate driver implementations?
I say we don&#x27;t. Here&#x27;s where Rust comes in, giving us amazing tools to step back
and focus on &lt;em&gt;what actually matters&lt;&#x2F;em&gt;. Let&#x27;s forget all the specific chip details
we&#x27;ve learned and sketch out the abstract details of what we&#x27;re working with.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We have &lt;code&gt;some concept of an address&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We have &lt;code&gt;some concept of a region&lt;&#x2F;code&gt;, which &lt;code&gt;contains addresses&lt;&#x2F;code&gt;. This can be a
sector, a subsector, or a page. The distinction is arbitrary so it doesn&#x27;t
matter to us.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Okay, that looks a lot simpler. Let&#x27;s model it somewhere private in our crate
where we store functionality common to our flash drivers:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Address: Ord + Copy {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Region&amp;lt;A: Address&amp;gt; {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: A) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The beautiful thing is that the representation above doesn&#x27;t lose any
generality. Even though we have already committed to certain interpretations of
what a &lt;code&gt;Region&lt;&#x2F;code&gt; is, and even though these representations behave very
differently, we know they both conceptually conform to the traits above so we can
safely use them as our only model going forward.&lt;&#x2F;p&gt;
&lt;p&gt;In the next entry, we&#x27;ll see how a representation as simple as this is enough
for us to write a lot of useful code, so that each final concrete driver
becomes a succinct representation of the specifics of the hardware, with most
actual &lt;em&gt;behaviour&lt;&#x2F;em&gt; living in the abstract layer common to both of them.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;thanks-for-reading&quot;&gt;Thanks for reading&lt;a class=&quot;zola-anchor&quot; href=&quot;#thanks-for-reading&quot; aria-label=&quot;Anchor link for: thanks-for-reading&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;m not very active on social media, so send any questions, suggestions,
criticism or hate mail at my &lt;a href=&quot;mailto:cuervo@ecorax.net&quot;&gt;e-mail&lt;&#x2F;a&gt;, or the post&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;if21da&#x2F;as_above_so_below_using_rust_generics_to_develop&#x2F;&quot;&gt;reddit
thread&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Happy rusting!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.ecorax.net&#x2F;as-above-so-below-2&#x2F;&quot;&gt;Next entry is up!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</description>
        </item>
    </channel>
</rss>
