<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>Katashift</title>
      <link>https://maguire.tech</link>
      <description>Vaguely directed ramblings</description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://maguire.tech/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Sat, 18 Oct 2025 00:00:00 +0000</lastBuildDate>
      <item>
          <title>Shove</title>
          <pubDate>Sat, 18 Oct 2025 00:00:00 +0000</pubDate>
          <author>Jack Maguire</author>
          <link>https://maguire.tech/posts/shove/</link>
          <guid>https://maguire.tech/posts/shove/</guid>
          <description xml:base="https://maguire.tech/posts/shove/">&lt;p&gt;Say hello to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BurntNail&#x2F;shove&quot;&gt;shove&lt;&#x2F;a&gt;, my brand new HTTP file server and content manager!&lt;&#x2F;p&gt;
&lt;p&gt;Shove is an S3-backed HTTP file server that handles live-reloads, partial updates and even basic HTTP auth and it has now replaced caddy as the HTTP server that serves this very blog&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-0-1&quot;&gt;&lt;a href=&quot;#fn-0&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;! This blog post will be part explanation, part advertisement and part me being excited about my latest project!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;current-functionality&quot;&gt;Current Functionality&lt;&#x2F;h2&gt;
&lt;p&gt;Currently, there’s three main commands inside &lt;code&gt;shove&lt;&#x2F;code&gt; - &lt;code&gt;protect&lt;&#x2F;code&gt;, &lt;code&gt;upload&lt;&#x2F;code&gt; and &lt;code&gt;serve&lt;&#x2F;code&gt;, which I’ll briefly explain in that order. I’ll then go over some of the interesting things I did with each.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;protect&quot;&gt;Protect&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;shove protect&lt;&#x2F;code&gt; deals with the HTTP Basic Auth that &lt;code&gt;shove&lt;&#x2F;code&gt; has - internally it’s modelled as a bunch of users (each of which has a username, a password and a uuid), and a list of realms (each of which has a pattern to protect and a list of uuids that can access it).&lt;&#x2F;p&gt;
&lt;p&gt;You run &lt;code&gt;shove protect&lt;&#x2F;code&gt; from wherever you’re uploading from (to get easy access to environment variables), add the users and add the realms. The default behaviour for paths which don’t match any patterns is just to allow anyone and everyone access to those files - for example, my blog currently has no access control in place.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;protect-1&quot;&gt;Protect&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;shove upload&lt;&#x2F;code&gt; uploads the given directory to the given S3 bucket - as far as the user cares, that’s all it does.&lt;&#x2F;p&gt;
&lt;p&gt;The complexity comes from the fact that it only uploads new files and deletes old files - to achieve this there’s a file in the root directory that stores hashes of each file. &lt;code&gt;shove protect&lt;&#x2F;code&gt; first reads in all the files, then gets that file, checks the hashes and only uploads the files that have changed.&lt;&#x2F;p&gt;
&lt;p&gt;That’s why &lt;code&gt;shove protect&lt;&#x2F;code&gt; can’t upload a ‘current directory’ - it has to have somewhere to put all the files in the bucket where there’s a guarantee the data file (and the auth file) won’t clash.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;serve&quot;&gt;Serve&lt;&#x2F;h3&gt;
&lt;p&gt;By far however, the most complicated part is &lt;code&gt;shove serve&lt;&#x2F;code&gt; - this is the general lifecycle:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Read in the data file from S3&lt;&#x2F;li&gt;
&lt;li&gt;Find all the files&lt;&#x2F;li&gt;
&lt;li&gt;Read them in from S3 and put them into a cache&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Then, when we need to serve a file it does this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Check for access control - if that fails, then send a &lt;a href=&quot;https:&#x2F;&#x2F;http.cat&#x2F;status&#x2F;401&quot;&gt;401&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Check if that file is in the cache - if so, send it&lt;&#x2F;li&gt;
&lt;li&gt;If it isn’t: grab it from S3, put that in the cache and serve it&lt;&#x2F;li&gt;
&lt;li&gt;If we couldn’t find it in S3, serve a &lt;a href=&quot;https:&#x2F;&#x2F;http.cat&#x2F;status&#x2F;404&quot;&gt;404&lt;&#x2F;a&gt; page.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;That’s all 

&lt;span id=&quot;animated-918806491&quot;&gt;&lt;&#x2F;span&gt;
&lt;script&gt;
    let personToThankForThisSickAnimation=&quot;https:&#x2F;&#x2F;codepen.io&#x2F;zachkrall&#x2F;pen&#x2F;MWWGMPx&quot;
    let delay = 250;
    let outerspan = document.getElementById(&quot;animated-918806491&quot;);

    outerspan.innerHTML = &quot;relatively&quot;
        .split(&quot;&quot;) 
        .map(letter =&gt; {
            return `&lt;span&gt;` + letter + `&lt;&#x2F;span&gt;`;
        })
        .join(&quot;&quot;);

    Array.from(outerspan.children).forEach((span, index) =&gt; {
        setTimeout(() =&gt; {
            span.classList.add(&quot;wavy&quot;);
        }, index * 60 + delay);
    });
&lt;&#x2F;script&gt; simple&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The complicated part is the live reloading which goes a little something like this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Check if we need to reload - Tigris has a webhook, or we can just re-fetch the upload data every 60s and see if that file has changed.&lt;&#x2F;li&gt;
&lt;li&gt;Work out which files have changed, and add their new versions to our cache.&lt;&#x2F;li&gt;
&lt;li&gt;Work out which files have gone missing, and evict them from our cache.&lt;&#x2F;li&gt;
&lt;li&gt;Send a notice to all the websockets connected to reload their pages.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;fun-tricks-stories&quot;&gt;Fun Tricks &amp;amp; Stories&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;protect-2&quot;&gt;Protect&lt;&#x2F;h3&gt;
&lt;p&gt;HTTP Basic Auth was certainly interesting to get working - I wanted to have some form of authentication, and got 90% the way through implementing SCRAM-SHA-256&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-10-1&quot;&gt;&lt;a href=&quot;#fn-10&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, before I realised that this is supposed to be for server-&amp;gt;server authentication and no web browser lets you just put in a password for that.&lt;&#x2F;p&gt;
&lt;p&gt;I then redirected that work into my HTTP Basic Auth implementation. I’d originally planned to more closely copy Caddy (which this project is designed to replace for me), but I kinda ended up going ham on the access control. I’d always been annoyed that I had to SSH-in, use &lt;code&gt;caddy hash-password&lt;&#x2F;code&gt;, update the caddyfile and restart caddy to change the auth&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-20-1&quot;&gt;&lt;a href=&quot;#fn-20&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; but &lt;code&gt;shove&lt;&#x2F;code&gt; auth just updates an encrypted file in the bucket that gets regularly checked for updates!&lt;&#x2F;p&gt;
&lt;p&gt;On that front, the auth benefits from the livereloading as well - &lt;code&gt;shove serve&lt;&#x2F;code&gt; never changes the auth, so we know that if it’s been changed then we need to update. Technically, if multiple people were to start changing the protections and finishing their work in weird orders, there could be a race condition where work would be lost, but I’m not concerned about this at the moment&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-30-1&quot;&gt;&lt;a href=&quot;#fn-30&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;upload&quot;&gt;Upload&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;upload&lt;&#x2F;code&gt; was (&lt;strong&gt;comparatively&lt;&#x2F;strong&gt;) simple - we just read in the provided directory, calculate hashes, read in the upload data from S3, and deal with the S3 bits. The only vaguely interesting parts are that I’ve used things like &lt;code&gt;FuturesUnordered&lt;&#x2F;code&gt; to get a load of uploads going at once.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;serve-1&quot;&gt;Serve&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;serve&lt;&#x2F;code&gt; is by far the most complicated, because it handles so damn much. This section will be more an explanation of how stuff works, rather than just tricks and stories. With &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;axum&quot;&gt;&lt;code&gt;axum&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&#x2F;&lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;hyper&quot;&gt;&lt;code&gt;hyper&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&#x2F;&lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;tower&quot;&gt;&lt;code&gt;tower&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; projects, I always find a fun way to gauge the complexity is to have a look at the &lt;code&gt;State&lt;&#x2F;code&gt; that the services use, and this is mine:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Clone)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;bucket&lt;&#x2F;span&gt;&lt;span&gt;: Box&amp;lt;Bucket&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tigris_token&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;Arc&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pages&lt;&#x2F;span&gt;&lt;span&gt;: Pages,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;live_reloader&lt;&#x2F;span&gt;&lt;span&gt;: LiveReloader,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;: AuthChecker,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yeah, that’s not a lot but still considerable, especially considering three of them are custom structs with lots of other functionality. They also happen to be relatively neat lines to draw for explanations and stories about &lt;code&gt;serve&lt;&#x2F;code&gt; so I’ll give a general explanation, and then dive into those three parts (the live reloader, the auth and the pages).&lt;&#x2F;p&gt;
&lt;h4 id=&quot;uploaddata&quot;&gt;&lt;code&gt;UploadData&lt;&#x2F;code&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;The &lt;code&gt;UploadData&lt;&#x2F;code&gt; is the struct that holds all of the hashes for all of the files in S3 and was where this whole project started. Whenever the reload is triggered&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-40-1&quot;&gt;&lt;a href=&quot;#fn-40&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, we check whether any of the upload data has changed and if so, change it. Once I got hashing working, this was relatively simple.&lt;&#x2F;p&gt;
&lt;p&gt;It doesn’t store any of the actual data, just a map which links a path to a hash, and the name of the root directory we’re serving from.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;livereloader&quot;&gt;&lt;code&gt;LiveReloader&lt;&#x2F;code&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;To use the livereloader, sites must include a small snippet in their javascript that creates a websocket connection to the server and reloads the page when it receives a &lt;code&gt;reload&lt;&#x2F;code&gt; message. Technically, they can open a websocket connection to &lt;em&gt;any&lt;&#x2F;em&gt; path as the HTTP server only checks whether the requests are for websocket upgrades and not what path they’re looking for. This works here and for now because I know there won’t be any other reasons to open websockets&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-50-1&quot;&gt;&lt;a href=&quot;#fn-50&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But how does that get handled in the server? So, whenever we receive an upgrade request&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-60-1&quot;&gt;&lt;a href=&quot;#fn-60&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, we send back an upgrade response (kindfully handled by &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;soketto&quot;&gt;&lt;code&gt;soketto&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;), and then create a &lt;code&gt;Sender&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Receiver&lt;&#x2F;code&gt; pair for messages. Then, whenever we need to reload the pages (handled by a channel&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-70-1&quot;&gt;&lt;a href=&quot;#fn-70&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;), we just send a &lt;code&gt;reload&lt;&#x2F;code&gt; message to all of the senders!&lt;&#x2F;p&gt;
&lt;p&gt;If you’ve had a peek over the source code though, it might look like &lt;code&gt;livereload.rs&lt;&#x2F;code&gt; is doing a fair bit more than that, and it is because we have to deal with closed sockets. That gets dealt with by another thread that pings all of the sockets every 60 seconds to make sure that they’re still alive and stops keeping track of the dead ones. It could be argued that this is excessive, but it’s only a server-side load and I’m happy with it. If you’ve got a better solution, feel free to submit a PR! The code is also slightly complicated because it uses a &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;latest&#x2F;futures&#x2F;prelude&#x2F;stream&#x2F;struct.FuturesUnordered.html&quot;&gt;&lt;code&gt;FuturesUnordered&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to deal with dead senders as their pings finish, rather than needing to wait for all of them.&lt;&#x2F;p&gt;
&lt;p&gt;There’s also some code there for closing sockets when the server finishes.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;authchecker&quot;&gt;&lt;code&gt;AuthChecker&lt;&#x2F;code&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Shove also has ways of dealing with HTTP basic auth. That’s when you open a webpage and the browser asks for a username and password, rather than the webpage. On the plus side, it’s relatively easy to implement from the server, but also it involves sending the entered password over the wire in plaintext which means that this &lt;strong&gt;must only&lt;&#x2F;strong&gt; be used with HTTPS deployments. In addition, you have to implement things like ratelimiting and it’s a faff.&lt;&#x2F;p&gt;
&lt;p&gt;How do I deal with it? I’ll firstly explain how the auth works, and then how it applies itself. So, when we load a page we firstly get a list of every user that has access to that page, and the hash of their password&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-80-1&quot;&gt;&lt;a href=&quot;#fn-80&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. That function deliberately returns an &lt;code&gt;Option&amp;lt;HashMap&amp;gt;&lt;&#x2F;code&gt; so that we can encode three states:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;None&lt;&#x2F;code&gt; signifies that there’s no auth needed - in that case we just return the page as normal!&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;code&gt;Some&lt;&#x2F;code&gt; with an empty &lt;code&gt;HashMap&lt;&#x2F;code&gt; signifies that nobody has access. This could be useful for pages that are only necessary for a specific job and that job isn’t always filled.&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;code&gt;Some&lt;&#x2F;code&gt; with a filled &lt;code&gt;HashMap&lt;&#x2F;code&gt; contains the users we need to auth against.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Once we’ve got the list of users and confirmed that the page needs auth, we check that user’s IP against a ratelimiter. At any point past here, if we fail then we return a response that tells the browser that the user is unauthenticated and needs to provide the correct password. If they pass that check, we then check the &lt;code&gt;Authorization&lt;&#x2F;code&gt; header in their request - if it isn’t there then we fail them and their browser prompts them for a username and password. We then try to find their user in the list we retreieved earlier. If we couldn’t find it then we fail them, but not before running a hash on a fake password - this ensures that they can’t use the round-trip-time to work out which users are valid and invalid. If we could find their password hash, then we hash what they provided and compare the two. If they match, then we serve the page and if not we fail them.&lt;&#x2F;p&gt;
&lt;p&gt;But how do we know when to apply the auth? As I mentioned earlier, I am not necessarily a fan of the way Caddy does things and I wanted to have some fun here - there’s a whole system of Users and Realms. There’s a list of Users which are just uuid-name-hash combinations, and of Realms which can match on paths (there’s exact match, regex, etc) and then we can link together users and realms for authentication. For me, this system just makes sense.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;This project was a blast to work on - just large enough to have some fun complicated parts, but not so large that it becomes painful to work on. It’s also legitimately useful for me which is a nice side effect. This was also my first project deployed with &lt;code&gt;fly.io&lt;&#x2F;code&gt;, which has been incredible to work with - speedy support, great documentation, reasonable prices, and the CLI works very very well.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-0&quot;&gt;
&lt;p&gt;I honestly don’t understand why more people don’t &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Eating_your_own_dog_food&quot;&gt;dogfood&lt;&#x2F;a&gt; their stuff - it’s been so incredible for finding bugs and new features. &lt;a href=&quot;#fr-0-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;Yes I spent far too long getting wavy text working - even with the help of &lt;a href=&quot;https:&#x2F;&#x2F;codepen.io&#x2F;zachkrall&#x2F;pen&#x2F;MWWGMPx&quot;&gt;a sick codepen&lt;&#x2F;a&gt;, it was certainly interesting learning more about Hugo &amp;amp; Zola and how to get a version that was repeatable on dynamic pages working. &lt;a href=&quot;#fr-5-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-10&quot;&gt;
&lt;p&gt;From the RFC alone, I might add. Definitely because I wanted the challenge, not because there were’t any rust crates I could find to do it for me ;). And yes, I am aware of how horrific an idea rolling my own cryptography is. &lt;a href=&quot;#fr-10-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-20&quot;&gt;
&lt;p&gt;And I just updated the files through &lt;code&gt;rclone&lt;&#x2F;code&gt; for reference. &lt;a href=&quot;#fr-20-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-30&quot;&gt;
&lt;p&gt;But if you are, feel free to open a PR! My first thought would be some kind of lockfile in the bucket which is the first thing created and the last thing destroyed in the &lt;code&gt;protect&lt;&#x2F;code&gt; flow. &lt;a href=&quot;#fr-30-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-40&quot;&gt;
&lt;p&gt;Either by a webhook which lives on &lt;code&gt;&#x2F;reload&lt;&#x2F;code&gt; or on a timer every 60s. &lt;a href=&quot;#fr-40-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-50&quot;&gt;
&lt;p&gt;If I ever need some kind of control&#x2F;management plane, I’ll probably just do it with a raw TCP socket. &lt;a href=&quot;#fr-50-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-60&quot;&gt;
&lt;p&gt;A special kind of request that signals to a server: &lt;em&gt;Heyo! I’d love to open a new websocket connection, can I?&lt;&#x2F;em&gt; &lt;a href=&quot;#fr-60-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-70&quot;&gt;
&lt;p&gt;That channel gets set off by either a 60s timer that checks for a different content hash in S3, or a Tigris webhook that lives on &lt;code&gt;&#x2F;reload&lt;&#x2F;code&gt;. &lt;a href=&quot;#fr-70-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-80&quot;&gt;
&lt;p&gt;For persistence, this data is stored in an encrypted file in S3. &lt;a href=&quot;#fr-80-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>Exploring Async Runtimes by Building our Own</title>
          <pubDate>Wed, 20 Nov 2024 00:00:00 +0000</pubDate>
          <author>Jack Maguire</author>
          <link>https://maguire.tech/posts/exploring-async-runtimes/</link>
          <guid>https://maguire.tech/posts/exploring-async-runtimes/</guid>
          <description xml:base="https://maguire.tech/posts/exploring-async-runtimes/">&lt;p&gt;For most people, asynchronous rust is as simple as &lt;code&gt;cargo add tokio -F full&lt;&#x2F;code&gt;, and then adding &lt;code&gt;#[tokio::main]&lt;&#x2F;code&gt; to your main function. Then, wham bam alakazam, you’re running rust asynchronously - you’ve got tasks and polling and all the other wonders of async rust.&lt;&#x2F;p&gt;
&lt;p&gt;If you’ve ever felt particularly curious, you might’ve chosen to &lt;code&gt;cargo expand&lt;&#x2F;code&gt;, and you’d find something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main &lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; body = async {
&lt;&#x2F;span&gt;&lt;span&gt;        {
&lt;&#x2F;span&gt;&lt;span&gt;            ::std::io::_print(format_args!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;));
&lt;&#x2F;span&gt;&lt;span&gt;        };
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allow&lt;&#x2F;span&gt;&lt;span&gt;(clippy::expect_used, clippy::diverging_sub_expression)]
&lt;&#x2F;span&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;tokio::runtime::Builder::new_multi_thread()
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;enable_all&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Failed building the Runtime&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;(body);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, we can see that it just starts a runtime with some custom options - if you add options to &lt;code&gt;tokio::main&lt;&#x2F;code&gt;, then it’ll change stuff here, but it doesn’t really tell us anything interesting.&lt;&#x2F;p&gt;
&lt;p&gt;If you then try to find the source code, it doesn’t really explain all that much - you can dig into the tokio source code, and you’ll eventually find &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;latest&#x2F;src&#x2F;tokio&#x2F;runtime&#x2F;runtime.rs.html#328-355&quot;&gt;&lt;code&gt;Runtime::block_on&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which’ll eventually lead to &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;latest&#x2F;src&#x2F;tokio&#x2F;runtime&#x2F;scheduler&#x2F;current_thread&#x2F;mod.rs.html&quot;&gt;&lt;code&gt;CurrentThread&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; or one of the other executors. The problem is that they’re not the easiest to read for a beginner&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-0-1&quot;&gt;&lt;a href=&quot;#fn-0&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;My goal for this essay is to try to explain how an executor works by building the most basic, least performant executor you will have ever seen but we’ll build it step-by-step and hopefully you’ll be able to understand other executors better afterwards.&lt;&#x2F;p&gt;
&lt;p&gt;For reading this, I’d like a intermediate understanding of Rust, and a pretty strong understanding of what a future is - if you have the former but not the latter, I can enthusiastically Amos’ &lt;a href=&quot;https:&#x2F;&#x2F;fasterthanli.me&#x2F;articles&#x2F;understanding-rust-futures-by-going-way-too-deep&quot;&gt;article on futures&lt;&#x2F;a&gt; because it really gets to the core of the matter in a way I aim to replicate.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-does-an-async-executor-do-anyways&quot;&gt;What does an async executor do, anyways?&lt;&#x2F;h2&gt;
&lt;p&gt;I’m going to start this essay much the same as how I started my &lt;a href=&quot;https:&#x2F;&#x2F;maguire.tech&#x2F;posts&#x2F;allocators&#x2F;&quot;&gt;allocators essay&lt;&#x2F;a&gt; - that is that I’ll try to find a standard library trait (or traits) which describe the required behaviour.&lt;&#x2F;p&gt;
&lt;p&gt;The easiest place to start is to look at &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;future&#x2F;trait.Future.html&quot;&gt;&lt;code&gt;std::future::Future&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; - we aren’t necessarily going to be writing any, but I know that we’ll definitely be calling them:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Future {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Required method
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, we can see that when we call the &lt;code&gt;poll&lt;&#x2F;code&gt; method, we need to provide a &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.Context.html&quot;&gt;&lt;code&gt;std::task::Context&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; with an anonymous lifetime - if we go to check that, we can see that it just provides access to a &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.Waker.html&quot;&gt;&lt;code&gt;std::task::Waker&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which it gets from the constructor.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;code&gt;Waker&lt;&#x2F;code&gt; allows a task to wake itself back up and encapsulates a &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.RawWaker.html&quot;&gt;&lt;code&gt;std::task::RawWaker&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which holds two pointers:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;RawWaker {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const &lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;vtable&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt; RawWakerVTable,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;data&lt;&#x2F;code&gt; pointer holds pretty much any data that the &lt;code&gt;executor&lt;&#x2F;code&gt; needs to hold - it’s expected to be used as an equivalent of &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;any&#x2F;trait.Any.html&quot;&gt;&lt;code&gt;std::any::Any&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.RawWakerVTable.html&quot;&gt;&lt;code&gt;std::task::RawWakerVTable&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; holds a list of function pointers, and if we check the documentation we can see that each function takes in a &lt;code&gt;*const ()&lt;&#x2F;code&gt; which always uses data from the &lt;code&gt;RawWaker&lt;&#x2F;code&gt;, and then each function has the following purpose:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Function&lt;&#x2F;th&gt;&lt;th&gt;Purpose&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;clone&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;This function gets used to create a new &lt;code&gt;RawWaker&lt;&#x2F;code&gt; for use when we clone a &lt;code&gt;Waker&lt;&#x2F;code&gt;.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;wake&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;This function is called when &lt;code&gt;wake&lt;&#x2F;code&gt; is called on the &lt;code&gt;Waker&lt;&#x2F;code&gt; and should wake up the relevant task. This also should consume the &lt;code&gt;Waker&lt;&#x2F;code&gt; and so needs to deal with any relevant cleanup (eg. freeing memory).&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;wake_by_ref&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;This function is the same as &lt;code&gt;wake&lt;&#x2F;code&gt; but doesn’t consume the &lt;code&gt;Waker&lt;&#x2F;code&gt;, so doesn’t need to deal with cleanup.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;drop&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;This is called when the &lt;code&gt;Waker&lt;&#x2F;code&gt; is dropped and has to &lt;code&gt;Drop&lt;&#x2F;code&gt; the contents of the &lt;code&gt;WakerData&lt;&#x2F;code&gt;.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;So, we now know roughly what our &lt;code&gt;Waker&lt;&#x2F;code&gt; needs, so let’s think about what else an async runtime could need.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-else&quot;&gt;What else?&lt;&#x2F;h3&gt;
&lt;p&gt;We probably need a list of tasks to poll and a list of results. I think it’ll be easiest to look at these as we go, so we’ll dive straight in.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;executor-time&quot;&gt;Executor Time!&lt;&#x2F;h2&gt;
&lt;p&gt;I haven’t built an async executor before, so this essay is more of the &lt;em&gt;come explore with me&lt;&#x2F;em&gt; variety, rather than the &lt;em&gt;guided tour of my thesis&lt;&#x2F;em&gt; variety. We’ll start with a relatively simple single-threaded executor and then see what happens from there.&lt;&#x2F;p&gt;
&lt;p&gt;First, we’ll begin a new cargo project with &lt;code&gt;cargo new --bin basic_async_executor&lt;&#x2F;code&gt;, and then open that project with whatever editor you think is best.&lt;&#x2F;p&gt;
&lt;p&gt;We can then start by laying out our definition for our executor.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::future::Future;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::sync::mpsc::{Receiver, Sender, channel};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::pin::Pin;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub type &lt;&#x2F;span&gt;&lt;span&gt;BoxedFuture&amp;lt;T&amp;gt; = Pin&amp;lt;Box&amp;lt;dyn Future&amp;lt;Output = T&amp;gt;&amp;gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tasks_to_poll&lt;&#x2F;span&gt;&lt;span&gt;: Vec&amp;lt;BoxedFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tasks_receiver&lt;&#x2F;span&gt;&lt;span&gt;: Receiver&amp;lt;BoxedFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tasks_sender&lt;&#x2F;span&gt;&lt;span&gt;: Sender&amp;lt;BoxedFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Default &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(tx, rx) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            tasks_to_poll: vec![],
&lt;&#x2F;span&gt;&lt;span&gt;            tasks_sender: tx,
&lt;&#x2F;span&gt;&lt;span&gt;            tasks_receiver: rx,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, you can see that we start with some imports - &lt;code&gt;Future&lt;&#x2F;code&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;pin&#x2F;struct.Pin.html&quot;&gt;&lt;code&gt;std::pin::Pin&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and channels. Even though this is all single-threaded we need to use the synchronisation primitives because of the method signatures in &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.RawWakerVTable.html&quot;&gt;&lt;code&gt;std::task::RawWakerVTable&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; - they all have the data as a non-mutable object, so we have to use interior mutability which is easiest with the synchronisation primitives we have in the standard library.&lt;&#x2F;p&gt;
&lt;p&gt;We then also define a type alias to not have to write out the whole future definition every time, which just makes life a bit easier. For our boxed future, we also need to have wrapped it in &lt;code&gt;Pin&lt;&#x2F;code&gt;. This is because of the way that Futures work, and I could try to explain it but I think I’d probably do it poorly and so will defer to &lt;a href=&quot;https:&#x2F;&#x2F;fasterthanli.me&#x2F;articles&#x2F;pin-and-suffering&quot;&gt;Amos’ Article&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We then define a struct for our actual executor - a list of tasks that we need to poll, and a receiver for tasks to add themselves to the list of tasks to be polled. They both have the concrete type of &lt;code&gt;u32&lt;&#x2F;code&gt; because that can communicate a fair few distinct values and it makes it easier not to have to deal with multiple types yet. As I mentioned earlier, we’re not trying to make a good one, we’re trying to make one that works.&lt;&#x2F;p&gt;
&lt;p&gt;Our basic event loop will go something like this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Check the receiver for tasks to poll.&lt;&#x2F;li&gt;
&lt;li&gt;Loop through the tasks we need to poll.&lt;&#x2F;li&gt;
&lt;li&gt;For each task, poll it.&lt;&#x2F;li&gt;
&lt;li&gt;For each task, if it is pending, continue on.&lt;&#x2F;li&gt;
&lt;li&gt;For each task, if it is ready, then just print out the result.&lt;&#x2F;li&gt;
&lt;li&gt;Repeat ad infinitum.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Since that should be relatively simple, we can also write out that loop:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;future&lt;&#x2F;span&gt;&lt;span&gt;: BoxedFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(future);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; task in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_receiver.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_iter&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(task);
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for mut&lt;&#x2F;span&gt;&lt;span&gt; task in std::mem::take(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll) {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cx = todo!();
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; task.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; cx) {
&lt;&#x2F;span&gt;&lt;span&gt;                    Poll::Ready(res) =&amp;gt; println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Received Result: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{res}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;                    Poll::Pending =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, we’ve now got a skeleton for our basic &lt;code&gt;block_on&lt;&#x2F;code&gt; function, with the only missing bit being our context, which will probably be the more difficult part.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;context&quot;&gt;Context&lt;&#x2F;h3&gt;
&lt;p&gt;First, I think the best place to start would be to create the data for each waker that lives inside the &lt;code&gt;*const ()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Clone)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;WakerData;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see, it’s currently empty because it isn’t yet clear what data we’ll need.&lt;&#x2F;p&gt;
&lt;p&gt;Now we need to do the functions for our VTable. We need to pay pretty careful attention here because it’s unsafe to call the functions that make the VTable, where the invariant is that all of these functions need to be thread-safe. Here, we can follow that by making sure to use the synchronisation primitives.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::task::RawWakerVTable;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VTABLE&lt;&#x2F;span&gt;&lt;span&gt;: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;clone &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const &lt;&#x2F;span&gt;&lt;span&gt;()) -&amp;gt; RawWaker {
&lt;&#x2F;span&gt;&lt;span&gt;    todo!()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;wake &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const &lt;&#x2F;span&gt;&lt;span&gt;()) {
&lt;&#x2F;span&gt;&lt;span&gt;    todo!()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;wake_by_ref &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const &lt;&#x2F;span&gt;&lt;span&gt;()) {
&lt;&#x2F;span&gt;&lt;span&gt;    todo!()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drop &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const &lt;&#x2F;span&gt;&lt;span&gt;()) {
&lt;&#x2F;span&gt;&lt;span&gt;    todo!()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Remember when I mentioned that I was learning at the same time? Well we’ve come across our first problem here - we need to be able to wake up a task using only the data in our &lt;code&gt;WakerData&lt;&#x2F;code&gt;. The first thing that comes to mind is the idea that we could have each &lt;code&gt;WakerData&lt;&#x2F;code&gt; store an index into the list of tasks, and our sender sends that index rather than the entire future. This is because we can’t send a partially completed future from inside the future, where we can’t access it.&lt;&#x2F;p&gt;
&lt;p&gt;Following Rust best practices, we’ll use an enum rather than a boolean for by ref versus owned - I’m not normally a shill for mindlessly following best practices but this one makes 100% sense to me. It makes it far easier to see in github diffs and to know what the code does at a glance.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::task::Poll;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tasks_to_poll&lt;&#x2F;span&gt;&lt;span&gt;: Vec&amp;lt;Option&amp;lt;BoxedFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tasks_receiver&lt;&#x2F;span&gt;&lt;span&gt;: Receiver&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tasks_sender&lt;&#x2F;span&gt;&lt;span&gt;: Sender&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Default &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;default &lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(tasks_sender, tasks_receiver) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            tasks_to_poll: Vec::new(),
&lt;&#x2F;span&gt;&lt;span&gt;            tasks_sender,
&lt;&#x2F;span&gt;&lt;span&gt;            tasks_receiver
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;future&lt;&#x2F;span&gt;&lt;span&gt;: BoxedFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(Some(future));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; index in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_receiver.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_iter&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; index &amp;gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;                    panic!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;index out of bounds&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cx = todo!();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;Some(task) = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll[index] {
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; task.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; cx) {
&lt;&#x2F;span&gt;&lt;span&gt;                        Poll::Ready(res) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;                            println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[executor] got: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{res}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;                            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll[index] = None;
&lt;&#x2F;span&gt;&lt;span&gt;                        },
&lt;&#x2F;span&gt;&lt;span&gt;                        Poll::Pending =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;                    }
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here you can see that I’ve moved to a list of Options where each can hold a future, and that future gets removed when the task finishes. We technically don’t need to do this, but it allows the program to free the memory used by those tasks and ensures we don’t poll a task after completion.&lt;&#x2F;p&gt;
&lt;p&gt;We’ll also need to add the index to the waker data, as well as a use statement for the &lt;code&gt;RawWaker&lt;&#x2F;code&gt; parts we’ll be doing next.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::task::RawWaker;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Clone)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;WakerData {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tasks_sender&lt;&#x2F;span&gt;&lt;span&gt;: Sender&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, we can get back to our VTable.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;clone&quot;&gt;Clone&lt;&#x2F;h4&gt;
&lt;p&gt;Clone should be relatively easy - we can just make a new RawWaker relatively easily. However, we do need to be careful on a few fronts to try to avoid undefined behaviour:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;We need to make sure that we create a new &lt;code&gt;Sender&lt;&#x2F;code&gt; - this avoids freeing the same &lt;code&gt;Sender&lt;&#x2F;code&gt; multiple times.&lt;&#x2F;li&gt;
&lt;li&gt;We need to ensure that the &lt;code&gt;WakerData&lt;&#x2F;code&gt; inside &lt;code&gt;data&lt;&#x2F;code&gt; does not get dropped as &lt;code&gt;clone&lt;&#x2F;code&gt; should only read the original, not drop it.&lt;&#x2F;li&gt;
&lt;li&gt;We need to make sure that the new data gets sent to the heap to make sure it will not just be dropped at the end of the function.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;clone &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const &lt;&#x2F;span&gt;&lt;span&gt;()) -&amp;gt; RawWaker {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; old_data = std::ptr::read(data as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const&lt;&#x2F;span&gt;&lt;span&gt; WakerData);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; new_data = old_data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;cloning clones all the interior contents, creating a new `Sender`
&lt;&#x2F;span&gt;&lt;span&gt;    std::mem::forget(old_data);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; boxed = Box::new(new_data);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; raw_ptr = Box::into_raw(boxed);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    RawWaker::new(raw_ptr as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const &lt;&#x2F;span&gt;&lt;span&gt;(), &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VTABLE&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;wake-wake-by-ref&quot;&gt;Wake &amp;amp; Wake By Ref&lt;&#x2F;h4&gt;
&lt;p&gt;These are pretty easy - we just need to read in the pointer and send the task id in the sender. However, we also need to remember to &lt;code&gt;std::mem::forget&lt;&#x2F;code&gt; the data to ensure that it doesn’t drop the contents of the pointer and make it invalid. For our implementation, there isn’t really any difference between &lt;code&gt;wake&lt;&#x2F;code&gt; and &lt;code&gt;wake_by_ref&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;wake&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const &lt;&#x2F;span&gt;&lt;span&gt;()) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = std::ptr::read(data as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const&lt;&#x2F;span&gt;&lt;span&gt; WakerData);
&lt;&#x2F;span&gt;&lt;span&gt;    data.tasks_sender
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(data.id)
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;unable to send task id to executor&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    std::mem::forget(data);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;wake_by_ref&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const &lt;&#x2F;span&gt;&lt;span&gt;()) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = std::ptr::read(data as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const&lt;&#x2F;span&gt;&lt;span&gt; WakerData);
&lt;&#x2F;span&gt;&lt;span&gt;    data.tasks_sender
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(data.id)
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;unable to send task id to executor&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    std::mem::forget(data);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;drop&quot;&gt;Drop&lt;&#x2F;h4&gt;
&lt;p&gt;For drop, we need to ensure that both the &lt;code&gt;WakerData&lt;&#x2F;code&gt; is properly dropped &lt;strong&gt;and&lt;&#x2F;strong&gt; the &lt;code&gt;Box&lt;&#x2F;code&gt; is properly deallocated. If we use &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;boxed&#x2F;struct.Box.html#method.from_raw&quot;&gt;&lt;code&gt;Box::from_raw&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, we can get our pointer back into the &lt;code&gt;Box&lt;&#x2F;code&gt;, and then when the function finishes, the contents will be both dropped and deallocated. We also know that we fit the safety requirements as we know this method will only be called once per pointer!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drop &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const &lt;&#x2F;span&gt;&lt;span&gt;()) {
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;_ = Box::from_raw(data as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut&lt;&#x2F;span&gt;&lt;span&gt; WakerData);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;virtual-function-table&quot;&gt;Virtual Function Table&lt;&#x2F;h4&gt;
&lt;p&gt;We can finally then create the virtual function table. Here, I’m using a &lt;code&gt;const&lt;&#x2F;code&gt; variable as the constructor for &lt;code&gt;RawWakerVTable&lt;&#x2F;code&gt; is &lt;code&gt;const&lt;&#x2F;code&gt; and it just contains function pointers and so this makes it easiest to use.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VTABLE&lt;&#x2F;span&gt;&lt;span&gt;: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;creating-the-context&quot;&gt;Creating the Context&lt;&#x2F;h3&gt;
&lt;p&gt;However, we still need to create the context to poll with. The best way to do this is to work backwards through the documentation to work out what we need.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;We need to finish with a &lt;code&gt;Context&lt;&#x2F;code&gt;, which seems to have a constructor method of &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.Context.html#method.from_waker&quot;&gt;&lt;code&gt;Context::from_waker&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which takes in a &lt;code&gt;Waker&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Waker&lt;&#x2F;code&gt; has &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.Waker.html#method.from_raw&quot;&gt;&lt;code&gt;Waker::from_raw&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which takes in a &lt;code&gt;RawWaker&lt;&#x2F;code&gt;. This is an unsafe function, where the invariant is that we need to make sure that our &lt;code&gt;RawWaker&lt;&#x2F;code&gt; and our &lt;code&gt;RawWakerVTable&lt;&#x2F;code&gt; are all sound and follow their invariants.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;RawWaker&lt;&#x2F;code&gt; has a constructor which takes in a pointer to some &lt;code&gt;WakerData&lt;&#x2F;code&gt; and our &lt;code&gt;VTABLE&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;So, we can then use this code block inside of our &lt;code&gt;block_on&lt;&#x2F;code&gt; loop to create our &lt;code&gt;Context&lt;&#x2F;code&gt;! When you add this, don’t forget to add an &lt;code&gt;use std::task::{Waker, Context}&lt;&#x2F;code&gt; to the top.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; waker_data = WakerData {
&lt;&#x2F;span&gt;&lt;span&gt;    id: index,
&lt;&#x2F;span&gt;&lt;span&gt;    tasks_sender: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_sender.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; boxed_waker_data = Box::new(waker_data);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; raw_waker_data = Box::into_raw(boxed_waker_data);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; raw_waker =
&lt;&#x2F;span&gt;&lt;span&gt;    RawWaker::new(raw_waker_data as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const&lt;&#x2F;span&gt;&lt;span&gt; WakerData as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const &lt;&#x2F;span&gt;&lt;span&gt;(), &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VTABLE&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; waker = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Waker::from_raw(raw_waker) };
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; cx = Context::from_waker(&amp;amp;waker);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Similar to the &lt;code&gt;clone&lt;&#x2F;code&gt; method, we need to make sure to put the &lt;code&gt;WakerData&lt;&#x2F;code&gt; onto the heap to make sure it doesn’t get double-freed.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;creating-a-future&quot;&gt;Creating a Future&lt;&#x2F;h3&gt;
&lt;p&gt;We can then create a very basic future that immediately returns to test our executor:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;BasicFuture;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;BasicFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        Poll::Ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;123&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And create a main method to run it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main &lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fut = BasicFuture;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; exec = Executor::default();
&lt;&#x2F;span&gt;&lt;span&gt;    exec.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;(Box::pin(fut));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We then get this output:
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo r --quiet
&lt;&#x2F;span&gt;&lt;span&gt;[executor] Received Result: 123
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;And the program hangs forever. This however, we can easily fix! Since we know that once our main future (the one we called &lt;code&gt;block_on&lt;&#x2F;code&gt; with) is finished, all tasks are finished, we can just break the loop when that one finishes!&lt;&#x2F;p&gt;
&lt;p&gt;Just put this in our &lt;code&gt;Poll::Ready&lt;&#x2F;code&gt; branch, and make sure to label the loop.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; index == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break &amp;#39;main&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, I’ve used the &lt;code&gt;&#x27;main&lt;&#x2F;code&gt; label, but you could use anything - this is to make sure that it breaks the right loop, as &lt;code&gt;break&lt;&#x2F;code&gt; breaks the inner-most loop by default.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;creating-a-more-complicated-future&quot;&gt;Creating a more complicated future&lt;&#x2F;h3&gt;
&lt;p&gt;Whilst that future works, we can also create more complicated futures to actually test whether things are actually running concurrently. For a basic timer future, we can use this one.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;TimerFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;Instant&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;: Duration,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;timeout_ms&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;TimerFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;timeout_ms&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            start: None,
&lt;&#x2F;span&gt;&lt;span&gt;            timeout_ms,
&lt;&#x2F;span&gt;&lt;span&gt;            time: Duration::from_millis(timeout_ms as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;TimerFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.start {
&lt;&#x2F;span&gt;&lt;span&gt;            None =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.start = Some(Instant::now());
&lt;&#x2F;span&gt;&lt;span&gt;            },
&lt;&#x2F;span&gt;&lt;span&gt;            Some(x) =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;elapsed&lt;&#x2F;span&gt;&lt;span&gt;() &amp;gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.time {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Poll::Ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.timeout_ms);
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        cx.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;waker&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;wake_by_ref&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        Poll::Pending
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can also then add the &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;futures&quot;&gt;&lt;code&gt;futures&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate and this snippet which creates three of our futures, and then prints how long it takes for them all to run at the same time. If we’re doing actual concurrency, they should hopefully only take roughly as long as the longest timeout.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::time::{Instant, Duration};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    Executor::default().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;(Box::pin(async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[main] Creating futures&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; one = TimerFuture::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;250&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; two = TimerFuture::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;500&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; three = TimerFuture::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;750&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[main] Created all&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; t = Instant::now();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = futures::join!(one, two, three);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; elapsed = t.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;elapsed&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[main] Got &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{res:?}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt; in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{elapsed:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;span&gt;    }));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And if we run that, we then get:&lt;&#x2F;p&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo r --quiet
&lt;&#x2F;span&gt;&lt;span&gt;[main] Creating futures
&lt;&#x2F;span&gt;&lt;span&gt;[main] Created all
&lt;&#x2F;span&gt;&lt;span&gt;[main] Got (250, 500, 750) in 750.380037ms
&lt;&#x2F;span&gt;&lt;span&gt;[executor] Received Result: 0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;Yes! We now have a basic executor that works!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;but-is-it-safe&quot;&gt;But is it safe?&lt;&#x2F;h2&gt;
&lt;p&gt;So, all of the code looks relatively safe but we still have to check. My tool for that is &lt;code&gt;miri&lt;&#x2F;code&gt;, so let’s &lt;code&gt;cargo +nightly miri run&lt;&#x2F;code&gt; and we get the exact same result without any complaints!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;running-multiple-tasks-at-once&quot;&gt;Running multiple tasks at once&lt;&#x2F;h2&gt;
&lt;p&gt;Right now, we’re only running our &lt;code&gt;main&lt;&#x2F;code&gt; task, which works well, but also means that we have to use the &lt;code&gt;futures&lt;&#x2F;code&gt; machinery to run multiple futures at once. Right now, all of our work with keeping track of multiple tasks is also all going to waste!&lt;&#x2F;p&gt;
&lt;p&gt;So, we need to fix that.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-will-we-need&quot;&gt;What will we need?&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;We need to move the task execution to a new thread - this way we can add more tasks whilst tasks are running.&lt;&#x2F;li&gt;
&lt;li&gt;We need a way to add tasks to the executor.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;moving-tasks-to-a-new-thread&quot;&gt;Moving tasks to a new thread&lt;&#x2F;h3&gt;
&lt;p&gt;For this, we basically just need to move most of the Executor &lt;code&gt;block_on&lt;&#x2F;code&gt; logic to a new thread, so let’s change that method. For now, we’ll also change it to not take in a task and we can call it a &lt;code&gt;start&lt;&#x2F;code&gt; method.&lt;&#x2F;p&gt;
&lt;p&gt;For reference, this is our current code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;future&lt;&#x2F;span&gt;&lt;span&gt;: BoxedFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(Some(future));
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_sender.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;#39;main: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; index in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_receiver.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_iter&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; index &amp;gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;                panic!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;index out of bounds&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; waker_data = WakerData::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_sender.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(), index);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; boxed_waker_data = Box::new(waker_data);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; raw_waker_data = Box::into_raw(boxed_waker_data);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; raw_waker =
&lt;&#x2F;span&gt;&lt;span&gt;                RawWaker::new(raw_waker_data as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const&lt;&#x2F;span&gt;&lt;span&gt; WakerData as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const &lt;&#x2F;span&gt;&lt;span&gt;(), &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VTABLE&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; waker = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Waker::from_raw(raw_waker) };
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; cx = Context::from_waker(&amp;amp;waker);   
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;Some(task) = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll[index] {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;Poll::Ready(res) = task.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; cx) {
&lt;&#x2F;span&gt;&lt;span&gt;                    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[executor] Received Result: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{res}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll[index] = None;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; index == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break &amp;#39;main&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;                    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And our first try at moving stuff around gets us this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    std::thread::spawn(|| {
&lt;&#x2F;span&gt;&lt;span&gt;        &amp;#39;main: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; index in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_receiver.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_iter&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; index &amp;gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;                    panic!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;index out of bounds&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;                println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[executor] polling &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{index}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; waker_data = WakerData::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_sender.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(), index);
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; boxed_waker_data = Box::new(waker_data);
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; raw_waker_data = Box::into_raw(boxed_waker_data);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; raw_waker =
&lt;&#x2F;span&gt;&lt;span&gt;                    RawWaker::new(raw_waker_data as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const&lt;&#x2F;span&gt;&lt;span&gt; WakerData as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const &lt;&#x2F;span&gt;&lt;span&gt;(), &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VTABLE&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; waker = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Waker::from_raw(raw_waker) };
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; cx = Context::from_waker(&amp;amp;waker);   
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;Some(task) = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll[index] {
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;Poll::Ready(res) = task.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; cx) {
&lt;&#x2F;span&gt;&lt;span&gt;                        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[executor] Received Result: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{res}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll[index] = None;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; index == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;                            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break &amp;#39;main&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;                        }
&lt;&#x2F;span&gt;&lt;span&gt;                    }
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, we immediately encounter problems. Firstly - we get told that our futures cannot be sent across threads:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;error[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;E0277&lt;&#x2F;span&gt;&lt;span&gt;]: `(dyn futures::Future&amp;lt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;)` cannot be sent between threads safely
&lt;&#x2F;span&gt;&lt;span&gt;    --&amp;gt; src&#x2F;main.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;41&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;28
&lt;&#x2F;span&gt;&lt;span&gt;     |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;41   &lt;&#x2F;span&gt;&lt;span&gt;|           std::thread::spawn(|| {
&lt;&#x2F;span&gt;&lt;span&gt;     |  _________------------------_^
&lt;&#x2F;span&gt;&lt;span&gt;     | |         |
&lt;&#x2F;span&gt;&lt;span&gt;     | |         required by a bound introduced by this call
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;42   &lt;&#x2F;span&gt;&lt;span&gt;| |             &amp;#39;main: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;43   &lt;&#x2F;span&gt;&lt;span&gt;| |                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; index in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_receiver.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_iter&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;44   &lt;&#x2F;span&gt;&lt;span&gt;| |                     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; index &amp;gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;...    |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;71   &lt;&#x2F;span&gt;&lt;span&gt;| |             }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;72   &lt;&#x2F;span&gt;&lt;span&gt;| |         });
&lt;&#x2F;span&gt;&lt;span&gt;     | |&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;_________&lt;&#x2F;span&gt;&lt;span&gt;^ `(dyn futures::Future&amp;lt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;)` cannot be sent between threads safely
&lt;&#x2F;span&gt;&lt;span&gt;     |
&lt;&#x2F;span&gt;&lt;span&gt;     = help: the &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span&gt; `std::marker::Send` is not implemented &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; `(dyn futures::Future&amp;lt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;)`, which is required by `{closure@src&#x2F;main.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;41&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;28&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;41&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;30&lt;&#x2F;span&gt;&lt;span&gt;}: std::marker::Send`
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is because we are trying to move all of our tasks from one thread to another, and to do that they need to implement &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;marker&#x2F;trait.Send.html&quot;&gt;&lt;code&gt;std::marker::Send&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. That one is relatively easy to fix - we just need to change our &lt;code&gt;BoxedFuture&lt;&#x2F;code&gt; to have a &lt;code&gt;Send&lt;&#x2F;code&gt; bound, like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub type &lt;&#x2F;span&gt;&lt;span&gt;BoxedFuture&amp;lt;T&amp;gt; = Pin&amp;lt;Box&amp;lt;dyn Future&amp;lt;Output = T&amp;gt; + Send&amp;gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Our next error is then:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;error[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;E0521&lt;&#x2F;span&gt;&lt;span&gt;]: borrowed data escapes outside of method
&lt;&#x2F;span&gt;&lt;span&gt;  --&amp;gt; src&#x2F;main.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;41&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;9
&lt;&#x2F;span&gt;&lt;span&gt;   |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;40 &lt;&#x2F;span&gt;&lt;span&gt;|       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;   |                    -----
&lt;&#x2F;span&gt;&lt;span&gt;   |                    |
&lt;&#x2F;span&gt;&lt;span&gt;   |                    `&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;` is a reference that is only valid in the method body
&lt;&#x2F;span&gt;&lt;span&gt;   |                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&amp;#39;s&lt;&#x2F;span&gt;&lt;span&gt; call the lifetime of this reference `&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;41 &lt;&#x2F;span&gt;&lt;span&gt;| &#x2F;         std::thread::spawn(|| {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;42 &lt;&#x2F;span&gt;&lt;span&gt;| |             &amp;#39;main: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;43 &lt;&#x2F;span&gt;&lt;span&gt;| |                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; index in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_receiver.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_iter&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;44 &lt;&#x2F;span&gt;&lt;span&gt;| |                     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; index &amp;gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tasks_to_poll.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;...  |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;71 &lt;&#x2F;span&gt;&lt;span&gt;| |             }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;72 &lt;&#x2F;span&gt;&lt;span&gt;| |         });
&lt;&#x2F;span&gt;&lt;span&gt;   | |          ^
&lt;&#x2F;span&gt;&lt;span&gt;   | |          |
&lt;&#x2F;span&gt;&lt;span&gt;   | |&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;__________&lt;&#x2F;span&gt;&lt;span&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;` escapes the method body here
&lt;&#x2F;span&gt;&lt;span&gt;   |            argument requires that `&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;` must outlive `&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;`
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This one is that we borrow things from &lt;code&gt;self&lt;&#x2F;code&gt;, but that the thread must have a &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; lifetime.&lt;&#x2F;p&gt;
&lt;p&gt;The easiest way to fix this one&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-10-1&quot;&gt;&lt;a href=&quot;#fn-10&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; is to change the way that our start function works - we can make it into a constructor, rather than just a method. That way, we can let the thread own things like &lt;code&gt;tasks_to_poll&lt;&#x2F;code&gt; and the &lt;code&gt;tasks_receiver&lt;&#x2F;code&gt; and we don’t need to worry about borrowing and other issues.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;making-start-a-constructor&quot;&gt;Making &lt;code&gt;start&lt;&#x2F;code&gt; a constructor&lt;&#x2F;h3&gt;
&lt;p&gt;Firstly, we need to decide on what our &lt;code&gt;Executor&lt;&#x2F;code&gt; will hold and not hold.&lt;&#x2F;p&gt;
&lt;p&gt;Currently, we have this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tasks_to_poll&lt;&#x2F;span&gt;&lt;span&gt;: Vec&amp;lt;Option&amp;lt;BoxedFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tasks_receiver&lt;&#x2F;span&gt;&lt;span&gt;: Receiver&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tasks_sender&lt;&#x2F;span&gt;&lt;span&gt;: Sender&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We already decided to move &lt;code&gt;tasks_to_poll&lt;&#x2F;code&gt;, &lt;code&gt;tasks_receiver&lt;&#x2F;code&gt; and &lt;code&gt;tasks_sender&lt;&#x2F;code&gt; to the thread, and since we’re now using a thread we’ll hold onto a &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;thread&#x2F;struct.JoinHandle.html&quot;&gt;&lt;code&gt;std::thread::JoinHandle&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;That gives our new definition as:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::thread::JoinHandle;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;thread&lt;&#x2F;span&gt;&lt;span&gt;: JoinHandle&amp;lt;()&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can then finish off our new constructor:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; thread = std::thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|| {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; tasks_to_poll: Vec&amp;lt;Option&amp;lt;BoxedFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(tasks_sender, tasks_receiver) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;snip: executor loop, with all `self.`s removed
&lt;&#x2F;span&gt;&lt;span&gt;        });
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ thread }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;One slight issue now - we can’t actually add any new tasks! For that, we’ll need another &lt;code&gt;Sender&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Receiver&lt;&#x2F;code&gt; pair.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sending-tasks&quot;&gt;Sending tasks&lt;&#x2F;h3&gt;
&lt;p&gt;Firstly, we’ll add the &lt;code&gt;Sender&lt;&#x2F;code&gt; to our struct definition:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;thread&lt;&#x2F;span&gt;&lt;span&gt;: JoinHandle&amp;lt;()&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;new_task_sender&lt;&#x2F;span&gt;&lt;span&gt;: Sender&amp;lt;BoxedFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then add a function for sending tasks when we get them:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;add_task &lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: impl Future&amp;lt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; + Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.new_task_sender.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(Box::pin(f)).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;unable to send new task to executor&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can even use some a fun &lt;code&gt;impl Trait&lt;&#x2F;code&gt; to allow users to pass in any future to be used and then we deal with &lt;code&gt;Box&lt;&#x2F;code&gt;ing&#x2F;&lt;code&gt;Pin&lt;&#x2F;code&gt;ning it. As with &lt;code&gt;BoxedFuture&lt;&#x2F;code&gt;, we need to add the &lt;code&gt;Send&lt;&#x2F;code&gt; bound and here we also need to add the &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; bound to make sure that the task can live forever as we’ll be sending it to a different thread with no idea when we’ll be executing it.&lt;&#x2F;p&gt;
&lt;p&gt;We then just need to add some more logic to our &lt;code&gt;start&lt;&#x2F;code&gt; function to add any new tasks. This logic also needs to send those tasks to the &lt;code&gt;tasks_sender&lt;&#x2F;code&gt; to ensure they get polled!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(new_task_sender, new_task_receiver) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; thread = std::thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|| {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; tasks_to_poll: Vec&amp;lt;Option&amp;lt;BoxedFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(tasks_sender, tasks_receiver) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;#39;main: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; task in new_task_receiver.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_iter&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; index = tasks_to_poll.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;                    tasks_to_poll.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(Some(task));
&lt;&#x2F;span&gt;&lt;span&gt;                    tasks_sender.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(index).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;snip: polling loop
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        });
&lt;&#x2F;span&gt;&lt;span&gt;        
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ thread, new_task_sender }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;time-to-test&quot;&gt;Time to test!&lt;&#x2F;h3&gt;
&lt;p&gt;If we then add a few simple futures to our &lt;code&gt;main&lt;&#x2F;code&gt; function, let’s see what happens!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; executor = Executor::start();
&lt;&#x2F;span&gt;&lt;span&gt;    executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add_task&lt;&#x2F;span&gt;&lt;span&gt;(async {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;    executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add_task&lt;&#x2F;span&gt;&lt;span&gt;(async {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These futures don’t do anything vaguely interesting, but we should see some print statements with their results if this works.&lt;&#x2F;p&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo run --quiet
&lt;&#x2F;span&gt;&lt;span&gt;# snip: cargo warnings
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;Nothing!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nothing&quot;&gt;Nothing?&lt;&#x2F;h3&gt;
&lt;p&gt;First step when things don’t seem to work? Print statements! Let’s add one at each ‘stage’ of our &lt;code&gt;main&lt;&#x2F;code&gt; function to see how far it gets.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[main] start&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; executor = Executor::start();
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[main] started executor&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add_task&lt;&#x2F;span&gt;&lt;span&gt;(async {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;    executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add_task&lt;&#x2F;span&gt;&lt;span&gt;(async {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[main] added tasks&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then if we run it:
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo run --quiet
&lt;&#x2F;span&gt;&lt;span&gt;# snip: warnings from cargo
&lt;&#x2F;span&gt;&lt;span&gt;[main] start
&lt;&#x2F;span&gt;&lt;span&gt;[main] started executor
&lt;&#x2F;span&gt;&lt;span&gt;[main] added tasks
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;So it appears that our main function is all running, but we aren’t getting anything from our executor. I’ve got a hunch, so I’m going to add some print statements to our thread:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(new_task_sender, new_task_receiver) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; thread = std::thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|| {
&lt;&#x2F;span&gt;&lt;span&gt;            println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[executor] thread started&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; tasks_to_poll: Vec&amp;lt;Option&amp;lt;BoxedFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(tasks_sender, tasks_receiver) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;            println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[executor] channels created&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;#39;main: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;                println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[executor] loop&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;snip: adding tasks from new_tasks_receiver
&lt;&#x2F;span&gt;&lt;span&gt;                println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[executor] got new tasks&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;snip: polling
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        });
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ thread, new_task_sender }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then:&lt;&#x2F;p&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo run --quiet
&lt;&#x2F;span&gt;&lt;span&gt;# snip: warnings from cargo
&lt;&#x2F;span&gt;&lt;span&gt;[main] start
&lt;&#x2F;span&gt;&lt;span&gt;[main] started executor
&lt;&#x2F;span&gt;&lt;span&gt;[main] added tasks
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;It looks like our thread is never actually running. If we check the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;thread&#x2F;fn.spawn.html&quot;&gt;docs&lt;&#x2F;a&gt; for &lt;code&gt;thread::spawn&lt;&#x2F;code&gt;, it looks like our thread has become &lt;em&gt;detached&lt;&#x2F;em&gt;. This means that our program starts the thread, and runs all of the rest of the logic before our thread can do anything and then exits.&lt;&#x2F;p&gt;
&lt;p&gt;That means that we need to &lt;code&gt;join&lt;&#x2F;code&gt; the thread at the end of the program. We unfortunately cannot use &lt;code&gt;Drop&lt;&#x2F;code&gt; as &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;thread&#x2F;struct.JoinHandle.html#method.join&quot;&gt;&lt;code&gt;JoinHandle::join&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; takes &lt;code&gt;self&lt;&#x2F;code&gt; on the thread, but &lt;code&gt;Drop&lt;&#x2F;code&gt; only has &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;join &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.thread.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;error joining thread&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[main] start&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; executor = Executor::start();
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[main] started executor&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add_task&lt;&#x2F;span&gt;&lt;span&gt;(async {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;    executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add_task&lt;&#x2F;span&gt;&lt;span&gt;(async {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[main] added tasks&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then?
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo run --quiet
&lt;&#x2F;span&gt;&lt;span&gt;[main] start
&lt;&#x2F;span&gt;&lt;span&gt;[main] started executor
&lt;&#x2F;span&gt;&lt;span&gt;[main] added tasks
&lt;&#x2F;span&gt;&lt;span&gt;[executor] thread started
&lt;&#x2F;span&gt;&lt;span&gt;[executor] channels created
&lt;&#x2F;span&gt;&lt;span&gt;[executor] loop
&lt;&#x2F;span&gt;&lt;span&gt;[executor] got new tasks
&lt;&#x2F;span&gt;&lt;span&gt;[executor] polling 0
&lt;&#x2F;span&gt;&lt;span&gt;[executor] Received Result: 0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Nearly? It looks like only the first task is running…. Which actually makes sense, because when the first task added finishes, we stop the executor 🤦.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;stopping-the-executor-at-the-right-time&quot;&gt;Stopping the Executor at the right time&lt;&#x2F;h3&gt;
&lt;p&gt;My initial instinct is just to remove the check and break, but then the issue becomes that we then can’t stop the executor.&lt;&#x2F;p&gt;
&lt;p&gt;The next possibility is changing it out for a check whether all the tasks are done. This would work, but it would also mean that if we got through a single cycle of the loop before any tasks were added, it would finish straight away.&lt;&#x2F;p&gt;
&lt;p&gt;I propose we add an atomic variable to &lt;em&gt;allow&lt;&#x2F;em&gt; the executor to stop, and then if that variable is true and all the tasks are finished, we can stop the loop. We can have that variable default to false, and then set it to true when we call &lt;code&gt;Executor::join&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Firstly, the struct definition:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::sync::{Arc, atomic::AtomicBool};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;thread&lt;&#x2F;span&gt;&lt;span&gt;: JoinHandle&amp;lt;()&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;new_task_sender&lt;&#x2F;span&gt;&lt;span&gt;: Sender&amp;lt;BoxedFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;can_stop&lt;&#x2F;span&gt;&lt;span&gt;: Arc&amp;lt;AtomicBool&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then the &lt;code&gt;join&lt;&#x2F;code&gt; method:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::sync::atomic::Ordering;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;join &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.can_stop.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;, Ordering::Relaxed);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.thread.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;error joining thread&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And finally, a few changes to the constructor:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Executor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;start &lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(new_task_sender, new_task_receiver) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; can_stop = Arc::new(AtomicBool::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; executor_can_stop = can_stop.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; thread = std::thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|| {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;snip: variable construction
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;#39;main: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;snip: get tasks
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;snip: poll tasks. NB: we removed the check for breaking the loop
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; executor_can_stop.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(Ordering::Relaxed) {
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; tasks_to_poll.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;all&lt;&#x2F;span&gt;&lt;span&gt;(Option::is_none) {
&lt;&#x2F;span&gt;&lt;span&gt;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break &amp;#39;main&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;                    }
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        });
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ thread, new_task_sender, can_stop }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;does-it-work&quot;&gt;Does it work?&lt;&#x2F;h3&gt;
&lt;p&gt;If we run our same main function from earlier, we get:&lt;&#x2F;p&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo r --quiet
&lt;&#x2F;span&gt;&lt;span&gt;[main] start
&lt;&#x2F;span&gt;&lt;span&gt;[main] started executor
&lt;&#x2F;span&gt;&lt;span&gt;[main] added tasks
&lt;&#x2F;span&gt;&lt;span&gt;[executor] thread started
&lt;&#x2F;span&gt;&lt;span&gt;[executor] channels created
&lt;&#x2F;span&gt;&lt;span&gt;[executor] loop
&lt;&#x2F;span&gt;&lt;span&gt;[executor] got new tasks
&lt;&#x2F;span&gt;&lt;span&gt;[executor] polling 0
&lt;&#x2F;span&gt;&lt;span&gt;[executor] Received Result: 0
&lt;&#x2F;span&gt;&lt;span&gt;[executor] polling 1
&lt;&#x2F;span&gt;&lt;span&gt;[executor] Received Result: 1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;Which looks all correct to me!&lt;&#x2F;p&gt;
&lt;p&gt;However, I want to test some more complicated futures. I’ve removed some of the print statements and created the following main function to test lots of futures at once.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; executor = Executor::start();
&lt;&#x2F;span&gt;&lt;span&gt;   
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;create_task &lt;&#x2F;span&gt;&lt;span&gt;= |&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fut = TimerFuture::new(time);
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[task &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{id}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;] created future&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; start = Instant::now();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = fut.await;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; el = start.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;elapsed&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[task &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{id}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;] awaited future, got &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{res:?}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt; in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{el:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        res
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; task_1 = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;create_task&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;150&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; task_2 = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;create_task&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;150&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; task_3 = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;create_task&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; task_4 = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;create_task&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; start = Instant::now();
&lt;&#x2F;span&gt;&lt;span&gt;    executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(task_1);
&lt;&#x2F;span&gt;&lt;span&gt;    executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(task_2);
&lt;&#x2F;span&gt;&lt;span&gt;    executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(task_3);
&lt;&#x2F;span&gt;&lt;span&gt;    executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(task_4);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[main] created all tasks, joining executor&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; el = start.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;elapsed&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[main] joined, took &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{el:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This creates a number of different tasks, some with similar times, some with different times. Ideally, they should all print out and say that they took as long as we would have expected, and they’ll finish in the order 3,1&#x2F;2,1&#x2F;2,4. Then, the whole thing should only take about as long as the longest task.&lt;&#x2F;p&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo r --quiet
&lt;&#x2F;span&gt;&lt;span&gt;[main] created all tasks, joining executor
&lt;&#x2F;span&gt;&lt;span&gt;[executor] adding new task @ 0
&lt;&#x2F;span&gt;&lt;span&gt;[executor] adding new task @ 1
&lt;&#x2F;span&gt;&lt;span&gt;[executor] adding new task @ 2
&lt;&#x2F;span&gt;&lt;span&gt;[executor] adding new task @ 3
&lt;&#x2F;span&gt;&lt;span&gt;[task 1] created future
&lt;&#x2F;span&gt;&lt;span&gt;[task 2] created future
&lt;&#x2F;span&gt;&lt;span&gt;[task 3] created future
&lt;&#x2F;span&gt;&lt;span&gt;[task 4] created future
&lt;&#x2F;span&gt;&lt;span&gt;[task 3] awaited future, got 50 in 50.005528ms
&lt;&#x2F;span&gt;&lt;span&gt;[executor] Received 50 from 2
&lt;&#x2F;span&gt;&lt;span&gt;[task 1] awaited future, got 150 in 150.008273ms
&lt;&#x2F;span&gt;&lt;span&gt;[executor] Received 150 from 0
&lt;&#x2F;span&gt;&lt;span&gt;[task 2] awaited future, got 150 in 150.023708ms
&lt;&#x2F;span&gt;&lt;span&gt;[executor] Received 150 from 1
&lt;&#x2F;span&gt;&lt;span&gt;[task 4] awaited future, got 200 in 200.004303ms
&lt;&#x2F;span&gt;&lt;span&gt;[executor] Received 200 from 3
&lt;&#x2F;span&gt;&lt;span&gt;[main] joined, took 200.377115ms
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;And that’s what we got! Sick!&lt;&#x2F;p&gt;
&lt;p&gt;We can even run it through &lt;code&gt;miri&lt;&#x2F;code&gt;, and whilst it might take longer, it should still work? We can also add the &lt;code&gt;--release&lt;&#x2F;code&gt; flag. This won’t make it any faster (as we’re still in miri), but it will remove some checks like integer overflows that can cause issues if you aren’t being careful.&lt;&#x2F;p&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo +nightly miri run --release
&lt;&#x2F;span&gt;&lt;span&gt;[main] created all tasks, joining executor
&lt;&#x2F;span&gt;&lt;span&gt;[executor] adding new task @ 0
&lt;&#x2F;span&gt;&lt;span&gt;[executor] adding new task @ 1
&lt;&#x2F;span&gt;&lt;span&gt;[executor] adding new task @ 2
&lt;&#x2F;span&gt;&lt;span&gt;[executor] adding new task @ 3
&lt;&#x2F;span&gt;&lt;span&gt;[task 1] created future
&lt;&#x2F;span&gt;&lt;span&gt;[task 2] created future
&lt;&#x2F;span&gt;&lt;span&gt;[task 3] created future
&lt;&#x2F;span&gt;&lt;span&gt;[task 4] created future
&lt;&#x2F;span&gt;&lt;span&gt;[task 3] awaited future, got 50 in 70.405ms
&lt;&#x2F;span&gt;&lt;span&gt;[executor] Received 50 from 2
&lt;&#x2F;span&gt;&lt;span&gt;[task 1] awaited future, got 150 in 290.625ms
&lt;&#x2F;span&gt;&lt;span&gt;[executor] Received 150 from 0
&lt;&#x2F;span&gt;&lt;span&gt;[task 2] awaited future, got 150 in 346.535ms
&lt;&#x2F;span&gt;&lt;span&gt;[executor] Received 150 from 1
&lt;&#x2F;span&gt;&lt;span&gt;[task 4] awaited future, got 200 in 391.34ms
&lt;&#x2F;span&gt;&lt;span&gt;[executor] Received 200 from 3
&lt;&#x2F;span&gt;&lt;span&gt;[main] joined, took 763.05ms
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;It took longer, but no task executed faster than we would have expected and &lt;em&gt;crucially&lt;&#x2F;em&gt; we don’t have any memory issues!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Bam! We’ve just finished making our async executor and it actually works. If I can work it out, next time will be running the tasks on multiple threads using a pool of workers.&lt;&#x2F;p&gt;
&lt;p&gt;The final code from this is &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;BurntNail&#x2F;36a5543738d208305d59cecbd2fb5c9e&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-0&quot;&gt;
&lt;p&gt;Read &lt;em&gt;noob&lt;&#x2F;em&gt; - the Tokio developers have a ton of features and are working with performance as a goal, rather than being easy to read for someone without any async background experience. &lt;a href=&quot;#fr-0-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Or in &lt;code&gt;C&lt;&#x2F;code&gt;, a &lt;code&gt;void*&lt;&#x2F;code&gt;. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-10&quot;&gt;
&lt;p&gt;Or at least the way I’ve done it. &lt;a href=&quot;#fr-10-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>Integer Compression</title>
          <pubDate>Wed, 30 Oct 2024 00:00:00 +0000</pubDate>
          <author>Jack Maguire</author>
          <link>https://maguire.tech/posts/integercmp/</link>
          <guid>https://maguire.tech/posts/integercmp/</guid>
          <description xml:base="https://maguire.tech/posts/integercmp/">&lt;p&gt;Recently, I’ve been working on a compression engine (&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BurntNail&#x2F;Souris&quot;&gt;Souris&lt;&#x2F;a&gt;), and I’m really pretty proud of some of my compression tricks, so I thought I’d go through a few of them here!&lt;&#x2F;p&gt;
&lt;p&gt;We’ll start with one of the fundamental ones - integers. The main point of this compression is to get integers to take as few bytes as possible - if I’m encoding the length of a list, the chances are that it might only be 10 or a 100, which could probably fit in one byte, but normally takes 8&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-0-1&quot;&gt;&lt;a href=&quot;#fn-0&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For reference, whenever I mention &lt;code&gt;serialising&lt;&#x2F;code&gt;, I’m talking about turning an in-memory structure into a bunch of bytes that can be written, and I’m using &lt;code&gt;deserialising&lt;&#x2F;code&gt; to refer to turning the bytes back into an in-memory structure.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting started&lt;&#x2F;h2&gt;
&lt;p&gt;The way I think is best to do this is to go through two main stages - we first take in a number and turn it into an intermediary form that’s easy to serialise and deserialise as well as being easy to get from&#x2F;into a normal number type like &lt;code&gt;u32&lt;&#x2F;code&gt; or &lt;code&gt;usize&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For now, we’ll only be dealing with unsigned integers, as signed integers make this quite messy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;usize-integer&quot;&gt;&lt;code&gt;usize&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Integer&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;We’ll first create our intermediary struct &lt;code&gt;Integer&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX_BYTES&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;BITS &lt;&#x2F;span&gt;&lt;span&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Integer {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;content&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; MAX_BYTES],
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;bytes_used&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can see that we’ve got space to store all the bytes for anything up to a &lt;code&gt;u128&lt;&#x2F;code&gt;, the current largest integer, as well as a variable to store how many bytes we’ve used in this.&lt;&#x2F;p&gt;
&lt;p&gt;For now, let’s start by making the conversion from &lt;code&gt;usize&lt;&#x2F;code&gt;, and then we can work out how to generalise it. In Rust, when converting infallibly&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-10-1&quot;&gt;&lt;a href=&quot;#fn-10&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, we typically implement &lt;code&gt;From&lt;&#x2F;code&gt;, so let’s add a skeleton for that.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;From&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Integer {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        todo!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;AGRRGGHHH!!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We need to fill out those bytes, and luckily &lt;code&gt;usize&lt;&#x2F;code&gt; has a method called &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.usize.html#method.to_le_bytes&quot;&gt;&lt;code&gt;usize::to_le_bytes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which converts our &lt;code&gt;usize&lt;&#x2F;code&gt; into an array of little-endian bytes. Little-endian bytes are the standard on modern machines, so it is easier for the CPU to get it in that form, so we can use that.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; content = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX_BYTES&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i, b) in n.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_le_bytes&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    content[i] = b;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That all works! The next part of our scaffold is working out how many bytes we actually used here. There’s two ways we could do this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;We could use &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.usize.html#method.ilog2&quot;&gt;&lt;code&gt;usize::ilog2&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and some maths to work out how many bytes we used.&lt;&#x2F;li&gt;
&lt;li&gt;We could find the last full byte and work out how many bytes are empty, and use that to work out the number we used.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Having done both, they’re both equally good solutions. However, I’ve encountered some issues with the first&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-20-1&quot;&gt;&lt;a href=&quot;#fn-20&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; as the maths isn’t 100% obvious on reading. It’s the eternal dilemma of code - I love the sick one-liners and cool tricks, but I spend far more time reading the code than writing it so I’m going to go with the simpler solution here.&lt;&#x2F;p&gt;
&lt;p&gt;To go with the second, we just need to find the index of the last byte that isn’t empty, and then add 1 to get the number of bytes we used.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; content = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX_BYTES&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; last_non_zero_byte = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i, b) in n.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_le_bytes&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    content[i] = b;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; b != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        last_non_zero_byte = i;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Integer {
&lt;&#x2F;span&gt;&lt;span&gt;    content,
&lt;&#x2F;span&gt;&lt;span&gt;    bytes_used: last_non_zero_byte + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we add a quick &lt;code&gt;#[derive(Debug)]&lt;&#x2F;code&gt; to the &lt;code&gt;Integer&lt;&#x2F;code&gt; declaration, and a quick main function, we get:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main &lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; int: Integer = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1000.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{int:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which then outputs:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;Integer { content: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;232&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;], bytes_used: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We used two bytes, and those numbers look alright to me so let’s keep on going!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;integer-vec-u8&quot;&gt;&lt;code&gt;Integer&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Theoretically here we just need to serialise the number of bytes used (which we can do in just one byte, as &lt;code&gt;MAX_BYTES&lt;&#x2F;code&gt; is equal to 16 which is less than &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.u8.html#associatedconstant.MAX&quot;&gt;&lt;code&gt;u8::MAX&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;), and then add all of the relevant bytes!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Integer {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;ser &lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; output = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;        output.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.bytes_used as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;        output.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;extend&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.content[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.bytes_used]);
&lt;&#x2F;span&gt;&lt;span&gt;        output
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Theoretically here we could even skip serialising the length! However, that trick only works if you are only dealing with Integers alone in arrays, as otherwise it isn’t clear how much to read. If you do serialise the length, you could convert our next &lt;code&gt;deser&lt;&#x2F;code&gt; method to use something like &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;sourisdb&#x2F;latest&#x2F;sourisdb&#x2F;utilities&#x2F;cursor&#x2F;struct.Cursor.html&quot;&gt;&lt;code&gt;sourisdb::Cursor&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to only take as many bytes as needed from a longer series of bytes.&lt;&#x2F;p&gt;
&lt;p&gt;If we then modify our &lt;code&gt;main&lt;&#x2F;code&gt; method to print out the serialised version&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-30-1&quot;&gt;&lt;a href=&quot;#fn-30&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, we get this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;232&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That makes sense! We get the two from the two bytes used, then the same bytes from earlier. Congrats! We’ve just managed to turn an 8-byte &lt;code&gt;usize&lt;&#x2F;code&gt; into a 3-byte &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt;!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;vec-u8-integer&quot;&gt;&lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Integer&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;But what about the other way around?&lt;&#x2F;p&gt;
&lt;p&gt;This is even easier! We just need to read in the length, then read in those bytes and add them to an &lt;code&gt;Integer&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Integer {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;deser &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; len = bytes[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; content = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX_BYTES&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i, b) in (&amp;amp;bytes[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;..(len + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)]).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;copied&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;            content[i] = b;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            content,
&lt;&#x2F;span&gt;&lt;span&gt;            bytes_used: len
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we go back to our main method and deserialise the serialised bytes, we get this out:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;Integer { content: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;232&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;], bytes_used: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which is the same as earlier!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;integer-usize&quot;&gt;&lt;code&gt;Integer&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;usize&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Our last step is to get it back into a &lt;code&gt;usize&lt;&#x2F;code&gt;. This is the first step where we could fail - we need to make sure that our destination type has enough space. For example, we wouldn’t be able to store our current test value inside of a &lt;code&gt;u8&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s start with a skeleton.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;TryFrom&amp;lt;Integer&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;usize {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Error = ();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;try_from &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;: Integer) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        todo!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;AARRGGHH&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because we’re only dealing with one error type right now, and this is just a proof-of-concept, I just used &lt;code&gt;()&lt;&#x2F;code&gt; as the error type.&lt;&#x2F;p&gt;
&lt;p&gt;So, earlier we used &lt;code&gt;usize::to_le_bytes&lt;&#x2F;code&gt; to get our &lt;code&gt;usize&lt;&#x2F;code&gt; into some bytes, so we should probably use &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.usize.html#method.from_le_bytes&quot;&gt;&lt;code&gt;usize::from_le_bytes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to turn some bytes into a &lt;code&gt;usize&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;As with always, we can just create enough bytes to fill the method signature, then just fill them in!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;T_BYTES&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;BITS &lt;&#x2F;span&gt;&lt;span&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; n.bytes_used &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;T_BYTES &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Err(());
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; output = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;T_BYTES&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i, b) in n.content.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(n.bytes_used).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    output[i] = b;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Ok(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;::from_le_bytes(output))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we try that in this main method:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; int: Integer = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1000.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; sered = int.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;ser&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; deser = Integer::deser(&amp;amp;sered);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; back_out: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;= deser.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_into&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{back_out}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We get $1000$ out, and since $1000 \equiv 1000$, we should be all good?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;let-s-check&quot;&gt;Let’s check&lt;&#x2F;h2&gt;
&lt;p&gt;This is a great opportunity to introduce &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;proptest&quot;&gt;&lt;code&gt;proptest&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which we’ll be using to work out whether our algorithm actually works, or only works on certain inputs.&lt;&#x2F;p&gt;
&lt;p&gt;We’re pretty sure it works on 1000, but we haven’t checked any other number. We could write a test to check every number, but that would take far too long&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-40-1&quot;&gt;&lt;a href=&quot;#fn-40&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; to be reasonable to be running as frequently as tests should run.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;proptest&lt;&#x2F;code&gt; is designed to check a random set of inputs from a set of all possible inputs, and when it finds an error, it’ll try to ‘reduce’ it down to the simplest input that results in an error. It isn’t guaranteed to find all the edge cases, but it can be incredibly useful for checking lots of cases without having to basically re-write the test harness on every run.&lt;&#x2F;p&gt;
&lt;p&gt;We can add &lt;code&gt;proptest&lt;&#x2F;code&gt; to our &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; following their instructions, and then get started with some tests!&lt;&#x2F;p&gt;
&lt;p&gt;Our main four use-cases are the four stages we went through earlier, so we can have these two tests to test all of that:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;A test to ensure that it can go from &lt;code&gt;usize&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Integer&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;usize&lt;&#x2F;code&gt; correctly.&lt;&#x2F;li&gt;
&lt;li&gt;A test to go from &lt;code&gt;usize&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Integer&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Integer&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;usize&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If these tests fail, we can also add more tests to diagnose exactly where the error comes from.&lt;&#x2F;p&gt;
&lt;p&gt;This is what I’d write for that:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cfg&lt;&#x2F;span&gt;&lt;span&gt;(test)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod &lt;&#x2F;span&gt;&lt;span&gt;tests {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use super&lt;&#x2F;span&gt;&lt;span&gt;::*;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;proptest::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    proptest!{
&lt;&#x2F;span&gt;&lt;span&gt;        #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;test&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;check_in_memory &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; int = Integer::from(n);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; back = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;::try_from(int).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;            prop_assert_eq!(back, n);
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;test&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;check_serialised &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; int = Integer::from(n);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; sered = int.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;ser&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; back_int = Integer::deser(&amp;amp;sered);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; back_n = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;::try_from(back_int).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            prop_assert_eq!(back_n, n);
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we then &lt;code&gt;cargo test&lt;&#x2F;code&gt; or even &lt;a href=&quot;https:&#x2F;&#x2F;nexte.st&#x2F;&quot;&gt;&lt;code&gt;cargo nextest run&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, we see that all of our tests pass! Since we’re checking all of the functionality here&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-50-1&quot;&gt;&lt;a href=&quot;#fn-50&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, I’m confident that we can move on!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;small-numbers&quot;&gt;Small Numbers&lt;&#x2F;h2&gt;
&lt;p&gt;There’s one thing that’s annoying me about this right now. If we were to try to expand this to &lt;code&gt;u8&lt;&#x2F;code&gt;, most numbers would have to take two bytes - one for the length (which is always one) and one for the content.&lt;&#x2F;p&gt;
&lt;p&gt;However, there’s actually a trick we can modify from the &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;bincode&quot;&gt;&lt;code&gt;bincode&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bincode-org&#x2F;bincode&#x2F;blob&#x2F;trunk&#x2F;docs&#x2F;spec.md&quot;&gt;specification&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We always know that our integers can be no more than 8 bytes long, so our first byte will always be in the range &lt;code&gt;0..=8&lt;&#x2F;code&gt;. There’s 247 numbers we aren’t using there, so we can say that, for the first byte, any number in the range &lt;code&gt;0..=247&lt;&#x2F;code&gt; represents that number, but any number greater than that represents $247 + x$ where $x$ is the length.&lt;&#x2F;p&gt;
&lt;p&gt;For convenience, we can also add a constant to the top of our file that holds &lt;code&gt;247&lt;&#x2F;code&gt; - this also makes it clearer to future programmers why the constant is the way it is.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ONE_BYTE_MAX_SIZE&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX &lt;&#x2F;span&gt;&lt;span&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX_BYTES&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To implement this, we can just add this if statement to the top of our &lt;code&gt;ser&lt;&#x2F;code&gt; method, and change the length serialisation below:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.bytes_used &amp;lt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; first_byte = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.content[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; first_byte as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ONE_BYTE_MAX_SIZE &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;vec![first_byte];
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; output = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;output.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.bytes_used + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ONE_BYTE_MAX_SIZE&lt;&#x2F;span&gt;&lt;span&gt;) as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;output.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;extend&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.content[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.bytes_used]);
&lt;&#x2F;span&gt;&lt;span&gt;output
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And change our &lt;code&gt;deser&lt;&#x2F;code&gt; method to do some checks to the &lt;code&gt;len&lt;&#x2F;code&gt; and fix it if it is representing a length:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; first_byte = bytes[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; content = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX_BYTES&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; first_byte as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ONE_BYTE_MAX_SIZE &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    content[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] = first_byte;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bytes_used = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;::from(content[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        content, bytes_used
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; len = first_byte as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ONE_BYTE_MAX_SIZE&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i, b) in (&amp;amp;bytes[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;..(len + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)]).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;copied&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    content[i] = b;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    content,
&lt;&#x2F;span&gt;&lt;span&gt;    bytes_used: len
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can then re-run our tests, and it all works!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;left-to-the-reader&quot;&gt;Left to the Reader&lt;&#x2F;h2&gt;
&lt;p&gt;Whilst &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;BurntNail&#x2F;1c5f33afd4b10b4bc10bb89a387dce94&quot;&gt;this code&lt;&#x2F;a&gt; all works, there are several things that would need to be done before I’d use it in a production environment:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;error-handling&quot;&gt;Error Handling&lt;&#x2F;h3&gt;
&lt;p&gt;Right now almost every method is infallible, but there are a ton of methods that have failure modes. For example, what if the &lt;code&gt;bytes&lt;&#x2F;code&gt; in &lt;code&gt;deser&lt;&#x2F;code&gt; don’t have enough bytes?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;utility-traits&quot;&gt;Utility Traits&lt;&#x2F;h3&gt;
&lt;p&gt;This code is pretty hard to use in a larger codebase right now - ideally you would implement a number of traits like &lt;code&gt;FromStr&lt;&#x2F;code&gt;, &lt;code&gt;Display&lt;&#x2F;code&gt;, &lt;code&gt;Debug&lt;&#x2F;code&gt;, and maybe even some of the &lt;code&gt;std::ops&lt;&#x2F;code&gt; traits.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;more-types&quot;&gt;More types&lt;&#x2F;h3&gt;
&lt;p&gt;Currently, this code only supports dealing with &lt;code&gt;usize&lt;&#x2F;code&gt;s&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-60-1&quot;&gt;&lt;a href=&quot;#fn-60&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; - what about &lt;code&gt;u16&lt;&#x2F;code&gt;s or &lt;code&gt;u8&lt;&#x2F;code&gt;s or even &lt;code&gt;u128&lt;&#x2F;code&gt;s? Ideally, you’d implement some kind of macro to convert the code - it shouldn’t be too hard, as you just need to change some of the types as the code isn’t really that dependent on it being a &lt;code&gt;usize&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;negative-numbers&quot;&gt;Negative Numbers&lt;&#x2F;h3&gt;
&lt;p&gt;Negative numbers are &lt;em&gt;difficult&lt;&#x2F;em&gt;, but possible - if this post gets much interaction I’ll share how I managed to get them working. If you decide to have a go at it, don’t underestimate it - that algorithm took me 4 iterations to actually get something that worked and that I understood. If you want to see a hint of my pain, check the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BurntNail&#x2F;Souris&#x2F;blame&#x2F;8d607c37efec6cee6f75c550512ebd5890013f0a&#x2F;crates&#x2F;sourisdb&#x2F;src&#x2F;types&#x2F;integer.rs&quot;&gt;blame&lt;&#x2F;a&gt; for that file and weep.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-production-code&quot;&gt;My Production code&lt;&#x2F;h2&gt;
&lt;p&gt;As of writing, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BurntNail&#x2F;Souris&#x2F;blob&#x2F;8d607c37efec6cee6f75c550512ebd5890013f0a&#x2F;crates&#x2F;sourisdb&#x2F;src&#x2F;types&#x2F;integer.rs&quot;&gt;this&lt;&#x2F;a&gt; is my latest iteration - it includes all of the above, and has functioned incredibly effectively as a backbone for all of &lt;code&gt;sourisdb&lt;&#x2F;code&gt;’s integer serialisation needs. As you can see, once you implement the extra traits it &lt;strong&gt;balloons&lt;&#x2F;strong&gt; to almost a thousand lines of code (including docs&#x2F;tests).&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-0&quot;&gt;
&lt;p&gt;Assuming a 64-bit computer, and &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;2098149&#x2F;what-platforms-have-something-other-than-8-bit-char&quot;&gt;8-bit bytes&lt;&#x2F;a&gt;. &lt;a href=&quot;#fr-0-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-10&quot;&gt;
&lt;p&gt;In such a way that we cannot fail. &lt;a href=&quot;#fr-10-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-20&quot;&gt;
&lt;p&gt;Skill issue? 100% yes. &lt;a href=&quot;#fr-20-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-30&quot;&gt;
&lt;p&gt;Left as an exercise to the reader. &lt;a href=&quot;#fr-30-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-40&quot;&gt;
&lt;p&gt;I ran a quick test on my laptop, and it took 1962s to reach $3378000000000$. Assuming it stays at a constant rate (which it likely won’t, because as the numbers get bigger, more bytes will have to be copied), it’ll take around 340 years to reach &lt;code&gt;usize::MAX&lt;&#x2F;code&gt; on my laptop. &lt;a href=&quot;#fr-40-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-50&quot;&gt;
&lt;p&gt;And I’ve already written this algorithm and tested it far more thoroughly in my own time. &lt;a href=&quot;#fr-50-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-60&quot;&gt;
&lt;p&gt;And yes &lt;code&gt;u64&lt;&#x2F;code&gt;s on 64-bit platforms and &lt;code&gt;u32&lt;&#x2F;code&gt;s on 32-bit platforms. &lt;a href=&quot;#fr-60-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>Cameras???</title>
          <pubDate>Sat, 24 Feb 2024 00:00:00 +0000</pubDate>
          <author>Jack Maguire</author>
          <link>https://maguire.tech/posts/cameras/</link>
          <guid>https://maguire.tech/posts/cameras/</guid>
          <description xml:base="https://maguire.tech/posts/cameras/">&lt;p&gt;Cameras have 4 main settings that affect the look of a photo - but how do they work and what do they mean?&lt;&#x2F;p&gt;
&lt;p&gt;Over Christmas, I got a new Camera - an EOS R10 with a pair of lenses, and I’ll be using it to explain what the different settings do. The sensor is really good and it spits out incredibly high quality images. For the purposes of demonstration, I’ll be using my cat on a beanbag as the &lt;em&gt;purr&lt;&#x2F;em&gt;fect subject. Unless otherwise specified, I’ll be using a 50mm lens.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-the-main-settings&quot;&gt;What are the main settings?&lt;&#x2F;h2&gt;
&lt;p&gt;Here, I’ll only be talking about the main mechanical settings - nothing really artistic like profiles, composition or how to get your control ring to control ISO.&lt;&#x2F;p&gt;
&lt;p&gt;In my opinion, there are 4 main mechanical settings:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Aperture&lt;&#x2F;li&gt;
&lt;li&gt;Shutter Speed&lt;&#x2F;li&gt;
&lt;li&gt;ISO&lt;&#x2F;li&gt;
&lt;li&gt;Focal Length&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;However, to understand the effects of each of those changes (in my humble opinion) you need to actually know how a camera takes a photo, even if only at a very basic level.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;so-how-do-we-go-from-photons-to-pixels&quot;&gt;So how do we go from photons to pixels?&lt;&#x2F;h3&gt;
&lt;p&gt;Firstly - here, I’ll just be talking about digital cameras - although the main difference is that for film you’d swap ‘sensor’ for ‘film’ and add steps for development. ISO is also called Speed for film and comes factory set in the particular roll of film.&lt;&#x2F;p&gt;
&lt;p&gt;Light is emitted from sources in the form of photons - each photon can act like a wave, and here we’ll be focusing on that part&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-0-1&quot;&gt;&lt;a href=&quot;#fn-0&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Every wave has a &lt;em&gt;wavelength&lt;&#x2F;em&gt;, which is a measure of the distance between two peaks of that wave. When light hits the rods and cones in your eyes, the colours come from the different wavelengths interacting differently with your eyes - for example we see red at about 700nm, green at about 525nm and blue at about 425nm&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The only principle difference between radio waves, microwaves and visible light is the wavelength - our eyes only see what we call visible light, but some animals see far more than we can.&lt;&#x2F;p&gt;
&lt;p&gt;Most light sources emit a variety of wavelengths (white is an equal mix of the whole visible spectrum), and as light bounces around some of those surfaces some of the wavelengths get absorbed. Eventually, only the wavelengths that didn’t get absorbed (or just spread elsewhere) reach our eyes and that influences what colour we see. When I see the green cover for my pad of paper, that tells me that the ink absorbs every wavelength apart from the ones that correspond to green.&lt;&#x2F;p&gt;
&lt;p&gt;The same way that light can hit your eyes, it can also hit a camera sensor - they use complicated electronics to detect the different wavelengths of light and their different quantities to produce binary data that can then be displayed on our screens as pixels in photos.&lt;&#x2F;p&gt;
&lt;p&gt;However, you never see anyone ever take photos with sensors alone and they always use a lens on top - why? So, it’s partially to protect the sensor which is the most crucial part of the camera - if I scratch the dial to change modes, nobody cares but a broken sensor will ruin a camera body. The other reason is to help control the light and ensure it enters the sensor perpendicularly. Normally, the light entering a sensor might come from all different kinds of angles and the lens just makes them all straight using glass. The lens also controls Aperture, but we’ll get there when we get there.&lt;&#x2F;p&gt;
&lt;p&gt;To actually take a photo, a digital camera just resets a few counters and then waits for a specified amount of time for the sensor to accumulate data and then it spits it all out. Simple!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-settings-themselves&quot;&gt;The Settings Themselves&lt;&#x2F;h2&gt;
&lt;p&gt;Now, after that fun physics detour, time for the settings themselves.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;shutter-speed&quot;&gt;Shutter Speed&lt;&#x2F;h3&gt;
&lt;p&gt;The Shutter Speed is probably the simplest to understand - the specified amount of time that the sensor waits is the shutter speed. So, technically it should be the Shutter Time or the Exposure Time or something because it doesn’t measure distance, but I don’t make the rules. Being serious, this might have come from film, where you could qualify the distance as the width of the film, but I’m not a photography etymologist.&lt;&#x2F;p&gt;
&lt;p&gt;Shutter Speed is usually referred to as 1&#x2F;x where x is some nice number, but for longer exposures it’ll say the number of seconds. Obviously, if you have a longer shutter speed then you’ll get more light but there’s a cost! If you set the shutter speed to be too high, then you have to start worrying about whether your camera will move during the exposure. If we take this back to the photons, in a shorter exposure all of the photons hitting the specific spots on the sensor will have taken similar paths, but if you’re taking a photo of usain bolt over a second, then the photons hitting the same spots on the sensor are taking very different paths which leads to absorption of different wavelengths and so different colours. It’s blurry, to put it simply.&lt;&#x2F;p&gt;
&lt;p&gt;Here, I’ve got two photos of my cat (ISO 2000, F1.8) - one taken at 1&#x2F;20 and one at 1&#x2F;80.


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;camera_workings&amp;#x2F;lowshutter.JPG&quot;&#x2F;&gt;
    &lt;figcaption&gt;1&amp;#x2F;80&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;camera_workings&amp;#x2F;highshutter.JPG&quot;&#x2F;&gt;
    &lt;figcaption&gt;1&amp;#x2F;20&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If we assume that my hand stayed relatively still, we can see that the second photo is far blurrier than the second. However, in the second photo we can actually see the cat which is a plus.&lt;&#x2F;p&gt;
&lt;p&gt;Clearly, we need another way to change the light.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;aperture&quot;&gt;Aperture&lt;&#x2F;h3&gt;
&lt;p&gt;Inside the lens, there are ‘blades’ which form rotate in to the centre to form a circle. The Aperture measures how close they are together. Counter-intuitively, a larger aperture means a smaller number.&lt;&#x2F;p&gt;
&lt;p&gt;Here, I’ve got 3 photos of my lens taken at varying apertures from my phone.


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;camera_workings&amp;#x2F;small_ap.jpeg&quot;&#x2F;&gt;
    &lt;figcaption&gt;Large Aperture&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;camera_workings&amp;#x2F;med_ap.jpeg&quot;&#x2F;&gt;
    &lt;figcaption&gt;Medium Aperture&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;camera_workings&amp;#x2F;huge_ap.jpeg&quot;&#x2F;&gt;
    &lt;figcaption&gt;Small Aperture&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Common sense dictates that the a bigger hole would let in more light and here common sense is 100% correct. I have another two photos below (1&#x2F;80, ISO 8000):


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;camera_workings&amp;#x2F;highap.JPG&quot;&#x2F;&gt;
    &lt;figcaption&gt;F4&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;camera_workings&amp;#x2F;lowap.JPG&quot;&#x2F;&gt;
    &lt;figcaption&gt;F1.8&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There’s also another effect at play here with the aperture which is far more subtle. A wide aperture makes for a far shallower focal plane. I can hear you already - &lt;code&gt;Too much jargon Jack!&lt;&#x2F;code&gt;, &lt;code&gt;What does that mean?&lt;&#x2F;code&gt;, &lt;code&gt;Is that related to my glasses?&lt;&#x2F;code&gt;. The answer to the third is actually yes! The focal plane represents where is in-focus for the image - if you’re in the focal plane then you’ll be lovely and sharp and if not then you’ll be blurred. A varifocal lens for a pair of glasses would just mean that you can have multiple focal planes with one lens&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-15-1&quot;&gt;&lt;a href=&quot;#fn-15&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. A shallower focal plane means that more will be in blur, which is incredible for portraits but maybe less good for taking a big group photo. The farther away you are from the subject, the more this diminishes (eg. feel free to use F1.8 for landscapes), but for close subjects this can be an issue (above, you can see my cat’s back out of focus).&lt;&#x2F;p&gt;
&lt;p&gt;To provide an example of why I almost always stick to F1.8 for things like portraits, I’ll put a photo of myself below that a friend took:


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;camera_workings&amp;#x2F;mug.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;Background Blur ❤️, Seeing my face 😑&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Without that wide aperture we couldn’t have got that background blur&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-20-1&quot;&gt;&lt;a href=&quot;#fn-20&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The extra light also allowed me to put a relatively low ISO (leading to less digital noise, as you’ll learn in a second) and a lower shutter speed (to remove blur from shaky hands).&lt;&#x2F;p&gt;
&lt;p&gt;So to conclude, the tradeoff for increasing aperture is more light in exchange for a shallower focal plane.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;iso&quot;&gt;ISO&lt;&#x2F;h3&gt;
&lt;p&gt;The nerdier amongst you may have recognised this acronym as being for the International Standards Organisation and quickly dismissed it for being unrelated to just photography - I’m here to tell you that this is the correct acronym expansion&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-30-1&quot;&gt;&lt;a href=&quot;#fn-30&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Why?? I have not the foggiest clue.&lt;&#x2F;p&gt;
&lt;p&gt;The ISO represents the sensitivity of the sensor - the higher the ISO, the brighter the photo! There isn’t anything mechanical about this - it’s just the sensor. See more photos (F4, 1&#x2F;80):


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;camera_workings&amp;#x2F;lowiso.JPG&quot;&#x2F;&gt;
    &lt;figcaption&gt;Low ISO&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;camera_workings&amp;#x2F;highiso.JPG&quot;&#x2F;&gt;
    &lt;figcaption&gt;High ISO&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;&lt;&#x2F;p&gt;
&lt;p&gt;At first glance, this seems to have no real effect but when you look closer at the high ISO photo, it seems &lt;em&gt;off&lt;&#x2F;em&gt;. If you zoom in sufficiently, you’ll also start to see that the pixels average out to a nicer colour, but individually are a mess. We call that digital noise and that is the tradeoff for ISO - more light but more noise at higher ISO.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;focal-length&quot;&gt;Focal Length&lt;&#x2F;h3&gt;
&lt;p&gt;The focal length is like the zoom, but instead of cropping, we just choose to focus on different light rays. It is measured in mm for millimetres which approximately measures the distance between the front of the lens and the sensor&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-40-1&quot;&gt;&lt;a href=&quot;#fn-40&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. A longer lens means more zoomed in.&lt;&#x2F;p&gt;
&lt;p&gt;Here are two example photos taken on my other lens (F6.3, 1&#x2F;50, ISO 16000):


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;camera_workings&amp;#x2F;18mm.JPG&quot;&#x2F;&gt;
    &lt;figcaption&gt;18mm&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;camera_workings&amp;#x2F;150mm.JPG&quot;&#x2F;&gt;
    &lt;figcaption&gt;150mm&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;&lt;&#x2F;p&gt;
&lt;p&gt;My other lens is the lens that came with my camera and goes from 15 to 180mm. As you can see, the light isn’t vastly changed by the focal length (except for an exception I’ll get into), but the main thing that is clearly changed is what photographers call Compression. In the 150mm photo, the cat and the beanbag look to be at about the same depth and that makes total sense - I took that photo from 3 or 4 metres away, and the cat is centimetres away from the beanbag. However, I took the other photo only centimetres from the cat’s nose so you can really clearly see the depth in the photo which makes his face pop.&lt;&#x2F;p&gt;
&lt;p&gt;Because of that compression, we also change the focal plane, which is how lots of people choose to simulate the same effects you get on a lower aperture. The reason you need to simulate those effects is the same reason that I almost never take my 18-150mm with me unless I’m going outside - you lose light with a cheap lens &lt;em&gt;really&lt;&#x2F;em&gt; easily. To buy both new, my 50mm and 18-150mm lenses are about the same price (if not, the zoom lens being more expensive) but my 50mm lens has a maximum aperture of F1.8 and the 18-150mm has a &lt;strong&gt;floating&lt;&#x2F;strong&gt; maximum aperture of F3.6 to F6.3&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-50-1&quot;&gt;&lt;a href=&quot;#fn-50&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Whilst that doesn’t seem like a lot, aperture doesn’t increase as a continuous variable - it goes in stops which jump larger gaps as you get higher, which means that F3.6 is closer to F6.3 than to F1.8. This means that even if I can get more people in a photo with an 18mm lens, it’ll be a better quality photo (as I can use a higher aperture and so a lower ISO) with my 50mm lens. Since I normally shoot in manual mode, this also means that as I zoom in, the light available to the sensor decreases which means that I have to adjust two or three settings at once - not ideal, especially if I need to get a photo quickly in a crowded touristy area.&lt;&#x2F;p&gt;
&lt;p&gt;My prime lens is far cheaper and has a far higher maximum aperture because it is far easier for manufacturers to make prime lenses with fast (fast glass means a higher maximum aperture and vice versa), and so fast variable lenses are &lt;em&gt;incredibly expensive&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing Thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;I freaking love my camera - not only has it allowed me to capture some really precious moments, even in the time just since Christmas, it’s given me the perfect excuse to learn more about optics and physics and to deep dive into a field I knew I wanted to look at but had never had the opportunity to before.&lt;&#x2F;p&gt;
&lt;p&gt;Learning about all of the different settings has also allowed me to make interesting artistic choices, where I’d always just used the Automatic mode on cameras I’d borrowed before to make the photos &lt;em&gt;perfect&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re looking to get into photography, I can recommend the following youtube channels most:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@PetaPixel&quot;&gt;PetaPixel&lt;&#x2F;a&gt; does a &lt;em&gt;ton&lt;&#x2F;em&gt; of reviews and roundups, and the host is really charismatic.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@simon_dentremont&quot;&gt;Simon d’Entremont&lt;&#x2F;a&gt; does a lot of more educational content, and is always incredibly concise and clear.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@froknowsphoto&quot;&gt;Jared Polin&lt;&#x2F;a&gt; does more week-to-week news as well as reviews as well as expeditions and things adjacent to photography. He can be a bit modern-youtube-shouty-and-clickbaity&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-60-1&quot;&gt;&lt;a href=&quot;#fn-60&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, but I’d still 100% recommend.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-0&quot;&gt;
&lt;p&gt;This is intro to photography, not intro to Quantum Physics - we’ll leave it here for now, and probably for the foreseeable future. &lt;a href=&quot;#fr-0-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;This is why some people call purple a &lt;em&gt;fake&lt;&#x2F;em&gt; colour - you get purple when you mix red and blue light, but technically the middle of red and blue is green in the electromagnetic spectrum. As far as I believe, purple has just as much a right as any other colour, because the part that actually matters to people is what we see. ALso - by that logic, white is a fake colour. &lt;a href=&quot;#fr-5-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-15&quot;&gt;
&lt;p&gt;The glass inside the camera shifts using motors to focus at different distances in case you were wondering - if you here some whirring as you focus the image, that’s what it is. &lt;a href=&quot;#fr-15-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-20&quot;&gt;
&lt;p&gt;Except maybe without focal length shenanigans - and I do mean shenanigans (put a pin in this for now though). &lt;a href=&quot;#fr-20-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-30&quot;&gt;
&lt;p&gt;English speaking peoples will be forever cursed with the limits of 3-letter acronyms - 17576 sounds like a lot of combinations until you realise it’s really not (just ask the &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;jfOUVYQnuhw&quot;&gt;ICAO 🤣&lt;&#x2F;a&gt;). &lt;a href=&quot;#fr-30-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-40&quot;&gt;
&lt;p&gt;Approximately because of things like &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Crop_factor&quot;&gt;Crop Factor&lt;&#x2F;a&gt;, internal zooming lenses and advances in lens technology from when the convention started. &lt;a href=&quot;#fr-40-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-50&quot;&gt;
&lt;p&gt;So here I took both photos at F6.3 to keep the light as similar as possible, whilst keeping the compression effects. &lt;a href=&quot;#fr-50-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-60&quot;&gt;
&lt;p&gt;I also can’t blame him at all for that - that’s the way the platform is going right now, and he’s the one who can afford to take $60k of photography gear on an expedition in Kenya. &lt;a href=&quot;#fr-60-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>London My Beloved</title>
          <pubDate>Sat, 27 Jan 2024 00:00:00 +0000</pubDate>
          <author>Jack Maguire</author>
          <link>https://maguire.tech/ramblings/london-my-beloved/</link>
          <guid>https://maguire.tech/ramblings/london-my-beloved/</guid>
          <description xml:base="https://maguire.tech/ramblings/london-my-beloved/">&lt;p&gt;I’ve lived in London for a pretty long while and I’ve done a lot of what there is to be done. Here, I’ll be detailing my opinions on stuff I’ve done. I’ll try to vaguely organise it into the different parts of London, but there’s public transport so feel free to hop, jump and skip around to whatever interests you.&lt;&#x2F;p&gt;
&lt;p&gt;If you are visiting, I’d also definitely have a gander over my previous article about &lt;a href=&quot;https:&#x2F;&#x2F;maguire.tech&#x2F;ramblings&#x2F;tfl-for-dummies&#x2F;&quot;&gt;the public transport here&lt;&#x2F;a&gt; because it’s the best way to get around.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;west-end&quot;&gt;West End&lt;&#x2F;h2&gt;
&lt;p&gt;A visit to the West End gets you to a lovely part of Central London. You’ve got most of the London theatres and you can see everything from Six to Hamilton. I’ve been to see a fair few productions, so here are my general opinions on some of the ones that made an impact on me (but you’ll be happy with pretty much anything).&lt;&#x2F;p&gt;
&lt;p&gt;If you’re after snacks, I’d recommend grabbing something outside of the theatre because it’s always insanely expensive inside. The same goes for the cinemas if that’s your poison - there’s corner shops everywhere.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;six&quot;&gt;Six&lt;&#x2F;h3&gt;
&lt;p&gt;Desc: &lt;em&gt;(historical - stories told from the perspectives of each of Henry VIII’s wives)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.sixthemusical.com&#x2F;london&quot;&gt;Six&lt;&#x2F;a&gt; is incredible, and I would highly recommend going to watch. When I went, there were incredible vibes all around and you’ll definitely come out smiling.&lt;&#x2F;p&gt;
&lt;p&gt;Interestingly enough, this was started at &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Edinburgh_Festival_Fringe&quot;&gt;Fringe&lt;&#x2F;a&gt; - a huge performing arts festival in Scotland. Anyone can perform (assuming you can book a venue &amp;amp; accommodation 🤣), so you’ll often see lots of university companies. You also hear about productions starting at Fringe, getting noticed and then getting West End &amp;amp; Broadway Runs (with Six being one of the most common examples of a Fringe production doing incredibly well).&lt;&#x2F;p&gt;
&lt;p&gt;It was also fun for me to see some new parts to Henry VIII’s wives which I didn’t know about before. The &lt;a href=&quot;https:&#x2F;&#x2F;open.spotify.com&#x2F;album&#x2F;5jTDaLFNQovRyjNcWe4cZh?si=agbVb4i0SRajFvxRLhxqUg&quot;&gt;songs&lt;&#x2F;a&gt; were also great and stays on my playlist to this day&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-0-1&quot;&gt;&lt;a href=&quot;#fn-0&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-ocean-at-the-end-of-the-lane&quot;&gt;The Ocean at the End of the Lane&lt;&#x2F;h3&gt;
&lt;p&gt;Desc: &lt;em&gt;(late 20th century - a man going for a funeral and remembering the events of the past. adaption of a Neil Gaiman novel)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This was an incredible piece of &lt;a href=&quot;https:&#x2F;&#x2F;www.nationaltheatre.org.uk&#x2F;productions&#x2F;the-ocean-at-the-end-of-the-lane&#x2F;&quot;&gt;theatre&lt;&#x2F;a&gt; &lt;em&gt;annnnnnnddddddd&lt;&#x2F;em&gt; we got another &lt;a href=&quot;https:&#x2F;&#x2F;open.spotify.com&#x2F;album&#x2F;7p6TvPsvX6Xzab9KNPFaEz?si=myTtMbDOT9WFTMv5-4t8qw&quot;&gt;&lt;em&gt;banging&lt;&#x2F;em&gt; soundtrack&lt;&#x2F;a&gt; which has also remained on my playlist. The actors all were incredible at their roles (although the actors might have changed by now - I saw it in 2022) and the technical effects were top-notch. It also really made me feel something at the end, which I suppose lends credence to my acclaim of the story and actors’ skill.&lt;&#x2F;p&gt;
&lt;p&gt;I also really enjoyed &lt;a href=&quot;https:&#x2F;&#x2F;maguire.tech&#x2F;ramblings&#x2F;technical-theatre-experience&#x2F;#assistant-stage-manager-asm&quot;&gt;assistant stage managers&lt;&#x2F;a&gt; - they were really effectively utilised and incredibly skilful.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;harry-potter-the-cursed-child&quot;&gt;Harry Potter &amp;amp; The Cursed Child&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;em&gt;(modern - a Harry Potter story told a long time after the main series)&lt;&#x2F;em&gt; - I’m aware that the &lt;a href=&quot;https:&#x2F;&#x2F;www.vox.com&#x2F;culture&#x2F;23622610&#x2F;jk-rowling-transphobic-statements-timeline-history-controversy&quot;&gt;writer&lt;&#x2F;a&gt; isn’t the best, but there are better people to speak about that.&lt;&#x2F;p&gt;
&lt;p&gt;The story was really good and the pacing was phenomenal (which is a feat for a play this length - see the next paragraph). They also had some really interesting technical effects which I’ve not a clue how they were pulled off&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Somewhat famously, this is shown as 2 2.5hr plays with one interval in each mini-play and a larger interval between both of them. There’s Wednesday, Friday &amp;amp; Saturday showings that start the first at 14:00 and the second play at 19:00 and then a Sunday showing which is an hour earlier. I think you can also book individual parts, but check &lt;a href=&quot;https:&#x2F;&#x2F;uk.harrypottertheplay.com&#x2F;purchase-tickets&#x2F;#&#x2F;&quot;&gt;the website&lt;&#x2F;a&gt; for latest details. I’m glad I got to see the West End version, as I’ve heard that the Broadway version has some parts cut out to make it all fit into one showing. I loved the double-feature nature because I got to grab dinner in between and digest&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; what I’d seen so far with my family.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-play-that-goes-wrong&quot;&gt;The Play that Goes Wrong&lt;&#x2F;h3&gt;
&lt;p&gt;Desc: &lt;em&gt;(modern - a play that goes terribly terribly wrong whilst the actors attempt not to break character)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I went to &lt;a href=&quot;https:&#x2F;&#x2F;theduchesstheatre.co.uk&#x2F;tickets&#x2F;the-play-that-goes-wrong&#x2F;&quot;&gt;this one&lt;&#x2F;a&gt; with a friend in the summer and when I left my face hurt from the constant smiling. What happens is in the name, but I won’t spoil the degree to how far it goes. The actors all had perfect comedic timing and I also had the fortune of being a part of a really good audience.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;convent-garden-soho&quot;&gt;Convent Garden &amp;amp; Soho&lt;&#x2F;h2&gt;
&lt;p&gt;Convent Garden isn’t too far away from the West End and is really lovely. There’s a fair few nice cafes and ice cream parlours for your culinary enjoyment, or just to hang around in. There’s also the &lt;a href=&quot;https:&#x2F;&#x2F;www.ltmuseum.co.uk&#x2F;&quot;&gt;London Transport Museum&lt;&#x2F;a&gt; which I’ve always enjoyed.&lt;&#x2F;p&gt;
&lt;p&gt;Then not too far from there is Soho which is also lovely to walk around&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-10-1&quot;&gt;&lt;a href=&quot;#fn-10&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Whenever I’m around there, I’ll also always pop into &lt;a href=&quot;https:&#x2F;&#x2F;forbiddenplanet.com&#x2F;stores&#x2F;london-megastore&#x2F;&quot;&gt;Forbidden Planet&lt;&#x2F;a&gt; which is the only place I’ve found in London that has stock of all of the various Dungeons &amp;amp; Dragons books.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;south-kensington&quot;&gt;South Kensington&lt;&#x2F;h2&gt;
&lt;p&gt;South Kensington is also a lovely area of London which hosts some of the best museums in London (in my humble opinion). There’s also &lt;a href=&quot;https:&#x2F;&#x2F;www.allinlondon.co.uk&#x2F;regions&#x2F;south-kensington&#x2F;directory&#x2F;embassies-consulates&quot;&gt;lots of embassies&lt;&#x2F;a&gt; and some very expensive real estate.&lt;&#x2F;p&gt;
&lt;p&gt;All of London’s museums are incredible, and they’re mostly free to enter! I’d highly recommend visiting a few, and as with the theatres these are just the ones that have made a particular impact on me.&lt;&#x2F;p&gt;
&lt;p&gt;Also - for accessing the ones in South Kensington, you don’t even need to cross any roads! There’s an underground tunnel&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-20-1&quot;&gt;&lt;a href=&quot;#fn-20&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; which leads to an underground entrance to the V&amp;amp;A and comes up onto the street next to the Science and Natural History museums&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-25-1&quot;&gt;&lt;a href=&quot;#fn-25&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-science-museum&quot;&gt;The Science Museum&lt;&#x2F;h3&gt;
&lt;p&gt;I could pretty much describe the entire &lt;a href=&quot;https:&#x2F;&#x2F;www.sciencemuseum.org.uk&#x2F;&quot;&gt;museum&lt;&#x2F;a&gt; from top to bottom at this point and navigate mostly blindfolded. This museum is my home away from home&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-30-1&quot;&gt;&lt;a href=&quot;#fn-30&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; in Central London and I don’t think I’ll ever be able to truly give thanks to all the incredible curators&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-26-1&quot;&gt;&lt;a href=&quot;#fn-26&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;My usual route is as follows - I walk straight through the entrance (on the opposite side to the shop to avoid temptation) where they’ve got some huge steam engines. Then I’ll enjoy the space section that comes afterwards - I’ve over 150 hours in Kerbal Space Program&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-40-1&quot;&gt;&lt;a href=&quot;#fn-40&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, but I’ve never had anything that’s shown me how much rocket is needed to get such a small payload into orbit&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-50-1&quot;&gt;&lt;a href=&quot;#fn-50&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. I then always enjoy all the cars &amp;amp; trains, as well as the smaller pieces off to the side. There’s then the back section with the rotating exhibition but I can never stay too long there because I just feel super tired after a while. I then usually work my way up the exhibits at the back end - one about genetics and people on the second floor which is good, and then one at the 3rd floor about logistics? There isn’t really a concrete theme other than a large number of sofas and interactive games to play - I used to enjoy it, but now it feels a bit shallow.&lt;&#x2F;p&gt;
&lt;p&gt;After that, I’ll work my way back to the front of the museum - there used to be an area here with some climate science stuff (it might still be there, but the map says that it’s currently under refurbishment), but this then takes you to the back of the Flight exhibit. After that, I’ll go to the 360° simulator&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-60-1&quot;&gt;&lt;a href=&quot;#fn-60&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; if I feel like it. I’ll now go on a brief tangent to mourn the Launchpad.&lt;&#x2F;p&gt;
&lt;p&gt;Both of my parents used to work full-time (leave the house at 7:15 and get home at 11 on a good day full-time) - because of this they hired a nanny to look after us in the day and deal with things like the school run and meals. During the holidays, we spent most of the time at museums&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-70-1&quot;&gt;&lt;a href=&quot;#fn-70&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; wandering around which is part of the reason I’ve always known the Science Museum like the back of my hand. Out of the time in the Science Museum, my favourite part was always the Launchpad - my memories are a little foggy because it was so long ago but I remember running around and seeing all of the different parts for hours. However, in 2015 it went down for renovations to then be relaunched as the Wonderlab Gallery in 2016. I can see the effort that’s been put in, but it gets a no from me for the following reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It’s paid! The old gallery was free to enter but this new&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-80-1&quot;&gt;&lt;a href=&quot;#fn-80&quot;&gt;13&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; one is paid entry for £9 (in fairness, they do also offer a year pass for £14). I get why it’s now paid but wasn’t before - they run lots of shows and the employees do most definitely need to be paid&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-90-1&quot;&gt;&lt;a href=&quot;#fn-90&quot;&gt;14&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; but it still annoys me that something that was once free is no longer such.&lt;&#x2F;li&gt;
&lt;li&gt;The shows vary in quality - I adore the one that is around something that could be likened to a bar, but the other two aren’t as good.&lt;&#x2F;li&gt;
&lt;li&gt;The activities are much smaller in scale - in the old launchpad there was a pretty big variety in activities sizes, with a few that could be explored for a good while without getting boring. The new ones are much smaller and less interesting.
However, there’s one factor that probably trumps all of the others:&lt;&#x2F;li&gt;
&lt;li&gt;I’m old now, and my desire to go back to the launchpad probably partially reflects a desire to go back to when I could spend all week in museums without any worries for exams or homework or other things. I’ve also grown up a bit and exhibits that once would’ve amazed me don’t quite do it the same any more because I understand why these things happen.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;After mourning the launchpad, I’ll head downstairs to the second level and wander through the &lt;code&gt;Information Age&lt;&#x2F;code&gt;. Usually after that I’m pretty happy and so I’ll head out, possibly stopping by the gift shop even if I almost never actually buy anything.&lt;&#x2F;p&gt;
&lt;p&gt;Overall - would highly highly highly recommend.&lt;&#x2F;p&gt;
&lt;p&gt;

&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;enema.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;This was a contraption I saw in the medical gallery for giving a tobacco enema. I wonder what our equivalent will be for future generations?&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;engine.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;I&amp;#x27;m pretty pleased with the bokeh I managed to get on this turbojet from the flight gallery.&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;plane1.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;This was also from the Flight gallery.&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;protein.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;Downstairs, I saw this protein model which was *insane*. I don&amp;#x27;t even want to think about how long it must have taken to build.&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-natural-history-museum&quot;&gt;The Natural History Museum&lt;&#x2F;h3&gt;
&lt;p&gt;Fortunately for the reading time, I don’t have quite as long a spiel on the &lt;a href=&quot;https:&#x2F;&#x2F;www.nhm.ac.uk&#x2F;&quot;&gt;NHM&lt;&#x2F;a&gt; as I do on the Science Museum.&lt;&#x2F;p&gt;
&lt;p&gt;The NHM appears much more prominently in popular media than the Science Museum, so if you’ve heard of one of them then it’s probably this one. The most recent depiction I can recall was probably in the Paddington films. They also advertise a fair bit more&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-100-1&quot;&gt;&lt;a href=&quot;#fn-100&quot;&gt;15&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;They tend to spend much more time on life sciences and history - there’s galleries filled wall to wall with specimens of various animals and insects. The main exhibits I can recall are those on dinosaurs, photography and one about the human body and genetics which is far better than the equivalent in the Science Museum.&lt;&#x2F;p&gt;
&lt;p&gt;The NHM also seems to have much more of a focus on research and preservation than the Science Museum but I can’t really speak to that because I’m not a postgrad.&lt;&#x2F;p&gt;
&lt;p&gt;They also run an ice rink in December, but I can’t speak for the quality of the ice because I’ve never been to use it.&lt;&#x2F;p&gt;
&lt;p&gt;

&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;nhm_ext.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;I&amp;#x27;m pretty happy with this shot I got of the exterior.&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;gem1.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;This a nightmare to focus onto (and is still blurry 😓), and I found it in the Treasures of the Earth gallery.&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;imperial-college-london&quot;&gt;Imperial College London&lt;&#x2F;h3&gt;
&lt;p&gt;But Jack, that’s not a museum, that’s a university! Most of the time you’d be 100% correct, but every summer they run a &lt;a href=&quot;https:&#x2F;&#x2F;www.imperial.ac.uk&#x2F;events&#x2F;160698&#x2F;great-exhibition-road-festival-2023&#x2F;&quot;&gt;weekend festival&lt;&#x2F;a&gt; as a part of the &lt;a href=&quot;https:&#x2F;&#x2F;www.greatexhibitionroadfestival.co.uk&#x2F;about-us&#x2F;about-festival&#x2F;&quot;&gt;Exhibition Road festival&lt;&#x2F;a&gt;. There’s all kind of stations you can visit, talks you can watch and it gives a similar vibe to something like New Scientist Live with less people trying to sell you stuff. There’s also food everywhere which has been pretty good when I’ve gone.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;victoria-albert&quot;&gt;Victoria &amp;amp; Albert&lt;&#x2F;h3&gt;
&lt;p&gt;This is the only arts &amp;amp; history museum on Exhibition Road - I haven’t spent nearly as much time there as in the other two, but whenever I’ve been in, I’ve wanted to spend more time there&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-105-1&quot;&gt;&lt;a href=&quot;#fn-105&quot;&gt;16&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;knightsbridge&quot;&gt;Knightsbridge&lt;&#x2F;h2&gt;
&lt;p&gt;Knightsbridge is &lt;em&gt;&lt;strong&gt;posh&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;, which means that there’s an abundance of fancy shops if you’re feeling like seeing how the other side lives, and nice coffee shops for when you’re done.&lt;&#x2F;p&gt;
&lt;p&gt;I’d especially recommend having a look through Harrods - there’s so much insane stuff in there that it’s fun just to wonder through and play guess-the-price with a friend. The food court (and the rest of the food) all looks incredible but I’ve never actually eaten any due to prices that I haven’t ever seen surpassed. If I recall correctly, on my last visit I saw a £17 croissant and a £32 carbonara. &lt;em&gt;insane&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There’s also a huge variety of different shops inside - parts feel more like a retail outlet&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-110-1&quot;&gt;&lt;a href=&quot;#fn-110&quot;&gt;17&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; with a labyrinth containing shops from the different brands and parts are the Harrods own-brand stuff. The latter is always funniest to me - there’s time-share and full purchase opportunities for waterside villas on beaches thousands of miles away from here, and the tech section never fails to impress. The idea of a wealthy Harrods customer has always made me giggle - pop in in the morning to grab a new coat that costs more than the median person in the UK makes in a month, stay for lunch with no natural light paying more than a properly fancy night out, and then finishing the day considering entire houses in the Bahamas.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;riverside&quot;&gt;Riverside&lt;&#x2F;h2&gt;
&lt;p&gt;Whilst, technically I think Riverside refers to a &lt;a href=&quot;https:&#x2F;&#x2F;riversidequarter.com&#x2F;&quot;&gt;specific place&lt;&#x2F;a&gt;, I’m using this to chat about all the lovely bits on the river.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-tate-modern&quot;&gt;The Tate Modern&lt;&#x2F;h3&gt;
&lt;p&gt;You couldn’t have possibly thought that we were done with museums? The Tate Modern is a lovely space with lots of modern art all housed inside a beautiful building. Before the renovations at Battersea Power Station, this was also pretty unique in that it was built in an old power station - that’s why the two halves are called Turbine Halls A &amp;amp; B.&lt;&#x2F;p&gt;
&lt;p&gt;Whenever I walk past, I always have think about the nearby residents - if you go to the top floor then there’s a balcony looking away from the river directly (about 10-20m away) into some nearby apartments. The residents got annoyed at people looking at them from the gallery and brought a &lt;a href=&quot;https:&#x2F;&#x2F;www.theguardian.com&#x2F;artanddesign&#x2F;2019&#x2F;feb&#x2F;12&#x2F;tate-modern-wins-privacy-case-brought-by-owners-of-4m-flats&quot;&gt;suit&lt;&#x2F;a&gt; against Tate Modern and lost whereafter the judge told them to install blinds.&lt;&#x2F;p&gt;
&lt;p&gt;I don’t even think I’ve ever paid to enter one of the galleries there as there’s tons of free stuff to go see. You can also easily get to it from Waterloo station via Wobbly bridge.&lt;&#x2F;p&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;tate.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;I managed to get this from the opposite side of the river - the contrast between the Tate Modern &amp;amp; The Globe is pretty funny.&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;&lt;h3 id=&quot;wobbly-bridge&quot;&gt;Wobbly Bridge&lt;&#x2F;h3&gt;
&lt;p&gt;Wobbly bridge (technically called The Millennium Bridge) is a pretty sick bridge which is worth walking over - the views are great, there aren’t any cars and there’s some nice photo ops. If you do end up walking over it, I’d make sure to look at the floor for a bit - sounds weird but check all of the gum. There’s some dude who doodles all over it, which I’ve never seen anywhere else.&lt;&#x2F;p&gt;
&lt;p&gt;

&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;gum1.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;See Exhibit A.&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;gum2.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;And Exhibit B.&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;paul.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;You can also get a photo of a lovely sightline to St Pauls.&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;southbank&quot;&gt;Southbank&lt;&#x2F;h3&gt;
&lt;p&gt;The Southbank is always really lovely - there’s food, a skate park, the national theatre&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-120-1&quot;&gt;&lt;a href=&quot;#fn-120&quot;&gt;18&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; &lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-125-1&quot;&gt;&lt;a href=&quot;#fn-125&quot;&gt;19&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; and some incredible views. You’ve also got the London Eye and 3 pretty decent attractions nearby - see below.&lt;&#x2F;p&gt;
&lt;p&gt;There’s also lots of food vendors (especially around the holidays) and a lovely park with a playground.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sea-life-aquarium-shrek-s-adventure-the-london-dungeon&quot;&gt;Sea Life Aquarium, Shrek’s Adventure &amp;amp; The London Dungeon&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;The first I can wholeheartedly recommend - many fond memories and some of the displays are incredible.&lt;&#x2F;li&gt;
&lt;li&gt;The second I remember as being pretty decent, but beware of the expected audience - more suited for 7-8 year olds than 18 year olds.&lt;&#x2F;li&gt;
&lt;li&gt;The third I can recommend against - the humour is all pretty juvenile but not in a funny way? The pacing was also pretty slow and from what I’ve heard the original incarnation on Tooley St was better.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;tower-bridge-parliament-big-ben&quot;&gt;Tower Bridge, Parliament &amp;amp; Big Ben&lt;&#x2F;h3&gt;
&lt;p&gt;Tower Bridge is also definitely worth seeing - there can be queues, but the view is really good and the glass part is always fun to walk over. For some fun London knowledge, there was once an American who adored Tower Bridge so much that they wanted to buy it and move it to the US. They &lt;a href=&quot;https:&#x2F;&#x2F;www.onthisday.com&#x2F;articles&#x2F;why-an-american-bought-london-bridge&quot;&gt;accidentally bought London Bridge&lt;&#x2F;a&gt; which is still lovely, but not quite the same - make sure not to make the same mistake and visit the wrong one!&lt;&#x2F;p&gt;
&lt;p&gt;Parliament &amp;amp; Big Ben are also worth visiting, but there might be some shenanigans around photo ID and booking far in advance, so if you’re interested I’d make sure to look at &lt;a href=&quot;https:&#x2F;&#x2F;www.parliament.uk&#x2F;visiting&#x2F;visiting-and-tours&#x2F;big-ben-tour&#x2F;&quot;&gt;their&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.parliament.uk&#x2F;visiting&#x2F;visiting-and-tours&#x2F;&quot;&gt;websites&lt;&#x2F;a&gt;. I’ve also got another fun fact - Big Ben is technically only the actual bell, and when most people talk about Big Ben they actually mean Elizabeth Tower.&lt;&#x2F;p&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;tower.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;It&amp;#x27;s even better in person when the bridge lifts up - if you&amp;#x27;re ever trying to time it, check here: &amp;lt;https:&amp;#x2F;&amp;#x2F;www.towerbridge.org.uk&amp;#x2F;lift-times&amp;gt;&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;&lt;h3 id=&quot;tower-of-london-hampton-court-other-crown-properties&quot;&gt;Tower of London (&amp;amp; Hampton Court &amp;amp; other crown properties)&lt;&#x2F;h3&gt;
&lt;p&gt;From what I can remember both are similar, but the Tower of London has more of a focus on crown jewels and execution but Hampton Court has more of a focus on the daily life of the royals. Both are very interesting and lovely to go to on a hot day - in my experience Hampton Court is always a bit more relaxed because it’s more out of the way and also has more outside green spaces to relax in. I’ve spent many a summer’s day here with picnics and friends and I’ve never regretted it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;battersea-power-station&quot;&gt;Battersea Power Station&lt;&#x2F;h3&gt;
&lt;p&gt;Battersea Power Station finished renovations &lt;a href=&quot;https:&#x2F;&#x2F;batterseapowerstation.co.uk&#x2F;news&#x2F;battersea-power-station-opening-date-announcement&#x2F;&quot;&gt;relatively recently&lt;&#x2F;a&gt;, and it’s pretty nice over there. There’s a ton of restaurants, plenty of options for retail therapy &amp;amp; lots of apartments. There’s also a tube station so it’s relatively easy to get to.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;oxo-tower&quot;&gt;Oxo Tower&lt;&#x2F;h3&gt;
&lt;p&gt;Oxo Tower was originally created as a power station, and was then later purchased by the manufacturers of Oxo stock cubes and is now owned by a non-profit. Fun fact - when the OXO letters were put into place on the tower, there was &lt;a href=&quot;https:&#x2F;&#x2F;www.artofthestate.co.uk&#x2F;archive&#x2F;london_photos-2&#x2F;oxo_tower&#x2F;&quot;&gt;legal faffery&lt;&#x2F;a&gt; around whether or not it qualified as an advertisement. The owners claimed that it was simply a geometric pattern with a cross between 2 circles and they won. Obviously, advertising legislation has changed a bit since then.&lt;&#x2F;p&gt;
&lt;p&gt;I don’t have any experience with the gallery or the restaurant, but I love visiting all of the small independent shops below. My favourite is &lt;a href=&quot;https:&#x2F;&#x2F;www.suck.uk.com&#x2F;&quot;&gt;suck uk&lt;&#x2F;a&gt; which sell a variety of unique gifts that rotate around regularly. They’re all designed in-house and all incredible.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-city-of-london&quot;&gt;The City of London&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve had the good fortune of visiting many cities around the world, but I’ve never been around a central business district that gives the same vibes as the city of London. I personally blame it on the fact that most of my more recent visits have been to the US, where the cities are &lt;em&gt;very&lt;&#x2F;em&gt; planned&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-130-1&quot;&gt;&lt;a href=&quot;#fn-130&quot;&gt;20&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. In contrast, the city of London has such a mish-mash of architectural styles and layouts, such that you never really know where you’re going along the right route unless you look up at landmarks, especially unlike New York or Washington DC which are strictly gridded.&lt;&#x2F;p&gt;
&lt;p&gt;The history of the City of London is also especially interesting, but I’d probably just butcher the explanation. If you’re interested, I’d highly recommend &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=LrObZ_HZZUc&quot;&gt;this video&lt;&#x2F;a&gt; by CGP Grey.&lt;&#x2F;p&gt;
&lt;p&gt;For the purposes of this section though, I’ll mainly just be talking about Central London without truly making a distinction.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-shard-london-eye&quot;&gt;The Shard &amp;amp; London Eye&lt;&#x2F;h3&gt;
&lt;p&gt;I only visited the Shard for the first time a few weeks ago, and the view was one of the best I’ve ever seen&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-140-1&quot;&gt;&lt;a href=&quot;#fn-140&quot;&gt;21&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; and I’d highly recommend heading up to catch the view. If you aren’t as bothered about being the highest or having food&#x2F;drinks, I’d head up the London Eye instead. Both are very near to public transport terminals (London Bridge &amp;amp; Waterloo) respectively. You can get tickets there and then for both, but I’d make sure to book in advance because they run on time slots and are also cheaper online.&lt;&#x2F;p&gt;
&lt;p&gt;

&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;shard.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;Here&amp;#x27;s one photo of the shard.&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;shard2.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;And another taken pretty far away from the first - it&amp;#x27;s such a huge monument that I had fun taking pictures of it on my walk today at huge intervals and seeing how it became harder and harder to fit in frame on my 50mm lens.&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;skygarden&quot;&gt;Skygarden&lt;&#x2F;h3&gt;
&lt;p&gt;Skygarden is a garden at the top of the Walkie Talkie&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-150-1&quot;&gt;&lt;a href=&quot;#fn-150&quot;&gt;22&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, to which you can obtain free tickets and vibe. There’s a cafe and lovely views - would recommend.&lt;&#x2F;p&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;london&amp;#x2F;walkie.jpg&quot;&#x2F;&gt;
    &lt;figcaption&gt;You can just about make out the skygarden at the top here, and you can also tell why we call it the Walkie Talkie. You can&amp;#x27;t see it from this angle, but it&amp;#x27;s just next to the cheese grater (AKA 122 Leadenhall Street).&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing Thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;By no means is this a complete list of London Attractions, only the ones that have especially stuck with me - as a resident I don’t go to the attractions all that often. I’ll also probably add more things as I do more things and remember old things. I’ll also try and add some photos, because this article&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-155-1&quot;&gt;&lt;a href=&quot;#fn-155&quot;&gt;23&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; is currently &lt;em&gt;severely&lt;&#x2F;em&gt; lacking in that area.&lt;&#x2F;p&gt;
&lt;p&gt;This was written during a fairly stressful period regarding my personal future and where I’d be going come September and it’s been really lovely to reminisce. I adore this city and have found no parallel yet - maybe it truly is the best for me, or maybe I have to visit more places and stay there longer and I want to do that. I’ve lived here for all my life, but I want to truly get to know somewhere else - part of the reason that I haven’t applied to any London universities&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-160-1&quot;&gt;&lt;a href=&quot;#fn-160&quot;&gt;24&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I truly look forward to the day I can write a similar post to this about somewhere else, or the day that I know that I’ve seen enough and am happy to move back home - I guess we’ll all have to wait and see ;)&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-0&quot;&gt;
&lt;p&gt;For reference, I think I saw Six single-digit days before the UK went into the first Covid-19 related lockdown which would be March 2020. &lt;a href=&quot;#fr-0-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Which is pretty rare for me, because a) most shows don’t go that insane with tech and b) I’ve just a little bit of experience with &lt;a href=&quot;https:&#x2F;&#x2F;maguire.tech&#x2F;ramblings&#x2F;technical-theatre-experience&#x2F;&quot;&gt;tech&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;&lt;em&gt;heh heh&lt;&#x2F;em&gt; &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-10&quot;&gt;
&lt;p&gt;Although maybe not with small children or nuns. &lt;a href=&quot;#fr-10-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-20&quot;&gt;
&lt;p&gt;Called, confusingly, the Subway. &lt;a href=&quot;#fr-20-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-25&quot;&gt;
&lt;p&gt;And also to Imperial College - I presume that it’s incredibly useful for the students to avoid rain. &lt;a href=&quot;#fr-25-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-30&quot;&gt;
&lt;p&gt;A STEM student, loving the science museum? Scandalous! &lt;a href=&quot;#fr-30-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-26&quot;&gt;
&lt;p&gt;I can’t lie - if I ever &lt;em&gt;make it make it&lt;&#x2F;em&gt; then the Science Museum is relatively high on the list of places to help out. &lt;a href=&quot;#fr-26-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-40&quot;&gt;
&lt;p&gt;tracked - in reality I probably have &amp;gt; 300-400 hours because it took too long to launch Steam (yes, my rockets were limited in size by frame-rate to not much beyond a Duna return w&#x2F; Science lab on board) on my old laptop so I just bookmarked the executable on the desktop. &lt;a href=&quot;#fr-40-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-50&quot;&gt;
&lt;p&gt;I have had the good fortune to visit both the &lt;a href=&quot;https:&#x2F;&#x2F;www.nasa.gov&#x2F;kennedy&#x2F;&quot;&gt;Kennedy&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.nasa.gov&#x2F;marshall&#x2F;&quot;&gt;Marshall&lt;&#x2F;a&gt; Space Centres, which have plenty of rockets but they go beyond the scale of my comprehension of vehicles into the realm of buildings. They were also all pointed vertically which made it harder. Yes, I also also know that there’s a horizontal Saturn in Marshall (which I’ve seen), but that carried a moon mission. &lt;a href=&quot;#fr-50-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-60&quot;&gt;
&lt;p&gt;I don’t get motion sickness, like at all. I’ve not a clue why because I’ve got decent balance (not sure if they’re linked but I think they’re both inner-ear related - do I have the audience to nerdsnipe a biologist?). This usually doesn’t affect that much, but comes in very handy for VR games and doing non-stop barrel rolls and loops in this simulator. Also - you know how people often don’t realise that they’re unique in minor ways until the situation directly confronts them? I managed to work out that my lack of motion sickness is unusual in this very spot, after I went in with my dad and managed to wipe him out for the rest of the day 😔. &lt;a href=&quot;#fr-60-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-70&quot;&gt;
&lt;p&gt;Especially the Exhibition Road ones, especially especially the Science Museum. &lt;a href=&quot;#fr-70-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-80&quot;&gt;
&lt;p&gt;why am I old now? how is 2016 new? &lt;a href=&quot;#fr-80-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-90&quot;&gt;
&lt;p&gt;Especially in London 😭 &lt;a href=&quot;#fr-90-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-100&quot;&gt;
&lt;p&gt;I’ve never seen actual targeted advertisements for either, but I’ve at least seen more &lt;a href=&quot;https:&#x2F;&#x2F;maguire.tech&#x2F;ramblings&#x2F;tfl-for-dummies&#x2F;#tube&quot;&gt;tube&lt;&#x2F;a&gt; ads for the NHM. &lt;a href=&quot;#fr-100-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-105&quot;&gt;
&lt;p&gt;even if I just end up going to the Science Museum again next time 😔 &lt;a href=&quot;#fr-105-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-110&quot;&gt;
&lt;p&gt;Except it’s not an outlet, it’s full price. &lt;a href=&quot;#fr-110-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-120&quot;&gt;
&lt;p&gt;Which, for reference, is one of the buildings that I think really &lt;em&gt;gets&lt;&#x2F;em&gt; brutalism right. See an example photo &lt;a href=&quot;http:&#x2F;&#x2F;civilianglobal.com&#x2F;wp-content&#x2F;uploads&#x2F;2016&#x2F;12&#x2F;National-Theatre-from-the-northeast-Photo-by-Philip-Vile.jpg&quot;&gt;here&lt;&#x2F;a&gt;. &lt;a href=&quot;#fr-120-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-125&quot;&gt;
&lt;p&gt;They do a variety of performances here, rotating every so often. They tend to be more &lt;em&gt;theatre&lt;&#x2F;em&gt;-y than most of the West End, which is why you might hear people talking about going to the National Theatre but you’d rarely hear people talking about going to, say the Criterion (no slight against them, just the first to pop into my head). &lt;a href=&quot;#fr-125-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-130&quot;&gt;
&lt;p&gt;Yes, I know there are actual &lt;code&gt;Planned Cities&lt;&#x2F;code&gt;. However, London is &lt;em&gt;insanely&lt;&#x2F;em&gt; old. For example, by the time New Amsterdam (the old name for New York) had around 2000 people, London had been around for about 1600 years (counting Roman &lt;code&gt;Londinium&lt;&#x2F;code&gt; as the start). &lt;a href=&quot;#fr-130-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-140&quot;&gt;
&lt;p&gt;even if we had really bad weather 😢 &lt;a href=&quot;#fr-140-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-150&quot;&gt;
&lt;p&gt;AKA &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;hlRNO8xcrgU?si=dh9Zx8d1_5JvPg06&quot;&gt;Walkie&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;c7VEu4ZHSUU?si=KuBGVl4dc9sLZxd3&quot;&gt;Scorchy&lt;&#x2F;a&gt; AKA 20 Fenchurch Street. &lt;a href=&quot;#fr-150-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-155&quot;&gt;
&lt;p&gt;And blog as a whole - call it my new years resolution to improve on that :) &lt;a href=&quot;#fr-155-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-160&quot;&gt;
&lt;p&gt;That, and London looks like an &lt;em&gt;awful&lt;&#x2F;em&gt; place to be a student in a myriad of ways (spread out accommodation, accommodation far away from campuses, small campuses, and the fact that London is more designed for people earning an insane amount of money which doesn’t include many students.) &lt;a href=&quot;#fr-160-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>Building 2 &#x27;Simple&#x27; Allocators</title>
          <pubDate>Sat, 13 Jan 2024 00:00:00 +0000</pubDate>
          <author>Jack Maguire</author>
          <link>https://maguire.tech/posts/allocators/</link>
          <guid>https://maguire.tech/posts/allocators/</guid>
          <description xml:base="https://maguire.tech/posts/allocators/">&lt;p&gt;I’ve always wondered how allocators work, so over the last week I’ve been working on this.&lt;&#x2F;p&gt;
&lt;p&gt;NB: This is a pretty true-to-life recreation of my journey, so there are twists, turns and unexpected last-minute betrayals but I hope that showing my process of fixing stuff helps more than if I’d just cleaned up the whole article to make it look like I’d got everything perfect on the first try.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-do-i-even-start&quot;&gt;Where do I even start?&lt;&#x2F;h2&gt;
&lt;p&gt;All &lt;code&gt;Rust&lt;&#x2F;code&gt; allocators must start with the trait &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;alloc&#x2F;trait.GlobalAlloc.html&quot;&gt;&lt;code&gt;std::alloc::GlobalAlloc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub unsafe trait &lt;&#x2F;span&gt;&lt;span&gt;GlobalAlloc {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Required methods
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;dealloc&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ptr&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are two methods that must be provided - one to allocate memory and one to deallocate it. Unlike some other languages, the Rust allocator takes in an alignment and a length for the allocation &lt;em&gt;and&lt;&#x2F;em&gt; the deallocation. Fun fact - it’s also UB to use a memory allocation with one alignment for a purpose with another alignment (like you might if you were, say, trying to &lt;a href=&quot;https:&#x2F;&#x2F;maguire.tech&#x2F;posts&#x2F;binary-serialisation&#x2F;#ub&quot;&gt;reinterpret a vector’s contents as a non byte aligned struct&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Then, once you’ve got an allocator, there are unstable methods to use it piecemeal (like &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;boxed&#x2F;struct.Box.html#method.new_in&quot;&gt;&lt;code&gt;Box::new_in&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for example), but these aren’t stable so I won’t really be looking at them here. Instead, we’ll be trying to build an allocator that gets used globally for our whole program. To do that, you have to do something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Allocator {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* contents *&#x2F; &lt;&#x2F;span&gt;&lt;span&gt;}; 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;global_allocator&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;static &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ALLOCATOR&lt;&#x2F;span&gt;&lt;span&gt;: Allocator = Allocator {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* contents *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Interestingly enough, &lt;code&gt;GlobalAlloc&lt;&#x2F;code&gt; is one of a few unsafe traits, which means that there are extra invariants you must follow. For &lt;code&gt;GlobalAlloc&lt;&#x2F;code&gt;, you must ensure the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Allocation and Deallocation cannot panic.&lt;&#x2F;li&gt;
&lt;li&gt;You must completely follow the &lt;code&gt;Layout&lt;&#x2F;code&gt;s.&lt;&#x2F;li&gt;
&lt;li&gt;You must not rely on allocations not being optimised away.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;something-simple-to-start&quot;&gt;Something simple to start?&lt;&#x2F;h2&gt;
&lt;p&gt;How about we start with just making an &lt;em&gt;‘allocator’&lt;&#x2F;em&gt; that just serves 4 byte alignment and size sections of memory. Why - so I can test it easily and make sure it actually works using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&quot;&gt;&lt;code&gt;miri&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Then, I can slowly expand the functionality and improve it whilst keeping it correct.&lt;&#x2F;p&gt;
&lt;p&gt;My first best guess for an allocator would just be to pretend to be the heap, and use the stack 😉. I’ve taken some inspiration on that front from the example arena allocator from the &lt;code&gt;GlobalAlloc&lt;&#x2F;code&gt; docs.&lt;&#x2F;p&gt;
&lt;p&gt;We’ll start here:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::sync::atomic::AtomicBool;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::cell::UnsafeCell;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::alloc::{GlobalAlloc, Layout};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;FourAllocator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;is_allocating&lt;&#x2F;span&gt;&lt;span&gt;: AtomicBool,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tracker&lt;&#x2F;span&gt;&lt;span&gt;: UnsafeCell&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;spaces&lt;&#x2F;span&gt;&lt;span&gt;: UnsafeCell&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;BITS as usize &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe impl &lt;&#x2F;span&gt;&lt;span&gt;Sync &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;FourAllocator {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe impl &lt;&#x2F;span&gt;&lt;span&gt;GlobalAlloc &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;FourAllocator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        todo!()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;dealloc &lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ptr&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout) {
&lt;&#x2F;span&gt;&lt;span&gt;        todo!()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;global_allocator&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;static &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ALLOCATOR&lt;&#x2F;span&gt;&lt;span&gt;: FourAllocator = FourAllocator {
&lt;&#x2F;span&gt;&lt;span&gt;    tracker: UnsafeCell::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    is_allocating: AtomicBool::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    spaces: UnsafeCell::new([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;BITS &lt;&#x2F;span&gt;&lt;span&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main &lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; test_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ALLOCATOR&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;(Layout::new::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;()) };
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We first define our allocator struct, consisting of an atomic boolean to act as a lock (I’ll come back to this), then a &lt;code&gt;tracker&lt;&#x2F;code&gt; (I’ll also come back to this later), and then an array of spaces held inside an &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;cell&#x2F;struct.UnsafeCell.html&quot;&gt;&lt;code&gt;UnsafeCell&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. &lt;code&gt;UnsafeCell&lt;&#x2F;code&gt; grants us the magical power of interior mutability - the ability to mutate something without needing &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt;. You’ve probably used this before, but it would’ve been shielded by something like &lt;code&gt;Mutex&lt;&#x2F;code&gt;. Here, we’re using it by itself to handle our &lt;em&gt;‘allocations’&lt;&#x2F;em&gt;. The difference here is that you just get a &lt;code&gt;*mut T&lt;&#x2F;code&gt;, and you are responsible for ensuring that it doesn’t get concurrently read or wrote to in different threads. That’s why we’ve got a lock.&lt;&#x2F;p&gt;
&lt;p&gt;Then &lt;code&gt;Sync&lt;&#x2F;code&gt; is the marker trait for allowing things to be shared between threads, and it is &lt;code&gt;unsafe&lt;&#x2F;code&gt; to implement because it can break lots of external guarantees. We’re safe here though because we ensure that the same spaces aren’t accessed concurrently and mutably in different threads. &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nomicon&#x2F;send-and-sync.html&quot;&gt;More info on &lt;code&gt;Send&lt;&#x2F;code&gt; and &lt;code&gt;Sync&lt;&#x2F;code&gt; can be found here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We then create our allocator using &lt;code&gt;#[global_allocator]&lt;&#x2F;code&gt;, and create an &lt;code&gt;i32&lt;&#x2F;code&gt; on the Heap using &lt;code&gt;Box&lt;&#x2F;code&gt;. Anyone want to guess what happens if we run the program? We stack overflow as the allocator repeatedly calls itself when it allocates a string to print for the &lt;code&gt;todo!&lt;&#x2F;code&gt;. This would seem bad, but it confirms that we are indeed using the custom allocator. This limitation of not being able to allocate when allocating can make things difficult later, but I’ve got some plans cooking to help with that.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;maybe-not-so-simple&quot;&gt;Maybe not so simple?&lt;&#x2F;h3&gt;
&lt;p&gt;The first step should be actually checking for our 4 size and alignment, which can be done with a quick &lt;code&gt;if&lt;&#x2F;code&gt;, returning a null pointer if not - which is the expected behaviour for out-of-memory and other errors in the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;alloc&#x2F;trait.GlobalAlloc.html#tymethod.alloc&quot;&gt;docs&lt;&#x2F;a&gt;. If we keep our &lt;code&gt;todo!()&lt;&#x2F;code&gt; underneath for now, but take it out from &lt;code&gt;dealloc&lt;&#x2F;code&gt;, then we can also test this!&lt;&#x2F;p&gt;
&lt;p&gt;If we try to allocate something with the correct size and alignment, we should see a stack overflow (as it reaches the &lt;code&gt;todo!()&lt;&#x2F;code&gt;), and if not then nothing should happen:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;Allocator:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe impl &lt;&#x2F;span&gt;&lt;span&gt;GlobalAlloc &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;FourAllocator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;() != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4 &lt;&#x2F;span&gt;&lt;span&gt;|| layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;align&lt;&#x2F;span&gt;&lt;span&gt;() != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;std::ptr::null_mut();
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        todo!()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;dealloc &lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ptr&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout) {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;Main:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main &lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;run 1:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; layout = Layout::new::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;u32 has layout 4, 4
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;run 2:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; layout = Layout::new::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;u8 has layout 1, 1
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ std::alloc::alloc(layout) };
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And we then run it?&lt;&#x2F;p&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo r --quiet
&lt;&#x2F;span&gt;&lt;span&gt;memory allocation of 10 bytes failed
&lt;&#x2F;span&gt;&lt;span&gt;error: process didn&amp;#39;t exit successfully: `target\debug\i32-allocator.exe` (exit code: 0xc0000409, STATUS_STACK_BUFFER_OVERRUN)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ # change to run two
&lt;&#x2F;span&gt;&lt;span&gt;$ cargo r --quiet
&lt;&#x2F;span&gt;&lt;span&gt;memory allocation of 10 bytes failed
&lt;&#x2F;span&gt;&lt;span&gt;error: process didn&amp;#39;t exit successfully: `target\debug\i32-allocator.exe` (exit code: 0xc0000409, STATUS_STACK_BUFFER_OVERRUN)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;h3 id=&quot;10-bytes&quot;&gt;10 bytes?&lt;&#x2F;h3&gt;
&lt;p&gt;Right, so something’s gone very wrong here - we only tried to allocate either 1 or 4 bytes, not 10. Ideally, the two runs should’ve also looked different.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;error: unsupported operation: can&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;t&lt;&#x2F;span&gt;&lt;span&gt; call (diverging) foreign function: __rust_alloc_error_handler
&lt;&#x2F;span&gt;&lt;span&gt;   --&amp;gt; C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\alloc.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;383&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13
&lt;&#x2F;span&gt;&lt;span&gt;    |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;383 &lt;&#x2F;span&gt;&lt;span&gt;|             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;__rust_alloc_error_handler&lt;&#x2F;span&gt;&lt;span&gt;(layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;(), layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;align&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;t&lt;&#x2F;span&gt;&lt;span&gt; call (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;diverging&lt;&#x2F;span&gt;&lt;span&gt;) foreign &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;: __rust_alloc_error_handler
&lt;&#x2F;span&gt;&lt;span&gt;    |
&lt;&#x2F;span&gt;&lt;span&gt;    = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
&lt;&#x2F;span&gt;&lt;span&gt;    = note: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;BACKTRACE&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::alloc::handle_alloc_error::rt_error` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\alloc.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;383&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;383&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;70
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::alloc::handle_alloc_error` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\alloc.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;389&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;9&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;389&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;75
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `alloc::raw_vec::RawVec::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;::allocate_in` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\raw_vec.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;204&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;27&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;204&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;53
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `alloc::raw_vec::RawVec::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;::with_capacity_in` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\raw_vec.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;145&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;9&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;145&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;69
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::vec::Vec::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;::with_capacity_in` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\vec\&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod&lt;&#x2F;span&gt;&lt;span&gt;.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;672&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;672&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;61
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::vec::Vec::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;::with_capacity` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\vec\&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod&lt;&#x2F;span&gt;&lt;span&gt;.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;481&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;9&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;481&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;49
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::sys::windows::to_u16s::inner` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sys\windows\&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod&lt;&#x2F;span&gt;&lt;span&gt;.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;186&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;32&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;186&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;63
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::sys::windows::to_u16s::&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sys\windows\&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod&lt;&#x2F;span&gt;&lt;span&gt;.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;198&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;198&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;22
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::sys::windows::thread::Thread::set_name` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sys\windows\thread.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;66&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;32&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;66&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;45
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::sys::windows::init` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sys\windows\&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod&lt;&#x2F;span&gt;&lt;span&gt;.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;66&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;66&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;39
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::rt::init` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\rt.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;97&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;9&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;97&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;39
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside closure at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\rt.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;147&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;147&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;67
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::panicking::r#try::do_call::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;closure@std::rt::lang_start_internal::{closure#&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;}}, ()&amp;gt;` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\panicking.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;552&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;40&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;552&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;43
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::panicking::r#try::&amp;lt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;closure@std::rt::lang_start_internal::{closure#&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;}}&amp;gt;` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\panicking.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;516&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;19&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;516&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;81
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::panic::catch_unwind::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;closure@std::rt::lang_start_internal::{closure#&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;}}, ()&amp;gt;` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\panic.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;142&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;14&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;142&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;33
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::rt::lang_start_internal` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\rt.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;147&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;147&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;70
&lt;&#x2F;span&gt;&lt;span&gt;    = note: inside `std::rt::lang_start::&amp;lt;()&amp;gt;` at C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\rt.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;165&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;17&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;170&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;6
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I can’t really make heads or tails of most of that, but if you skim around carefully, you can see lots of references to the rust runtime startup. That then explains our issues - something else is allocating. This also makes sense because the runtime startup probably allocates to do things like setting up the environment variables and command-line arguments in a nice place.&lt;&#x2F;p&gt;
&lt;p&gt;If this is happening, it might be easier to just allocate pointers as and when we need them, rather than trying to create a global allocator from the start. This’ll also let us do other useful things like allocating during our &lt;code&gt;alloc&lt;&#x2F;code&gt; function. For now though, we’ll keep using the skeleton of &lt;code&gt;GlobalAlloc&lt;&#x2F;code&gt;, if only for it being good practice.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;local-allocator&quot;&gt;Local Allocator&lt;&#x2F;h3&gt;
&lt;p&gt;We’ll start by commenting out &lt;code&gt;#[global_allocator]&lt;&#x2F;code&gt;. Then, we’ll replace &lt;code&gt;std::alloc::alloc&lt;&#x2F;code&gt; with &lt;code&gt;ALLOCATOR.alloc&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If we re-run our test from earlier (just to remind you - it should panic on unimplemented the first time, and not do anything on the second time):&lt;&#x2F;p&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo r --quiet
&lt;&#x2F;span&gt;&lt;span&gt;thread &amp;#39;main&amp;#39; panicked at src\main.rs:18:9:
&lt;&#x2F;span&gt;&lt;span&gt;not yet implemented
&lt;&#x2F;span&gt;&lt;span&gt;note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
&lt;&#x2F;span&gt;&lt;span&gt;error: process didn&amp;#39;t exit successfully: `target\debug\i32-allocator.exe` (exit code: 101)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ # change to run two
&lt;&#x2F;span&gt;&lt;span&gt;$ cargo r --quiet
&lt;&#x2F;span&gt;&lt;span&gt;# program exits successfully!
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;Success!&lt;&#x2F;p&gt;
&lt;p&gt;The next step would be to actually store allocations. We need some way to track when a slot is allocated and when it isn’t, and that’s why we’ve got a &lt;code&gt;usize&lt;&#x2F;code&gt; tracker and are storing &lt;code&gt;usize::BITS * 4&lt;&#x2F;code&gt; &lt;code&gt;u8&lt;&#x2F;code&gt;s. We can use each bit in the &lt;code&gt;usize&lt;&#x2F;code&gt; to mark whether or not the relevant slot has been handed over yet.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;actually-storing-allocations&quot;&gt;Actually Storing Allocations?&lt;&#x2F;h3&gt;
&lt;p&gt;One of the invariants of &lt;code&gt;UnsafeCell&lt;&#x2F;code&gt; that we need to uphold is to ensure that it isn’t accessed mutably by more than one thread at a time. We also need to hold up our own invariant, which is that the &lt;code&gt;tracker&lt;&#x2F;code&gt; is always either accurate or overzealous. In the Rust where we’re allowed to allocate, the solution is clear cut and obvious - &lt;code&gt;Arc&amp;lt;Mutex&amp;lt;usize&amp;gt;&amp;gt;&lt;&#x2F;code&gt;, but that doesn’t hold here because that allocates :&#x2F; .&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-0-1&quot;&gt;&lt;a href=&quot;#fn-0&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Instead, we’ll have to use an &lt;code&gt;AtomicBool&lt;&#x2F;code&gt; for whether we’re ‘holding the lock’, and then an &lt;code&gt;UnsafeCell&lt;&#x2F;code&gt; to store the actual &lt;code&gt;usize&lt;&#x2F;code&gt;. Before you point out that we could just use an &lt;code&gt;AtomicUsize&lt;&#x2F;code&gt;, we need to iterate through the &lt;code&gt;usize&lt;&#x2F;code&gt; a lot to find a space and I’m not sure how to ensure that an &lt;code&gt;AtomicUsize&lt;&#x2F;code&gt; doesn’t get accessed for a portion of time. Because of that, we need to emulate a &lt;code&gt;Mutex&lt;&#x2F;code&gt; and luckily, &lt;code&gt;AtomicBool&lt;&#x2F;code&gt; has a method called &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;core&#x2F;sync&#x2F;atomic&#x2F;struct.AtomicBool.html#method.compare_exchange&quot;&gt;&lt;code&gt;compare_exchange&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; where we can use &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;atomic&#x2F;enum.Ordering.html#variant.SeqCst&quot;&gt;&lt;code&gt;Ordering::SeqCst&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to keep it all thread-safe and ensure that only one thread will not be waiting at any time. &lt;code&gt;compare_exchange&lt;&#x2F;code&gt; takes two arguments at the start - a &lt;code&gt;current&lt;&#x2F;code&gt; variable and a &lt;code&gt;target&lt;&#x2F;code&gt; variable. It’ll only switch the &lt;code&gt;AtomicBool&lt;&#x2F;code&gt; to be the &lt;code&gt;target&lt;&#x2F;code&gt;, if it is currently the &lt;code&gt;current&lt;&#x2F;code&gt;. Using that, we can then set it to only set it to be allocating when it isn’t already allocating. The other two arguments are about ordering - the first is for what ordering to use when comparing and setting on success, and the second is for how to load &lt;code&gt;current&lt;&#x2F;code&gt; on failure. Here, I’ll just use &lt;code&gt;SeqCst&lt;&#x2F;code&gt; because I’m never 100% sure on Atomic Orderings, and I know this one will work.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.is_allocating.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;compare_exchange&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;, SeqCst, SeqCst).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_err&lt;&#x2F;span&gt;&lt;span&gt;() {std::thread::yield_now()}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since it returns &lt;code&gt;Result::Err&lt;&#x2F;code&gt; whenever it fails to store the new value, we can just wait for it to not do that. To give a small performance boost, we can also tell it to &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;thread&#x2F;fn.yield_now.html&quot;&gt;&lt;code&gt;yield_now&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which just tells the CPU scheduler to go to another thread. This makes sense because we can’t do anything until we’ve allocated so we may as well go elsewhere.&lt;&#x2F;p&gt;
&lt;p&gt;Then, we can get the pointer to our tracker, and copy it to the stack for convenience:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; tracker_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tracker.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(); 
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; tracker_copied = *tracker_ptr;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;UnsafeCell::get&lt;&#x2F;code&gt; is &lt;code&gt;unsafe&lt;&#x2F;code&gt;, but we know that our use is sound because we’re the only thread accessing this right now (because of our &lt;code&gt;AtomicBool&lt;&#x2F;code&gt; lock).&lt;&#x2F;p&gt;
&lt;p&gt;Then, we need to find the next slot that’s free in &lt;code&gt;tracked_copied&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; chosen_index = None;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;BITS &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; tracker_copied &amp;amp; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; i) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        *tracker_ptr = tracker_copied | (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; i);
&lt;&#x2F;span&gt;&lt;span&gt;        chosen_index = Some(i as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;} 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, we have a counter for iterating through the bits of the tracker. We’re counting &lt;code&gt;0&lt;&#x2F;code&gt; as free and &lt;code&gt;1&lt;&#x2F;code&gt; as occupied, as we start our tracker as all zeroes. We check each bit by shifting &lt;code&gt;0b1&lt;&#x2F;code&gt; the relevant number of bits, and if we logical and that with the &lt;code&gt;tracker_copied&lt;&#x2F;code&gt; and get &lt;code&gt;0&lt;&#x2F;code&gt; we must know that that slot is free. We then update &lt;code&gt;tracker_copied&lt;&#x2F;code&gt; using a logical or, and set &lt;code&gt;chosen_index&lt;&#x2F;code&gt; to be the index we ended up using. We then break the loop.&lt;&#x2F;p&gt;
&lt;p&gt;Now that we’re done with parts that care about the tracker, we can ‘hand back’ our ‘lock’ by storing &lt;code&gt;false&lt;&#x2F;code&gt;. We then also need to upkeep our invariants by ensuring not to use the pointer we hold for the rest of the function.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.is_allocating.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;, SeqCst);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, we need to extract the our chosen index. We aren’t 100% sure that we actually had a free space, but if we didn’t then that variable never got set to &lt;code&gt;Some&lt;&#x2F;code&gt;, and so we can extract it using &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;rust-by-example&#x2F;flow_control&#x2F;let_else.html&quot;&gt;&lt;code&gt;let-else&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;Some(chosen_index) = chosen_index &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;std::ptr::null_mut();
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That way, if we didn’t find a index, we can just return a null pointer.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, we can actually return a valid index into our array with:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.spaces.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(chosen_index * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since &lt;code&gt;self.spaces&lt;&#x2F;code&gt; is an array, we know it is all in one space in our stack memory, so we can just cast it to the element in that array and add on &lt;code&gt;chosen_index * 4&lt;&#x2F;code&gt; to give each allocation 4 bytes.&lt;&#x2F;p&gt;
&lt;p&gt;So, overall:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;() != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4 &lt;&#x2F;span&gt;&lt;span&gt;|| layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;align&lt;&#x2F;span&gt;&lt;span&gt;() != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;std::ptr::null_mut();
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;wait until we can start allocating
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.is_allocating.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;compare_exchange&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;, SeqCst, SeqCst).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_err&lt;&#x2F;span&gt;&lt;span&gt;() {std::thread::yield_now()}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;theoretically, now only this thread should be able to allocate
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; tracker_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tracker.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(); 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; tracker_copied: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;= *tracker_ptr;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;Sound, as we&amp;#39;re the only thread accessing this pointer
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; chosen_index = None;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;BITS &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; tracker_copied &amp;amp; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; i) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            *tracker_ptr = tracker_copied | (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; i);
&lt;&#x2F;span&gt;&lt;span&gt;            chosen_index = Some(i as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    } 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;we&amp;#39;re done with the tracker, so we can give back our lock
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.is_allocating.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;, SeqCst);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;Some(chosen_index) = chosen_index &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;std::ptr::null_mut();
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.spaces.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(chosen_index * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;but-does-it-actually-work&quot;&gt;But does it actually work?&lt;&#x2F;h3&gt;
&lt;p&gt;If we go back into our main function, we can write a quick function to keep on allocating until we get a null pointer (which here, means that we ran out of memory):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; layout = Layout::new::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ALLOCATOR&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;(layout) };
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Got &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{ptr:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; ptr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_null&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Ran out @ attempt &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, i + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    i += &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, if we run that we can see that it successfully manages 64 allocations before getting a null pointer. That makes sense, because on a 64-bit platform (like my machine), addresses are 64-bit and so a &lt;code&gt;usize&lt;&#x2F;code&gt; has 64 bits. We can even run it using &lt;code&gt;cargo +nightly miri run&lt;&#x2F;code&gt; and still have success which is a good sign.&lt;&#x2F;p&gt;
&lt;p&gt;There’s still another test though - what about multi-threading? Since we know we’ll have a maximum of 64 allocations, we can spin up 5 threads which will each attempt to make 15 allocations so we can see that multiple threads can access our allocations and all will work:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; t in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cloned_layout = layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    std::thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|| {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; r in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;15 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ALLOCATOR&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;(cloned_layout)};
&lt;&#x2F;span&gt;&lt;span&gt;            println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{t}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;R&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{r}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt; got &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{ptr:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;} 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then (with miri for safety):&lt;&#x2F;p&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo +nightly miri run
&lt;&#x2F;span&gt;&lt;span&gt;# warnings from the compiler about not using variables in `dealloc`
&lt;&#x2F;span&gt;&lt;span&gt;T0R0 got 0x2da10
&lt;&#x2F;span&gt;&lt;span&gt;T1R0 got 0x2da14
&lt;&#x2F;span&gt;&lt;span&gt;T2R0 got 0x2da18
&lt;&#x2F;span&gt;&lt;span&gt;T3R0 got 0x2da1c
&lt;&#x2F;span&gt;&lt;span&gt;T4R0 got 0x2da20
&lt;&#x2F;span&gt;&lt;span&gt;error: the main thread terminated without waiting for all remaining threads
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;It looks like each thread managed to get 1 allocation done before stopping without waiting?&lt;&#x2F;p&gt;
&lt;p&gt;Right, so it turns out that I just forgot to tell the main thread to actually wait for the threads to finish, so let’s quickly fix that:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; threads = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; t in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cloned_layout = layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; handle = std::thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|| {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;do thread stuff
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;    threads.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(handle);
&lt;&#x2F;span&gt;&lt;span&gt;} 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for mut&lt;&#x2F;span&gt;&lt;span&gt; handle in threads {
&lt;&#x2F;span&gt;&lt;span&gt;    handle.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;unable to join handle&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I’ve deliberately picked 5 threads - too many could lead to nobody actually waiting for the allocator because of the time it takes to start a thread, and too few wouldn’t have a high enough chance of causing interesting race conditions (if there were any).&lt;&#x2F;p&gt;
&lt;p&gt;And if we then run it we see a bunch of different memory addresses and 11 null pointers. &lt;code&gt;5 * 15 - 11 = 64&lt;&#x2F;code&gt;, which means that we managed to allocate the right number of addresses, and so theoretically didn’t have race conditions. Yay!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-about-de-allocating&quot;&gt;What about de-allocating?&lt;&#x2F;h3&gt;
&lt;p&gt;So, right now we’ve got 64 allocations for the entire span of our program. That’s not very much, so it’d be nice to be able to de-allocate, so we become limited to 64 concurrent allocations, with theoretically infinite allocations over the span of the program. The following code samples will be to start filling out &lt;code&gt;fn dealloc (...)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;When deallocating, an invariant that is held for us (how nice!) is that that pointer was obtained from this allocator and so we can make a few very handy assumptions. Also - since memory from &lt;code&gt;alloc&lt;&#x2F;code&gt; is regarded as uninitialised (and it is in fact UB to access it without writing to it first), we don’t have to worry about zeroing the memory&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This means that we really only have to wait to use the tracker, and then zero the relevant bit. We can work out the relevant bit because we know how long each section is and where the memory block we have starts.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; offset = (ptr as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.spaces.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) &#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.is_allocating.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;compare_exchange&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;, SeqCst, SeqCst).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_err&lt;&#x2F;span&gt;&lt;span&gt;() {std::thread::yield_now()}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.tracker.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;*ptr = *ptr - (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; offset);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.is_allocating.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;, SeqCst);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can then &lt;code&gt;miri&lt;&#x2F;code&gt; a quick single-threaded test:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;_ in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1000 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ALLOCATOR&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;(layout)};
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; ptr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_null&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;        eprintln!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;What?&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ALLOCATOR&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;dealloc&lt;&#x2F;span&gt;&lt;span&gt;(ptr, layout) };
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And it exits successfully, which implies that everything worked - yay!&lt;&#x2F;p&gt;
&lt;p&gt;If we also tell it to print out the pointers, we see that we only actually used one of our slots because each time it would search for places and just find the first place every time!&lt;&#x2F;p&gt;
&lt;p&gt;If we modify it to only deallocate every 5 runs, and to only to do 16 total runs:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; to_be_freed = Vec::with_capacity(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ALLOCATOR&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;(layout)};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{ptr:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    to_be_freed.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(ptr);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; i % &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5 &lt;&#x2F;span&gt;&lt;span&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; ptr in std::mem::take(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; to_be_freed) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ALLOCATOR&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;dealloc&lt;&#x2F;span&gt;&lt;span&gt;(ptr, layout) };
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can see that it re-uses the same 5 slots:&lt;&#x2F;p&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo +nightly miri run
&lt;&#x2F;span&gt;&lt;span&gt;0x24320 &#x2F;&#x2F;start, clears list &amp;amp; deallocates because 0 % 5 == 0    0
&lt;&#x2F;span&gt;&lt;span&gt;0x24320 &#x2F;&#x2F;starts again at beginning                              1
&lt;&#x2F;span&gt;&lt;span&gt;0x24324 &#x2F;&#x2F;                                                       2
&lt;&#x2F;span&gt;&lt;span&gt;0x24328 &#x2F;&#x2F;                                                       3
&lt;&#x2F;span&gt;&lt;span&gt;0x2432c &#x2F;&#x2F;                                                       4
&lt;&#x2F;span&gt;&lt;span&gt;0x24330 &#x2F;&#x2F;5 % 5 == 0, so deallocates                             5
&lt;&#x2F;span&gt;&lt;span&gt;0x24320 &#x2F;&#x2F;starts again                                           6
&lt;&#x2F;span&gt;&lt;span&gt;0x24324 &#x2F;&#x2F;                                                       7
&lt;&#x2F;span&gt;&lt;span&gt;0x24328 &#x2F;&#x2F;                                                       8
&lt;&#x2F;span&gt;&lt;span&gt;0x2432c &#x2F;&#x2F;                                                       9
&lt;&#x2F;span&gt;&lt;span&gt;0x24330 &#x2F;&#x2F;deallocates as 10 % 5 == 0                             10
&lt;&#x2F;span&gt;&lt;span&gt;0x24320 &#x2F;&#x2F;starts again                                           11
&lt;&#x2F;span&gt;&lt;span&gt;0x24324 &#x2F;&#x2F;                                                       12
&lt;&#x2F;span&gt;&lt;span&gt;0x24328 &#x2F;&#x2F;                                                       13
&lt;&#x2F;span&gt;&lt;span&gt;0x2432c &#x2F;&#x2F;                                                       14
&lt;&#x2F;span&gt;&lt;span&gt;0x24330 &#x2F;&#x2F;deallocates as 15 % 5 == 0                             15
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;Final code can be seen &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;BurntNail&#x2F;ec64fb3c2ec3bfcb94d38ecfe9b39b2c&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-now&quot;&gt;What now?&lt;&#x2F;h3&gt;
&lt;p&gt;We could continue on with this basic structure of a bit-tracker and a bank of &lt;code&gt;u8&lt;&#x2F;code&gt;s held in an &lt;code&gt;UnsafeCell&lt;&#x2F;code&gt;. The problems start when you can’t rely on 1 bit being equal to 1 allocation, as you then have to start searching for long spaces which have enough space. If you want to go beyond 64 slots, you’d also need to start handling multiple &lt;code&gt;usize&lt;&#x2F;code&gt;s (possibly by using something like &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;bitvec&#x2F;latest&#x2F;bitvec&#x2F;array&#x2F;struct.BitArray.html&quot;&gt;&lt;code&gt;bitvec::BitArray&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;). Then, you need to have all of your memory stored on the stack which would a) limit you to a relatively small size and b) mean that you have to have all of the memory at the ready for the whole program, regardless of how much you actually need.&lt;&#x2F;p&gt;
&lt;p&gt;You might also need to start worrying about heap fragmentation, where the heap has enough free slots for the memory required but they aren’t contiguous, so you then need to make sure that your allocations are in ideal places (eg. small allocations in gaps to leave room for bigger ones to come later).&lt;&#x2F;p&gt;
&lt;p&gt;All of that having been said, I’ll be damned if I’m not going to even try to make a really shit one that technically works for any sized allocation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;time-to-handle-more-layouts&quot;&gt;Time to handle more layouts&lt;&#x2F;h2&gt;
&lt;p&gt;We’ll be starting from scratch here, but based off a similar structure to the previous allocator and I’ll start with a few things that would get annoying &lt;strong&gt;quickly&lt;&#x2F;strong&gt; with a multi-sized allocator.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tracker-replacement&quot;&gt;&lt;code&gt;tracker&lt;&#x2F;code&gt; replacement&lt;&#x2F;h3&gt;
&lt;p&gt;Instead of storing one &lt;code&gt;tracker&lt;&#x2F;code&gt; in an &lt;code&gt;UnsafeCell&lt;&#x2F;code&gt;, we’ll store an array of &lt;code&gt;Option&amp;lt;Allocation&amp;gt;&lt;&#x2F;code&gt;s. This will lead to a maximum number of allocations (which I’ll control using a constant generic parameter here), but that number will &lt;em&gt;not&lt;&#x2F;em&gt; change based off the size of things allocated. I’ll also control the size of our ‘heap memory’ using a constant generic parameter. I’ll also add a function to quickly get the whole range of an Allocation for convenience.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::alloc::Layout;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::sync::atomic::AtomicBool;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::cell::UnsafeCell;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Copy, Clone)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Allocation {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Allocation {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get_range &lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;we need to minus one because this range is inclusive
&lt;&#x2F;span&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.start, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.start.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;() - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;) })
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Allocator&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; MAX_ALLOCS: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; MEMORY_SIZE: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;is_allocating&lt;&#x2F;span&gt;&lt;span&gt;: AtomicBool,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allocations&lt;&#x2F;span&gt;&lt;span&gt;: UnsafeCell&amp;lt;[Option&amp;lt;Allocation&amp;gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;MAX_ALLOCS&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: UnsafeCell&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;MEMORY_SIZE&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;finding-a-space-to-allocate-into&quot;&gt;Finding a space to allocate into&lt;&#x2F;h4&gt;
&lt;p&gt;Then, we’ll start with a convenience function to find the next free space of a set size. One interesting thing to note is that I’ve decided to make it &lt;code&gt;unsafe&lt;&#x2F;code&gt;, with the invariant being that we hold the ‘lock’. Below is just a skeleton which we’ll fill out as we go.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; MAX_ALLOCS: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; MEMORY_SIZE: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; Allocator&amp;lt;MAX_ALLOCS, MEMORY_SIZE&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F;SAFETY: must hold onto the `is_allocating` lock before calling
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F;Finds the next space free for an allocation of given length. NB: does not update
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F;`allocations`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;find_next_space &lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; current_allocations = *&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.allocations.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; end = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.memory.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(length);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; next_space_to_chk = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.memory.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; next_space_to_chk.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(length) &amp;gt; end {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;            } 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        std::ptr::null_mut()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We quickly copy our list of allocations and store a convenience variable for the end of our list. We also make a temporary variable for the next space we need to check. Then, at the start of each loop we check if we can allocate that pointer without going past the end of the list, and if we can’t we break. If we break out of the loop, the only thing we can do is to just return a &lt;code&gt;None&lt;&#x2F;code&gt;. Now, we’ll have a look over a naive algorithm to find the next usable block of memory that takes place during the loop, after the out-of-bounds check.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(start_check, end_check) = (next_space_to_chk, next_space_to_chk.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(length));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; space_found = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; allocation in current_allocations.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;flatten&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(start_block, end_block) = allocation.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_range&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(start_block &amp;lt;= start_check &amp;amp;&amp;amp; start_check &amp;lt;= end_block) || (start_block &amp;lt;= end_check &amp;amp;&amp;amp; end_check &amp;lt;= end_block) {
&lt;&#x2F;span&gt;&lt;span&gt;        space_found = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        next_space_to_chk = end_block.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; space_found {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Some(next_space_to_chk);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, we just loop through all of our allocations to check if any part of our desired block for allocation is within another allocation. If it is, then we set the next spot to check to be just after the end of the block we intersected with and break the loop. If it isn’t, then we return that slot. We can then use this to write an actual function to allocate!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;allocating-function&quot;&gt;Allocating Function&lt;&#x2F;h3&gt;
&lt;p&gt;Firstly, we’ll quickly implement &lt;code&gt;Sync&lt;&#x2F;code&gt; for &lt;code&gt;Allocator&lt;&#x2F;code&gt;. Like before, this is an &lt;code&gt;unsafe impl&lt;&#x2F;code&gt; but we know that this is sound because we control access to be single-threaded for the &lt;code&gt;UnsafeCell&lt;&#x2F;code&gt;. We can then also quickly tell Rust to use this as the global allocator like we did right at the start. I’ll also add a skeleton &lt;code&gt;GlobalAlloc&lt;&#x2F;code&gt; implementation.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::alloc::GlobalAlloc;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; MAX_ALLOCS: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; MEMORY_SIZE: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; GlobalAlloc &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Allocator&amp;lt;MAX_ALLOCS, MEMORY_SIZE&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        todo!()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;dealloc&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ptr&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout) {
&lt;&#x2F;span&gt;&lt;span&gt;        todo!()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; MAX_ALLOCS: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; MEMORY_SIZE: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; Sync &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Allocator&amp;lt;MAX_ALLOCS, MEMORY_SIZE&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;global_allocator&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;static &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ALLOCATOR&lt;&#x2F;span&gt;&lt;span&gt;: Allocator&amp;lt;1000, 1_000_000&amp;gt; = Allocator {
&lt;&#x2F;span&gt;&lt;span&gt;    is_allocating: AtomicBool::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    allocations: UnsafeCell::new([None; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;]),
&lt;&#x2F;span&gt;&lt;span&gt;    memory: UnsafeCell::new([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1_000_000&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, we have to build a function to actually allocate. These are the steps we need:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Obtain the lock in order to make it sound to mutate &lt;code&gt;allocations&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Find a space to allocate (and if not, early return &lt;code&gt;std::ptr::null_mut&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Find a space to add it to our allocations list. If we find a spot, add it to the list (and if not, then &lt;code&gt;std::ptr::null_mut&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Unlock the lock.&lt;&#x2F;li&gt;
&lt;li&gt;Return our pointer from Step 2.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This is what I’ve managed for that:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;get the lock
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.is_allocating.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;compare_exchange&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;, SeqCst, SeqCst).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_err&lt;&#x2F;span&gt;&lt;span&gt;() {std::thread::yield_now()}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;find the position
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;Some(position_to_allocate) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;find_next_space&lt;&#x2F;span&gt;&lt;span&gt;(layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;()) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;out of memory, return null_mut
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;std::ptr::null_mut();
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;add it to our array of allocations
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; allocations_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.allocations.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut &lt;&#x2F;span&gt;&lt;span&gt;Option&amp;lt;Allocation&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; found_spot = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX_ALLOCS &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this_spot = allocations_ptr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(i);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(*this_spot).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_none&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;            *this_spot = Some(Allocation { start: position_to_allocate, layout });
&lt;&#x2F;span&gt;&lt;span&gt;            found_spot = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;!found_spot {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;out of allocations, return null_mut
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;std::ptr::null_mut();
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.is_allocating.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;, SeqCst);
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    position_to_allocate
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We first use the same snippet as earlier to acquire the lock. Then we use &lt;code&gt;let-else&lt;&#x2F;code&gt; to extract our pointer or early return. We then iterate through our array of allocations, and when we find a free slot we add our allocation there. If we didn’t find a free slot, then we early return. We then unlock and return the pointer.&lt;&#x2F;p&gt;
&lt;p&gt;We can then add a simple main function that does a few allocations to test this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Variable a = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{a}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; v = (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;| (x, x * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)).collect::&amp;lt;Vec&amp;lt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;)&amp;gt;&amp;gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(one, five) in v {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{one}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt; * 5 = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{five}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And if we check our console, we can see that we get all of our expected output:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --quiet
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Hello,&lt;&#x2F;span&gt;&lt;span&gt; world!
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Variable&lt;&#x2F;span&gt;&lt;span&gt; a = 5
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;* 5 = 5
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;* 5 = 10
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;3 &lt;&#x2F;span&gt;&lt;span&gt;* 5 = 15
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;4 &lt;&#x2F;span&gt;&lt;span&gt;* 5 = 20
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;5 &lt;&#x2F;span&gt;&lt;span&gt;* 5 = 25
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;6 &lt;&#x2F;span&gt;&lt;span&gt;* 5 = 30
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;7 &lt;&#x2F;span&gt;&lt;span&gt;* 5 = 35
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;8 &lt;&#x2F;span&gt;&lt;span&gt;* 5 = 40
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;9 &lt;&#x2F;span&gt;&lt;span&gt;* 5 = 45
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But that’s not the end of allocation, unfortunately.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;did-you-really-think-we-d-avoided-ub&quot;&gt;Did you really think we’d avoided UB?&lt;&#x2F;h3&gt;
&lt;p&gt;If we run it through &lt;code&gt;miri&lt;&#x2F;code&gt; instead, we get this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo +nightly miri run
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;error:&lt;&#x2F;span&gt;&lt;span&gt; Undefined Behavior: constructing invalid value: encountered an unaligned reference (required 8 byte alignment but found 1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; C:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\U&lt;&#x2F;span&gt;&lt;span&gt;sers&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\m&lt;&#x2F;span&gt;&lt;span&gt;icro&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\.&lt;&#x2F;span&gt;&lt;span&gt;rustup&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\t&lt;&#x2F;span&gt;&lt;span&gt;oolchains&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span&gt;ightly-x86_64-pc-windows-msvc&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\l&lt;&#x2F;span&gt;&lt;span&gt;ib&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\r&lt;&#x2F;span&gt;&lt;span&gt;ustlib&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span&gt;rc&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\r&lt;&#x2F;span&gt;&lt;span&gt;ust&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\l&lt;&#x2F;span&gt;&lt;span&gt;ibrary&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\a&lt;&#x2F;span&gt;&lt;span&gt;lloc&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span&gt;rc&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span&gt;ync.rs:1834:24
&lt;&#x2F;span&gt;&lt;span&gt;     |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;1834 &lt;&#x2F;span&gt;&lt;span&gt;|             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ptr::write&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; (*inner)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;.strong,&lt;&#x2F;span&gt;&lt;span&gt; atomic::AtomicUsize::new(1));
&lt;&#x2F;span&gt;&lt;span&gt;     |                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;^^^^^^^^^^^^^^^^^^^^&lt;&#x2F;span&gt;&lt;span&gt; constructing invalid value: encountered an unaligned reference (required 8 byte alignment but found 1)
&lt;&#x2F;span&gt;&lt;span&gt;     |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# further output removed - it just says that this is from the language runtime startup 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And we come to an old friend - alignment. We didn’t really have to deal with this earlier (in our 4-4-only allocator), because the length was identical to the alignment and we didn’t just randomly skip bytes to have to deal with alignment. Here, however it is an issue. Luckily, the fix is relatively simple.&lt;&#x2F;p&gt;
&lt;p&gt;The first change needed is to make our &lt;code&gt;find_next_space&lt;&#x2F;code&gt; take in a &lt;code&gt;Layout&lt;&#x2F;code&gt; rather than just a length (and then in the callsite, we just remove the &lt;code&gt;.size()&lt;&#x2F;code&gt; call). Then, we need to change our code that changes &lt;code&gt;next_space_to_chk&lt;&#x2F;code&gt;. Previously, we just set it to one after the end of the block that we overlapped with, but now we need to set it to the next aligned pointer.&lt;&#x2F;p&gt;
&lt;p&gt;Rust integer division rounds down, so we can find the number of align spaces we need to add to get away from this block using &lt;code&gt;(end_block as usize - start_check as usize) &#x2F; align + 1&lt;&#x2F;code&gt;. Then, we just multiply that by &lt;code&gt;align&lt;&#x2F;code&gt;. That’s this line: &lt;code&gt;next_space_to_chk = end_block.add(1);&lt;&#x2F;code&gt; going to: &lt;code&gt;next_space_to_chk = next_space_to_chk.add(((end_block as usize - start_check as usize) &#x2F; align + 1) * align);&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If we quickly run this through &lt;code&gt;miri&lt;&#x2F;code&gt;, we see no complaints! Next on the list is deallocation.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;deallocation&quot;&gt;Deallocation&lt;&#x2F;h3&gt;
&lt;p&gt;Just like last time, de-allocation is vastly simpler than allocation. We just need to find which allocation struct was dealing with that allocation, and then remove it. We don’t even need to worry about using the layout when de-allocating because we know the pointer and the start of the allocation will be identical (as specified in the &lt;code&gt;GlobalAlloc&lt;&#x2F;code&gt; docs).&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;dealloc&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ptr&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.is_allocating.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;compare_exchange&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;, SeqCst, SeqCst).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_err&lt;&#x2F;span&gt;&lt;span&gt;() {std::thread::yield_now()}       
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; allocations_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.allocations.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut &lt;&#x2F;span&gt;&lt;span&gt;Option&amp;lt;Allocation&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX_ALLOCS &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this_spot = allocations_ptr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(i);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span&gt;*this_spot {
&lt;&#x2F;span&gt;&lt;span&gt;            Some(Allocation { start, layout: _ }) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; start == ptr =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;                *this_spot = None;
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;            },
&lt;&#x2F;span&gt;&lt;span&gt;            _ =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.is_allocating.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;, SeqCst);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let’s just run a multi-threading test for safety - I’ve constructed one that does computations and allocations on multiple threads to really check that we’ve got one that works:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;factorial &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u128&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u128 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; n &amp;lt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; n;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;        
&lt;&#x2F;span&gt;&lt;span&gt;        n * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;factorial&lt;&#x2F;span&gt;&lt;span&gt;(n - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; threads = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; block in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;6 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; t = std::thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|| {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; v = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; n in (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;..=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;| block + x * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;                v.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;((n, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;factorial&lt;&#x2F;span&gt;&lt;span&gt;(n)));
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{v:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        });
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        threads.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(t);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; t in threads {
&lt;&#x2F;span&gt;&lt;span&gt;        t.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Theoretically, each thread should have a roughly similar amount of work to do with a naive factorial algorithm. This also works perfectly correctly using the standard allocator.&lt;&#x2F;p&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo +nightly miri run
&lt;&#x2F;span&gt;&lt;span&gt;[(5, 120), (10, 3628800), (15, 1307674368000), (20, 2432902008176640000), (25, 15511210043330985984000000)]
&lt;&#x2F;span&gt;&lt;span&gt;[(6, 720), (11, 39916800), (16, 20922789888000), (21, 51090942171709440000), (26, 403291461126605635584000000)]
&lt;&#x2F;span&gt;&lt;span&gt;[(7, 5040), (12, 479001600), (17, 355687428096000), (22, 1124000727777607680000), (27, 10888869450418352160768000000)]
&lt;&#x2F;span&gt;&lt;span&gt;error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `&amp;lt;unnamed&amp;gt;` and (2) non-atomic write on thread `&amp;lt;unnamed&amp;gt;` at alloc65+0x4c8. (2) just happened here
&lt;&#x2F;span&gt;&lt;span&gt;    --&amp;gt; C:\Users\micro\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\vec\mod.rs:1923:13
&lt;&#x2F;span&gt;&lt;span&gt;     |
&lt;&#x2F;span&gt;&lt;span&gt;1923 |             ptr::write(end, value);
&lt;&#x2F;span&gt;&lt;span&gt;     |             ^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic read on thread `&amp;lt;unnamed&amp;gt;` and (2) non-atomic write on thread `&amp;lt;unnamed&amp;gt;` at alloc65+0x4c8. (2) just happened here
&lt;&#x2F;span&gt;&lt;span&gt;     |
&lt;&#x2F;span&gt;&lt;span&gt;# further output that doesn&amp;#39;t help
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;And we’ve got a data race. 😔&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ub-2-electric-boogaloo&quot;&gt;UB 2: Electric Boogaloo&lt;&#x2F;h3&gt;
&lt;p&gt;To debug this, we should probably work out a way to provide some form of logging. The problem occurs when we realise that just using &lt;code&gt;println&lt;&#x2F;code&gt; would cause infinite recursion because that allocates a string&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-20-1&quot;&gt;&lt;a href=&quot;#fn-20&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. I’ve got one idea on how to do this nicely and then a backup (which will definitely work).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;printing-without-allocating&quot;&gt;Printing without allocating&lt;&#x2F;h3&gt;
&lt;p&gt;My first instinct is to go with the standard library, and see what I can do safely - and I can test both of these methods by just putting one at the top of my &lt;code&gt;alloc&lt;&#x2F;code&gt; function.&lt;&#x2F;p&gt;
&lt;p&gt;Usually, if I want to write to &lt;code&gt;stdout&lt;&#x2F;code&gt; without using &lt;code&gt;println!&lt;&#x2F;code&gt;, I have to get a handle to &lt;code&gt;Stdout&lt;&#x2F;code&gt; and then just use &lt;code&gt;std::io::Write&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Allocating!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;std::io::stdout().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write_all&lt;&#x2F;span&gt;&lt;span&gt;(s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_bytes&lt;&#x2F;span&gt;&lt;span&gt;()).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, I’ve unwrapped the error - this technically breaks the invariant on not panicking but I’m going to ignore that for now because this function won’t be here any longer than about another sentence. If we run it we recurse and so we never even reach the &lt;code&gt;unwrap&lt;&#x2F;code&gt; which means that &lt;code&gt;Stdout::write_all&lt;&#x2F;code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-30-1&quot;&gt;&lt;a href=&quot;#fn-30&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; must allocate somewhere. We could dive deep and bypass it, or we could just go to where the standard library eventually links to - &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;libc&quot;&gt;&lt;code&gt;libc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;A while ago, I read Amos’s piece on &lt;a href=&quot;https:&#x2F;&#x2F;fasterthanli.me&#x2F;articles&#x2F;small-strings-in-rust&quot;&gt;Small Strings in Rust&lt;&#x2F;a&gt;, and I remember that he somehow managed to print to stdout &lt;em&gt;without&lt;&#x2F;em&gt; allocating. That method is to use &lt;code&gt;libc::write&lt;&#x2F;code&gt; to &lt;code&gt;stdout&lt;&#x2F;code&gt; just passing a pointer and length. That does unfortunately&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-40-1&quot;&gt;&lt;a href=&quot;#fn-40&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; mark our first dependency - I love doing things myself but I draw the line at syscalls (especially on Windows 😭). He then goes on to use an actually sensible method for getting the allocations to the console, but I’m going for something different&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-50-1&quot;&gt;&lt;a href=&quot;#fn-50&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To test it to start with we’ll just try to print out a string:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; string = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Allocating!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;libc::write(???, string.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ptr&lt;&#x2F;span&gt;&lt;span&gt;() as _, string.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;() as _);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Most of that call is fine, apart from the &lt;code&gt;???&lt;&#x2F;code&gt; for which we need the file descriptor of the output stream we want to send stuff to. This is in &lt;code&gt;libc&lt;&#x2F;code&gt; for linux users under &lt;code&gt;libc::STDOUT_FILENO&lt;&#x2F;code&gt;, but not for windows 😔. I turned to DuckDuckGo and found &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;13531677&#x2F;stdin-fileno-undeclared-in-windows&quot;&gt;this SO post&lt;&#x2F;a&gt;, which mentions the file descriptor being 0. That did nothing for me, so I tried &lt;code&gt;1&lt;&#x2F;code&gt; and luckily it worked. Examining the post closer, it says &lt;code&gt;0!&lt;&#x2F;code&gt; so I’m just going to assume that they meant &lt;code&gt;factorial(0)&lt;&#x2F;code&gt; rather than using &lt;code&gt;!&lt;&#x2F;code&gt; for exclamation. &lt;em&gt;(correction: u&#x2F;skynetsatellite013 pointed out that I had actually misread the SO post and it was talking about STDIN_FILENO not STDOUT_FILENO 🤦)&lt;&#x2F;em&gt; I’ll chuck that into a constant, and we then get a function for printing string references:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STDOUT_FILENO&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;print_string &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        libc::write(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STDOUT_FILENO&lt;&#x2F;span&gt;&lt;span&gt;, s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ptr&lt;&#x2F;span&gt;&lt;span&gt;() as _, s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Quick note: we need to cast the pointer to a &lt;code&gt;*const c_void&lt;&#x2F;code&gt;, but since the Rust compiler knows that we can just use an &lt;code&gt;_&lt;&#x2F;code&gt; to tell it to infer. This just saves an import.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately, this is where &lt;code&gt;miri&lt;&#x2F;code&gt; forsakes us because we’re making function calls which it cannot decipher. Once we’re finished with our whole &lt;code&gt;print_allocation&lt;&#x2F;code&gt; function, I’ll show a quick method to still be able to use &lt;code&gt;miri&lt;&#x2F;code&gt; with the rest of the program.&lt;&#x2F;p&gt;
&lt;p&gt;Then, we can extend that logic to make a function to print numbers. After some quick searching to find how to get the digits of a number (I managed to adapt something from &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;41536479&#x2F;how-do-i-split-an-integer-into-individual-digits&quot;&gt;here&lt;&#x2F;a&gt;) we can then print them out. That code spat out numbers in reverse order for me so I just print them out in reverse.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;print_number &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;NUMBERS&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;] = &amp;amp;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;9&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; numbers = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;64&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; digit = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span&gt; n != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this_digit = (n % &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;) as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        numbers[digit] = this_digit;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        n &#x2F;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        digit += &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span&gt; digit != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        digit -= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ libc::write(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STDOUT_FILENO&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;NUMBERS&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ptr&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const u8&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(numbers[digit]) as _, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;) };
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can then use both of those functions to build out a &lt;code&gt;print_allocation&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;print_allocation &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print_string&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Thread #&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print_number&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ winapi::um::processthreadsapi::GetCurrentThreadId() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print_string&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt; Allocating &lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print_number&lt;&#x2F;span&gt;&lt;span&gt;(layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print_string&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print_number&lt;&#x2F;span&gt;&lt;span&gt;(layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;align&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print_string&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because I’m on a windows machine, in order to get the thread ID&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-60-1&quot;&gt;&lt;a href=&quot;#fn-60&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, I have to add another dependency - &lt;code&gt;winapi&lt;&#x2F;code&gt; with the &lt;code&gt;processthreadsapi&lt;&#x2F;code&gt; feature. I can then use &lt;code&gt;winapi::um::processthreadsapi::GetCurrentThreadId()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Then, we can add this to the top of &lt;code&gt;fn alloc(layout: Layout)&lt;&#x2F;code&gt;, just below where we acquire the lock.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cfg&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;not&lt;&#x2F;span&gt;&lt;span&gt;(miri))]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print_allocation&lt;&#x2F;span&gt;&lt;span&gt;(layout);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The conditional compilation statement just makes sure that this function never gets called if we’re running with &lt;code&gt;miri&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;As we worked out earlier, even if you do nothing, the main function does some allocations, so we can just run &lt;code&gt;fn main () {}&lt;&#x2F;code&gt; and see:&lt;&#x2F;p&gt;
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo r --quiet
&lt;&#x2F;span&gt;&lt;span&gt;Thread #2024 Allocating 10-2
&lt;&#x2F;span&gt;&lt;span&gt;Thread #2024 Allocating 5-1
&lt;&#x2F;span&gt;&lt;span&gt;Thread #2024 Allocating 48-8
&lt;&#x2F;span&gt;&lt;span&gt;Thread #2024 Allocating 64-8
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;If I run it multiple times, then I get the same allocations displayed, only with different thread IDs.&lt;&#x2F;p&gt;
&lt;p&gt;We can then add another function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;print_end_of_allocation &lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print_string&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Thread #&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print_number&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ winapi::um::processthreadsapi::GetCurrentThreadId() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print_string&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt; finished allocation&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And use it just before we lose the lock and with the same conditional compilation gate. We then see this as output:
&lt;div class=&quot;crt scanlines&quot; aria-hidden=&quot;true&quot;&gt;
	&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo run --quiet
&lt;&#x2F;span&gt;&lt;span&gt;Thread #2072 Allocating 10-2
&lt;&#x2F;span&gt;&lt;span&gt;        Thread #2072 finished allocation
&lt;&#x2F;span&gt;&lt;span&gt;Thread #2072 Allocating 5-1
&lt;&#x2F;span&gt;&lt;span&gt;        Thread #2072 finished allocation
&lt;&#x2F;span&gt;&lt;span&gt;Thread #2072 Allocating 48-8
&lt;&#x2F;span&gt;&lt;span&gt;        Thread #2072 finished allocation
&lt;&#x2F;span&gt;&lt;span&gt;Thread #2072 Allocating 64-8
&lt;&#x2F;span&gt;&lt;span&gt;        Thread #2072 finished allocation
&lt;&#x2F;span&gt;&lt;span&gt;# more output cut
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;

&lt;&#x2F;div&gt;
&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-were-we-doing-again&quot;&gt;What were we doing again?&lt;&#x2F;h3&gt;
&lt;p&gt;If we were to then run our latest multi-threading test again we’d get a &lt;strong&gt;lot&lt;&#x2F;strong&gt; of output. To avoid this, I’ve just replaced the &lt;code&gt;vec!&lt;&#x2F;code&gt; calls with calls to &lt;code&gt;Vec::with_capacity&lt;&#x2F;code&gt; with capacity to hold the relevant struct. I’ve also added the thread ID to each call to &lt;code&gt;println!&lt;&#x2F;code&gt; inside a thread. That way, we might be able to see if it’s an issue with allocation or deallocation.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately, the output suggests that only one thread is ever holding the lock as each allocation start is immediately followed by that thread ID saying that it finished that allocation. This suggests that our problem lies elsewhere, which is unfortunate because that might be harder to fix.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-else-could-it-be&quot;&gt;What else could it be?&lt;&#x2F;h3&gt;
&lt;p&gt;Thanks to the printing, we know at least know that only one thread is concurrently using the allocation function. However, since we’re still getting data races&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-70-1&quot;&gt;&lt;a href=&quot;#fn-70&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; there must be concurrent access to pointers. The next step&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-80-1&quot;&gt;&lt;a href=&quot;#fn-80&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; is then to look at where we choose our pointer to hand over in &lt;code&gt;find_next_space&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;find_next_space &lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; current_allocations = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.allocations.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; end = (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.memory.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MEMORY_SIZE&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; length = layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; align = layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;align&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; next_space_to_chk = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.memory.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; next_space_to_chk.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(length) &amp;gt; end {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(start_check, end_check) = (next_space_to_chk, next_space_to_chk.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(length));
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; space_found = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; allocation in current_allocations.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;flatten&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(start_block, end_block) = allocation.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_range&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(start_block &amp;lt;= start_check &amp;amp;&amp;amp; start_check &amp;lt;= end_block) || (start_block &amp;lt;= end_check &amp;amp;&amp;amp; end_check &amp;lt;= end_block) {
&lt;&#x2F;span&gt;&lt;span&gt;                    space_found = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;                    next_space_to_chk = next_space_to_chk.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(((end_block as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;- start_check as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) &#x2F; align) * align);
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; space_found {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Some(next_space_to_chk);
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    None
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;We make a copy of our existing allocations for convenience - we’re reading from the pointer, but we know that we won’t get any data races because we’ve locked the lock.&lt;&#x2F;li&gt;
&lt;li&gt;We make a convenience variable to store the pointer after what we’re allowed to allocate - we only ever compare to this so we’re fine. This accesses the &lt;code&gt;memory&lt;&#x2F;code&gt; pointer, but never dereferences it and we’re in the lock anyway.&lt;&#x2F;li&gt;
&lt;li&gt;We set a variable equal to the start of our memory. This will eventually become our pointer to the memory, but we modify and check it several times so we’ll deal with that in a minute.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Then, we enter a loop:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;We check if we’ve gone out of our memory bounds. We can check for &lt;code&gt;&amp;gt; end&lt;&#x2F;code&gt; because &lt;code&gt;next_space_to_chk.add(length)&lt;&#x2F;code&gt; represents the pointer after the final one we use (because of zero-indexing).&lt;&#x2F;li&gt;
&lt;li&gt;We then create a convenience variable with the that &lt;code&gt;next_space_to_chk.add(length)&lt;&#x2F;code&gt; as the value.&lt;&#x2F;li&gt;
&lt;li&gt;We also declare a temporary variable for a flag, which assumes that we will find a space. We can then invalidate that if we overlap in the loop.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;We then enter &lt;em&gt;another&lt;&#x2F;em&gt; loop for every allocation:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;We get the &lt;strong&gt;inclusive&lt;&#x2F;strong&gt; range of pointers that that allocation uses.&lt;&#x2F;li&gt;
&lt;li&gt;We then check if either our start or end checking pointers are in the range. I’m not 100% sure about this maths, so we’ll check back on it later but it looks right to me right now.&lt;&#x2F;li&gt;
&lt;li&gt;If that check works, then we invalidate the assumption that we found a space.&lt;&#x2F;li&gt;
&lt;li&gt;We then do some pointer maths to add a multiple of &lt;code&gt;align&lt;&#x2F;code&gt; that should be just after the &lt;code&gt;end_block&lt;&#x2F;code&gt;.
If we’re testing this part, we can make the assumption that we have far more memory than we need for this program. From our earlier tests, I didn’t see any allocations bigger than about 100 bytes, so if we just add &lt;code&gt;1000 * align&lt;&#x2F;code&gt;, we’re pretty much guaranteed to be fine&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-90-1&quot;&gt;&lt;a href=&quot;#fn-90&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. If we run this with multi-threading under &lt;code&gt;miri&lt;&#x2F;code&gt; it works! 🥳🥳🥳&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-100-1&quot;&gt;&lt;a href=&quot;#fn-100&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This suggests that there’s an error with my logic that chooses when we’ve overlapped with another allocation. I’m also not the happiest with how this function looks so I’m going to make another pass over it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;find_next_space &lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;layout&lt;&#x2F;span&gt;&lt;span&gt;: Layout) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; current_allocations = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.allocations.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; end = (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.memory.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MEMORY_SIZE&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; length = layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; align = layout.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;align&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; next_space_to_chk = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.memory.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; end_check = next_space_to_chk.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(length - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; end_check &amp;gt;= end {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;None;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; space_found = current_allocations.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;flatten&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;all&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allocation&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(start_block, end_block) = allocation.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_range&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;            (next_space_to_chk &amp;lt; start_block &amp;amp;&amp;amp; end_check &amp;lt; start_block) || (next_space_to_chk &amp;gt; end_block &amp;amp;&amp;amp; end_check &amp;gt; end_block)
&lt;&#x2F;span&gt;&lt;span&gt;        });
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; space_found {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Some(next_space_to_chk);
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;        next_space_to_chk = next_space_to_chk.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(align);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This new function reduces some of the duplication I had earlier like both &lt;code&gt;start_check&lt;&#x2F;code&gt; and &lt;code&gt;next_space_to_chk&lt;&#x2F;code&gt; existing which was confusing. This function also works with no UB which would suggest that it is sound. I’ve also changed the logic for working out whether we overlap - either the whole block needs to be before the start, or after the end which makes more sense to me.&lt;&#x2F;p&gt;
&lt;p&gt;The low-hanging fruit for optimisation is to change the &lt;code&gt;all&lt;&#x2F;code&gt; call to a &lt;code&gt;find&lt;&#x2F;code&gt; call so we know which block we overlapped, to reduce the number of iterations.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; overlapping_block = current_allocations.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;flatten&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;find&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allocation&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(start_block, end_block) = allocation.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_range&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    !((next_space_to_chk &amp;lt; start_block &amp;amp;&amp;amp; end_check &amp;lt; start_block) || (next_space_to_chk &amp;gt; end_block &amp;amp;&amp;amp; end_check &amp;gt; end_block))
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; overlapping_block {
&lt;&#x2F;span&gt;&lt;span&gt;    Some(block) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; end = block.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_range&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; delta = end as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;- next_space_to_chk as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; aligns = delta &#x2F; align + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        next_space_to_chk = next_space_to_chk.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(align * aligns);
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    None =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Some(next_space_to_chk)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And that’s us done! Final code can be seen &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;BurntNail&#x2F;86463774717f1de59d76693e62e768d2&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing Thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;I can now technically say that I’ve built an allocator - more than likely one of the worst ones you’ve ever seen, but one that does work &lt;em&gt;just about&lt;&#x2F;em&gt;. There are however a few problems with it right now:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Because I don’t really know how to get more memory on the fly&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-110-1&quot;&gt;&lt;a href=&quot;#fn-110&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, all of the memory in this allocator exists for the entire program which means that you have to know how much memory you are going to need at compile-time which is pretty annoying. That’s why in the &lt;code&gt;gist&lt;&#x2F;code&gt; I just give it a gigabyte&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-120-1&quot;&gt;&lt;a href=&quot;#fn-120&quot;&gt;13&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; of RAM to make that a problem that I don’t have to deal with.&lt;&#x2F;li&gt;
&lt;li&gt;This allocator just tries to find the first space it can which would result in pretty bad heap fragmentation in a longer running program. This is where the heap has more than enough space to store what you’re trying to allocate but not contiguously because of bad planning. For example, let’s say we have a 10 byte heap. We allocate 2 &lt;code&gt;u32&lt;&#x2F;code&gt;s in the first 8 bytes. We then deallocate the first &lt;code&gt;u32&lt;&#x2F;code&gt;, and allocate a &lt;code&gt;u8&lt;&#x2F;code&gt;. That then goes in the first free space at the very start. We now have 5 bytes allocated out of 10, but nowhere to put another &lt;code&gt;u32&lt;&#x2F;code&gt; because our heap is fragmented.&lt;&#x2F;li&gt;
&lt;li&gt;Because we’re not getting a heap in a way that &lt;code&gt;miri&lt;&#x2F;code&gt; understands, &lt;code&gt;miri&lt;&#x2F;code&gt; and other similar tools cannot give us any help with pointers that aren’t freed - if we put a quick &lt;code&gt;let ptr = unsafe { alloc(Layout::new::&amp;lt;u8&amp;gt;()) };&lt;&#x2F;code&gt;, and then never free that we won’t have any way to know except for careful program analysis, which as we all know is &lt;a href=&quot;https:&#x2F;&#x2F;www.cvedetails.com&#x2F;vulnerability-list&#x2F;opmemc-1&#x2F;memory-corruption.html&quot;&gt;100% effective&lt;&#x2F;a&gt;. It also won’t warn us for use-after-frees. It is still a useful tool for things like concurrent accesses, but not much more than that.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That pretty much sums up my thoughts on the topic. I’ve gotta also say that I’ve loved doing this in Rust - the only runtime error that took me forever to figure out was the UB right at the end. This was also a really interesting project for me, because I got to take a deep look at a thing that I haven’t really even thought about before and that I usually just take for granted.&lt;&#x2F;p&gt;
&lt;p&gt;As with my other memory-related post, I’m happy to acknowledge that I’m not an all-knowing Rust God and if I’ll happily add corrections with credit. All I can say is that I’ve tried to ensure that the code is sound.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-0&quot;&gt;
&lt;p&gt;Yes, I know that because we’re using our own allocator piecemeal that we are allowed to allocate and deal with allocating stuff. However, firstly this is good practice for later when we actually want to allocate everything later. Also - &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;struct.Arc.html#method.new&quot;&gt;&lt;code&gt;Arc::new&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; isn’t &lt;code&gt;const&lt;&#x2F;code&gt;, so we can’t create it in a static context. Yes, we could just create the allocator at the top of main, but then we go back to the first point. &lt;a href=&quot;#fr-0-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;No guarantees are made about the contents of memory from &lt;code&gt;alloc&lt;&#x2F;code&gt;, but if you need pre-zeroed memory one of the provided functions for &lt;code&gt;GlobalAlloc&lt;&#x2F;code&gt; is &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;alloc&#x2F;trait.GlobalAlloc.html#method.alloc_zeroed&quot;&gt;&lt;code&gt;GlobalAlloc::alloc_zeroed&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which just gets the memory and writes zeroes to it if the pointer wasn’t null. &lt;a href=&quot;#fr-5-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-20&quot;&gt;
&lt;p&gt;How do I know? I was pretty sure it did, and then I added a quick &lt;code&gt;println!&lt;&#x2F;code&gt; to the top of &lt;code&gt;Allocator::alloc&lt;&#x2F;code&gt; to confirm. &lt;a href=&quot;#fr-20-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-30&quot;&gt;
&lt;p&gt;&lt;code&gt;Stdout::write&lt;&#x2F;code&gt; also hits a recursion error, so not it’s not that. I just didn’t want to deal with partial writes here. &lt;a href=&quot;#fr-30-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-40&quot;&gt;
&lt;p&gt;Unfortunately for my &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Not_invented_here&quot;&gt;NIH&lt;&#x2F;a&gt;, not for any actual reason. For actual projects though, I’m more than happy to add dependencies. &lt;a href=&quot;#fr-40-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-50&quot;&gt;
&lt;p&gt;He creates an array by &lt;code&gt;[0; 1024]&lt;&#x2F;code&gt;, then creates a &lt;code&gt;Cursor&lt;&#x2F;code&gt; holding the array which implements &lt;code&gt;std::io::Write&lt;&#x2F;code&gt;, so he can then use &lt;code&gt;serde_json::to_writer&lt;&#x2F;code&gt;. Then, he can get the end of the cursor to create a slice for all of the characters of the array that actually matter. &lt;a href=&quot;#fr-50-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-60&quot;&gt;
&lt;p&gt;I can’t use &lt;code&gt;std::thread::current().id().as_u64()&lt;&#x2F;code&gt; as that allocates. It’s also unstable right now, and this article is about stable Rust. I also can’t just use &lt;code&gt;libc::pthread_self()&lt;&#x2F;code&gt; because windows. &lt;a href=&quot;#fr-60-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-70&quot;&gt;
&lt;p&gt;Just to clarify - this is when multiple threads try to concurrently store data in the same memory address. The problem is that which thread writes first is non-deterministic outside of &lt;code&gt;Atomic&lt;&#x2F;code&gt; operations, which we aren’t using here (because Rust only has a few built-in &lt;code&gt;Atomic types&lt;&#x2F;code&gt;, which wouldn’t cover a 1 million byte array). &lt;a href=&quot;#fr-70-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-80&quot;&gt;
&lt;p&gt;This should really have been the first step, but I was already looking for an excuse to print without allocating. &lt;a href=&quot;#fr-80-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-90&quot;&gt;
&lt;p&gt;It’s also relatively easy to test this - just quickly remove the multi-threading parts, and it all works fine even under &lt;code&gt;miri&lt;&#x2F;code&gt;. &lt;a href=&quot;#fr-90-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-100&quot;&gt;
&lt;p&gt;You know what they say - premature optimisation is the root of all evil - &lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;1691&#x2F;&quot;&gt;relevant xkcd&lt;&#x2F;a&gt;. &lt;a href=&quot;#fr-100-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-110&quot;&gt;
&lt;p&gt;Apart from just using &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;alloc&#x2F;struct.System.html&quot;&gt;&lt;code&gt;std::alloc::System&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, but at that point you’re basically just wrapping it and probably doing a worse job. &lt;a href=&quot;#fr-110-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-120&quot;&gt;
&lt;p&gt;Fun fact - a gigabyte is actually 1 million bytes because we’re using the &lt;a href=&quot;https:&#x2F;&#x2F;www.nist.gov&#x2F;pml&#x2F;owm&#x2F;metric-si-prefixes&quot;&gt;SI prefix&lt;&#x2F;a&gt; of &lt;em&gt;giga&lt;&#x2F;em&gt;. If you want to talk about &lt;code&gt;1024 * 1024&lt;&#x2F;code&gt; bytes, you need to use a gibibyte (aka &lt;code&gt;GiB&lt;&#x2F;code&gt;). Similar binary prefixes also exist for smaller units like mebibyte and kibibyte. The confusion comes where people mess them up (sometimes accidentally, and sometimes &lt;em&gt;accidentally&lt;&#x2F;em&gt;) and you get hard drives seeming smaller than they actually are and other similar problems. &lt;a href=&quot;#fr-120-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>Adventures in Binary Serialisation</title>
          <pubDate>Sun, 07 Jan 2024 00:00:00 +0000</pubDate>
          <author>Jack Maguire</author>
          <link>https://maguire.tech/posts/binary-serialisation/</link>
          <guid>https://maguire.tech/posts/binary-serialisation/</guid>
          <description xml:base="https://maguire.tech/posts/binary-serialisation/">&lt;p&gt;The other day I came across an interesting question&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-0-1&quot;&gt;&lt;a href=&quot;#fn-0&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; - instead of faffing around with &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;serde&quot;&gt;&lt;code&gt;serde&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and dealing with the compile-time hits, can I just write the binary data from RAM to a file? This is just an exploration of that problem. I thought this would be simple, but I ended up finding some interesting UB and digging into how Vec allocates just a little bit.&lt;&#x2F;p&gt;
&lt;p&gt;If you find any factual errors with this article - I’ll happily take responsibility, edit it and provide appropriate credit. I’ve tried my best and that’s kinda all I can give. See contact details &lt;a href=&quot;https:&#x2F;&#x2F;maguire.tech&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Because, at least for now, this is just an experience in having fun I’ll be using whatever structs please me&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; without any real focus on real-world usage. I’ll also be expecting some intermediate to advanced knowledge on programming because I’ll be skipping over some basic explanations. This will also be specific to Rust and other manual-memory management languages.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;plain-old-data&quot;&gt;Plain-Old-Data&lt;&#x2F;h2&gt;
&lt;p&gt;Firstly, I have to work out some data to store, so I’ll start with a simple struct:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;ExampleData {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; 7],
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;example_data &lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; ExampleData {
&lt;&#x2F;span&gt;&lt;span&gt;    ExampleData {
&lt;&#x2F;span&gt;&lt;span&gt;        a: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        b: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        c: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;11&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;14&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;15&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;],
&lt;&#x2F;span&gt;&lt;span&gt;        d: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;123456789
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I’ve carefully chosen the types and their positions (but I’ll get more into that later), but all that matters for now is that they’re all stored on the stack&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;serialising&quot;&gt;Serialising&lt;&#x2F;h3&gt;
&lt;p&gt;Guess what? We’re all done here, because the compiler does all the work! The struct must be somewhere in memory and we just need to work out how to trick the compiler into letting us see the struct as just a series of bytes.&lt;&#x2F;p&gt;
&lt;p&gt;After some real soul-searching&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, I managed to find this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;any_as_u8_slice&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: Sized&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;T) -&amp;gt; &amp;amp;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;] {
&lt;&#x2F;span&gt;&lt;span&gt;    ::core::slice::from_raw_parts(
&lt;&#x2F;span&gt;&lt;span&gt;        (p as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const&lt;&#x2F;span&gt;&lt;span&gt; T) as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ::core::mem::size_of::&amp;lt;T&amp;gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This takes a reference to a Rust object (which has a finite and known-at-compile-time size), and creates a slice of bytes starting at the address of the reference with the length being the length of the struct. This looks sound to me as we know that the slice will only be valid for as long as the struct (because of lifetimes which are elided here), and we’re only accessing memory that we know belongs to the struct.&lt;&#x2F;p&gt;
&lt;p&gt;If we just print this to stdout, we see something really interesting that rust does that lots of other languages don’t:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;255&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;255&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;255&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;255&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;255&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;255&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;255&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;255&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;21&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;205&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;91&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;11&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;14&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;15&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I deliberately picked some quite distinctive values for the example data - we can see the 8 &lt;code&gt;255&lt;&#x2F;code&gt;s for the &lt;code&gt;u64::MAX&lt;&#x2F;code&gt;, the &lt;code&gt;[21, 205, 91, 7]&lt;&#x2F;code&gt; for our &lt;code&gt;u32&lt;&#x2F;code&gt;, the &lt;code&gt;0&lt;&#x2F;code&gt; for the u8, the &lt;code&gt;[10, 11, 12, 13, 14, 15, 16]&lt;&#x2F;code&gt; for the &lt;code&gt;u8&lt;&#x2F;code&gt; array. However, there are two main problems here - firstly, the struct’s been reordered and there’s also an extra 4 &lt;code&gt;0&lt;&#x2F;code&gt;s on the end?&lt;&#x2F;p&gt;
&lt;p&gt;The first is a consequence of Rust not having a stable ABI - that is to say that the compiler reserves every right to screw around with the internal representation of anything and everything if it works out it can pack it more efficiently. The second is a consequence of padding - unless we tell it otherwise, the compiler always tries to &lt;em&gt;align&lt;&#x2F;em&gt; the length of the struct to the &lt;del&gt;&lt;code&gt;word length&lt;&#x2F;code&gt; of the PC running the code (here, 8 bytes for a 64-byte word)&lt;&#x2F;del&gt; &lt;em&gt;correction: alignment is actually usually determined by the maximum length of variables inside - here, a u64 so 8 bytes&lt;&#x2F;em&gt;. This just allows reads to be far more efficient for reasons I’m not 100% sure on - I just chalk it up to one of those things that we deal with in exchange for &lt;em&gt;&lt;strong&gt;lightning rock magic&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;. &lt;em&gt;correction: some CPU instructions also require alignment for being able to work, not just performance reasons&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We can fix the first by adding a little &lt;code&gt;#[repr(C)]&lt;&#x2F;code&gt; to just before our struct declaration which tells the compiler to follow the C style which preserves ordering. However, this then balloons our struct to 32 bytes rather than just 24. The only reason you’d do so would be if you were trying to do some form of &lt;code&gt;FFI&lt;&#x2F;code&gt;, but there are far better solutions.&lt;&#x2F;p&gt;
&lt;p&gt;However, if you run this through &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&quot;&gt;&lt;code&gt;miri&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, you’ll see that this function exhibits undefined behaviour. This is because we’re accessing uninitialised memory. At first, you might be confused as to why - it’s the padding. Padding is uninitialised memory and so this function is UB (I’ll discuss UB more later, don’t worry). To fix this, we can instead &lt;code&gt;#[repr(packed)]&lt;&#x2F;code&gt;, which removes all padding at a possible cost to performance. That having been said, for &lt;em&gt;future learning opportunities&lt;&#x2F;em&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, we’ll pretend that the struct isn’t packed for the rest of this article.&lt;&#x2F;p&gt;
&lt;p&gt;For now, I’ll write those bytes to a file.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::{io::Write, fs::File};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main &lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; std::io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; eg = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;example_data&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bytes = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;any_as_u8_slice&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;eg) };
&lt;&#x2F;span&gt;&lt;span&gt;    File::create(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;out.bin&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write_all&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;bytes)?;
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;deserialising&quot;&gt;Deserialising&lt;&#x2F;h3&gt;
&lt;p&gt;Then, on this end, I can read those bytes back in to prove I’m using different bytes.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::Read;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_in &lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; std::io::Result&amp;lt;ExampleData&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; bytes = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;SIZE&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; reader = File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;out.bin&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; tmp = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;SIZE&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; reader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; tmp)? {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            n =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;                bytes.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;extend&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;tmp[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..n]);
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    todo!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;What now?&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I now have a vector full of data which consists of a pointer to the beginning of the data and the length of that data. I now need to do the reverse of what I did before but this is not nearly as easy.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;raw-pointer-dereference&quot;&gt;Raw pointer dereference&lt;&#x2F;h3&gt;
&lt;p&gt;My first instinct here is just to dereference the pointer like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ptr = bytes.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ptr&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const&lt;&#x2F;span&gt;&lt;span&gt; ExampleData;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; example = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ *ptr };
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We just have to cast it from a &lt;code&gt;*const u8&lt;&#x2F;code&gt; to a &lt;code&gt;*const ExampleData&lt;&#x2F;code&gt;, which is easy.&lt;&#x2F;p&gt;
&lt;p&gt;The first problem comes from the fact that we can’t dereference the pointer because we’d need to copy out the data. We can fix that with a quick &lt;code&gt;#[derive(Copy, Clone)]&lt;&#x2F;code&gt;. This then appears to work, until we run it through &lt;code&gt;miri&lt;&#x2F;code&gt; and see that the alignment is incorrect and this is undefined behaviour - we’ll have the same problem with the next method so I’ll dive deeper into it there.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;boxing&quot;&gt;Boxing&lt;&#x2F;h3&gt;
&lt;p&gt;Let’s delete the derive and try again by thinking about how we deal with pointers in Rust.&lt;&#x2F;p&gt;
&lt;p&gt;Well, we typically do that with a Box, which holds a pointer to a struct on the heap. We usually make one of these with &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;boxed&#x2F;struct.Box.html#method.new&quot;&gt;&lt;code&gt;Box::new&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to get it from the stack to the heap, but if the data is already on the heap, we can use &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;boxed&#x2F;struct.Box.html#method.from_raw&quot;&gt;&lt;code&gt;Box::from_raw&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; boxed: Box&amp;lt;ExampleData&amp;gt; = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Box::from_raw(bytes.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut&lt;&#x2F;span&gt;&lt;span&gt; ExampleData) };
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Ok(*boxed);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is very similar to the way we made a slice earlier, but here we don’t need to specify the size as &lt;code&gt;ExampleData&lt;&#x2F;code&gt; has a constant size. This then also works just fine, because we can dereference the box without needing copy and we’ve got the struct back out from the heap. 🥳🥳&lt;&#x2F;p&gt;
&lt;p&gt;However, if you run this just with &lt;code&gt;cargo run&lt;&#x2F;code&gt;, you’ll see a problem. You won’t see a lovely &lt;code&gt;0&lt;&#x2F;code&gt; exit code, and instead we get this: &lt;code&gt;error: process didn&#x27;t exit successfully: &#x27;target\debug\ser.exe&#x27; (exit code: 0xc0000374, STATUS_HEAP_CORRUPTION)&lt;&#x2F;code&gt;. This implies that we’ve somehow corrupted the heap, so let’s have a gander at the documentation.&lt;&#x2F;p&gt;
&lt;p&gt;The Rust standard library documentation is incredible for having thorough safety discussions and help for unsafe functions. If we look &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;boxed&#x2F;struct.Box.html#method.from_raw&quot;&gt;back at the function documentation&lt;&#x2F;a&gt;, we can see that it has this to say:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Constructs a box from a raw pointer.&lt;&#x2F;p&gt;
&lt;p&gt;After calling this function, the raw pointer is owned by the resulting Box. Specifically, the Box destructor will call the destructor of T and free the &amp;gt; allocated memory. For this to be safe, the memory must have been allocated in accordance with the memory layout used by Box.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Safety&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This function is unsafe because improper use may lead to memory problems. For example, a double-free may occur if the function is called twice on the same &amp;gt; raw pointer.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Here, we can now see our error - a classic double-free. When the function exits, &lt;code&gt;bytes&lt;&#x2F;code&gt; will get freed. Since &lt;code&gt;*boxed&lt;&#x2F;code&gt; goes back to &lt;code&gt;main&lt;&#x2F;code&gt;, it’ll get freed at the end there and we’ve now freed the same memory twice which corrupts the heap. Luckily, the fix here is relatively simple - we just need to add a strategic &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;mem&#x2F;fn.forget.html&quot;&gt;&lt;code&gt;std::mem::forget&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;bytes.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;shrink_to_fit&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; boxed: Box&amp;lt;ExampleData&amp;gt; = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Box::from_raw(bytes.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut&lt;&#x2F;span&gt;&lt;span&gt; ExampleData) };
&lt;&#x2F;span&gt;&lt;span&gt;std::mem::forget(bytes);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Ok(*boxed);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;mem&#x2F;fn.forget.html&quot;&gt;&lt;code&gt;std::mem::forget&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; basically just tells rust specifically not to run the destructor of the object you give it, therefore not freeing the memory. Here, we use it to make sure that &lt;code&gt;bytes&lt;&#x2F;code&gt; never gets freed. We don’t need to worry about the memory getting leaked because it then gets freed when &lt;code&gt;boxed&lt;&#x2F;code&gt; gets dropped. I’ve also added a &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;vec&#x2F;struct.Vec.html#method.shrink_to_fit&quot;&gt;&lt;code&gt;Vec::shrink_to_fit&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; call to ensure that the spare memory we likely allocated for the Vec doesn’t get lost.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;correction: the Vec’s allocation may be reused which would then be UB. Instead, use &lt;code&gt;bytes.leak()&lt;&#x2F;code&gt;&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ub&quot;&gt;UB?&lt;&#x2F;h3&gt;
&lt;p&gt;This all seems to work, but if we run it through &lt;code&gt;miri&lt;&#x2F;code&gt;, we can see that this is UB. Specifically: &lt;code&gt;error: Undefined Behavior: constructing invalid value: encountered an unaligned box (required 8 byte alignment but found 2)&lt;&#x2F;code&gt;, which happens when we create the &lt;code&gt;Box&lt;&#x2F;code&gt; with &lt;code&gt;Box::from_raw&lt;&#x2F;code&gt;. Here, we get to alignment issues. I briefly wrote about alignment earlier, and the part that matters here is that alignment is inherent to a specific struct. In fact, if we look at the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;alloc&#x2F;fn.alloc.html&quot;&gt;&lt;code&gt;alloc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;alloc&#x2F;fn.alloc.html&quot;&gt;&lt;code&gt;dealloc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; methods they take a &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;alloc&#x2F;struct.Layout.html&quot;&gt;&lt;code&gt;Layout&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which stores size and alignment, unlike C’s &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man3&#x2F;malloc.3.html&quot;&gt;&lt;code&gt;malloc&lt;&#x2F;code&gt; and &lt;code&gt;free&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which just take a size.&lt;&#x2F;p&gt;
&lt;p&gt;If we look at what behaviour is considered undefined (helpfully &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;reference&#x2F;behavior-considered-undefined.html&quot;&gt;linked&lt;&#x2F;a&gt; to me by &lt;code&gt;miri&lt;&#x2F;code&gt;), we can see (in the second item) that accessing a misaligned pointer is undefined behaviour. I’ll quickly explain for people coming from C the danger of undefined behaviour in Rust. In C, there are lots of behaviours that people use that aren’t specifically designated by the specification (like integer over&#x2F;under-flow) which are undefined behaviour. They’re mostly fine there, but Rust UB is a different beast entirely because of how heavily the compiler tries to optimise code. Generally in Rust, no UB is good UB, and if you wrote UB then the compiler reserves the right (and often will, especially in release builds) to do whatever the hell it wants regardless of your intentions. Here, it kinda works but in a larger program &lt;strong&gt;nobody&lt;&#x2F;strong&gt; can know what the compiler will do.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;correction&lt;&#x2F;strong&gt;: &lt;em&gt;C UB is also very very bad, and I think I just got confused between undefined behaviour and specification-undefined behaviour. the example I mentioned is also wrong - you can’t rely on signed integer over&#x2F;under-flow, especially in release builds&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;alignment&quot;&gt;Alignment&lt;&#x2F;h4&gt;
&lt;p&gt;To actually explain the issue, we need to look at the &lt;code&gt;Layout&lt;&#x2F;code&gt;’s of &lt;code&gt;Vec&lt;&#x2F;code&gt; and of &lt;code&gt;ExampleData&lt;&#x2F;code&gt;, which is easy because &lt;code&gt;Layout&lt;&#x2F;code&gt; implements &lt;code&gt;Debug&lt;&#x2F;code&gt; which means we can print it out to get all of its fields.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::alloc::Layout;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;print_layouts &lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Vec&amp;lt;u8&amp;gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, Layout::new&amp;lt;Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;());
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;ExampleData: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, Layout::new::&amp;lt;ExampleData&amp;gt;());
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which then outputs that they’re the same?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;:     Layout { size: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;24&lt;&#x2F;span&gt;&lt;span&gt;, align: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;8 &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;) }
&lt;&#x2F;span&gt;&lt;span&gt;ExampleData: Layout { size: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;24&lt;&#x2F;span&gt;&lt;span&gt;, align: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;8 &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;) }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;the-same&quot;&gt;The Same?&lt;&#x2F;h4&gt;
&lt;p&gt;This definitely stumped me for a while until I decided to have a look at the documentation &amp;amp; source for &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;vec&#x2F;struct.Vec.html&quot;&gt;&lt;code&gt;std::vec::Vec&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and then by clicking on &lt;em&gt;Source&lt;&#x2F;em&gt; I saw that it holds a &lt;code&gt;RawVec&lt;&#x2F;code&gt; buffer and the current length. I’ve added the definition below, simplified to remove the standard library shenanigans:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Vec&amp;lt;T, A: Allocator = Global&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: RawVec&amp;lt;T, A&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;RawVec&lt;&#x2F;code&gt; is a private class that &lt;code&gt;Vec&lt;&#x2F;code&gt; uses to wrap lots of the unsafe behaviours, and you can’t actually see it in any documentation. However, you can just click around in the source to find it &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;src&#x2F;alloc&#x2F;raw_vec.rs.html#51&quot;&gt;here&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;RawVec&amp;lt;T, A: Allocator = Global&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ptr&lt;&#x2F;span&gt;&lt;span&gt;: Unique&amp;lt;T&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cap&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;: A,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;alloc&lt;&#x2F;code&gt; is a zero-sized type, and then both &lt;code&gt;cap&lt;&#x2F;code&gt; and &lt;code&gt;ptr&lt;&#x2F;code&gt; have size &lt;code&gt;usize&lt;&#x2F;code&gt; which is 8 bytes. If we add up all of the bytes and check our alignments we can then see that yeah it’s 24 bytes with 8 byte-alignment.&lt;&#x2F;p&gt;
&lt;p&gt;To see where our alignment problem from earlier comes from, we have to dig into &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;src&#x2F;alloc&#x2F;vec&#x2F;mod.rs.html#1880&quot;&gt;&lt;code&gt;Vec::push&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: T) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.len == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;reserve_for_push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.len);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; end = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.len);
&lt;&#x2F;span&gt;&lt;span&gt;        ptr::write(end, value);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.len += &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can see that it checks for capacity (and reserves space if we don’t have enough which I’ll get to in just a second), and it then writes to a pointer with the new value. That call for reserving is on &lt;code&gt;self.buf&lt;&#x2F;code&gt;, which is the &lt;code&gt;RawVec&lt;&#x2F;code&gt; from earlier which handles all of the allocation so it’s probably &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;src&#x2F;alloc&#x2F;raw_vec.rs.html#301&quot;&gt;where&lt;&#x2F;a&gt; we want to be looking.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;reserve_for_push&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;handle_reserve&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;grow_amortized&lt;&#x2F;span&gt;&lt;span&gt;(len, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;grow_amortized&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;additional&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Result&amp;lt;(), TryReserveError&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    debug_assert!(additional &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;T::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;IS_ZST &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Err(CapacityOverflow.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; required_cap = len.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;checked_add&lt;&#x2F;span&gt;&lt;span&gt;(additional).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;ok_or&lt;&#x2F;span&gt;&lt;span&gt;(CapacityOverflow)?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cap = cmp::max(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.cap * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, required_cap);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cap = cmp::max(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MIN_NON_ZERO_CAP&lt;&#x2F;span&gt;&lt;span&gt;, cap);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; new_layout = Layout::array::&amp;lt;T&amp;gt;(cap);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;finish_grow&lt;&#x2F;span&gt;&lt;span&gt;(new_layout, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;current_memory&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.alloc)?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_ptr_and_cap&lt;&#x2F;span&gt;&lt;span&gt;(ptr, cap);
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;src&#x2F;alloc&#x2F;raw_vec.rs.html#393&quot;&gt;&lt;code&gt;handle_reserve&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; just deals with errors, and if we peer through &lt;code&gt;grow_amortized&lt;&#x2F;code&gt; which actually allocates (and strategically ignore the amortisation parts and just look for a &lt;code&gt;Layout&lt;&#x2F;code&gt;), we can see that it actually allocates using &lt;code&gt;Layout::array&amp;lt;T&amp;gt;(cap)&lt;&#x2F;code&gt;. If we then print out that layout (using the number of bytes we need for storing an &lt;code&gt;ExampleData&lt;&#x2F;code&gt; for the array size):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;print_layouts &lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; size = std::mem::size_of::&amp;lt;ExampleData&amp;gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Vec&amp;lt;u8&amp;gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, Layout::array::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(size).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;ExampleData: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, Layout::new::&amp;lt;ExampleData&amp;gt;());
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We get this out the other end - success! The alignment is different which then explains why our &lt;code&gt;Box&lt;&#x2F;code&gt; creation earlier was undefined behaviour.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;:     Layout { size: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;24&lt;&#x2F;span&gt;&lt;span&gt;, align: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) }
&lt;&#x2F;span&gt;&lt;span&gt;ExampleData: Layout { size: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;24&lt;&#x2F;span&gt;&lt;span&gt;, align: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;8 &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;) }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The obvious next question is whether there’s any way to convert between these two without copying (since that’s why we’ve gotten into this whole mess). That having been said, I’ll take a brief aside to explain how to do this if you’re OK with allocating another 24 bytes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;copying-again-but-without-copy-needed-nor-any-ub&quot;&gt;Copying again &lt;em&gt;(but without &lt;code&gt;Copy&lt;&#x2F;code&gt; needed nor any UB)&lt;&#x2F;em&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The following code (according to &lt;code&gt;miri&lt;&#x2F;code&gt; and my own gut feeling&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-6-1&quot;&gt;&lt;a href=&quot;#fn-6&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;) is unsafe, but sound (meaning that it doesn’t cause UB):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Ok(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; ptr = std::alloc::alloc(Layout::new::&amp;lt;ExampleData&amp;gt;());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; b in bytes {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ ptr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(b) };
&lt;&#x2F;span&gt;&lt;span&gt;        ptr = ptr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    ptr = ptr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sub&lt;&#x2F;span&gt;&lt;span&gt;(std::mem::size_of::&amp;lt;ExampleData&amp;gt;());
&lt;&#x2F;span&gt;&lt;span&gt;    *Box::from_raw(ptr as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut&lt;&#x2F;span&gt;&lt;span&gt; ExampleData)
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We create a pointer using &lt;code&gt;alloc&lt;&#x2F;code&gt; with the correct layout. We then write each byte and increment the address of the pointer each time. We then take the pointer back to the start and give it to a &lt;code&gt;Box&lt;&#x2F;code&gt; to be managed. That &lt;code&gt;Box&lt;&#x2F;code&gt; is then responsible for freeing the heap memory we allocated and we also use it to get the data out from the heap back to the stack. Don’t ask me how it does that - I can’t tell for the life of me. There’s probably a better way to do it, but I can at least say that this won’t cause memory leaks, memory corruption or compiler mayhem.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;is-there-a-no-copy-solution&quot;&gt;Is there a no-copy solution?&lt;&#x2F;h3&gt;
&lt;p&gt;As far as I can tell, there isn’t a way to tell the Rust compiler that we want to change the alignment of an existing allocation, which then means that (unless the struct has 1-byte alignment) there isn’t a way to do a no-copy solution which annoys me. If you work out a way of doing it - I’d love to hear it.&lt;&#x2F;p&gt;
&lt;p&gt;Unlike the first copying method which required the struct to be &lt;code&gt;Copy&lt;&#x2F;code&gt; and was UB unless the struct was packed, this doesn’t need that &lt;strong&gt;and&lt;&#x2F;strong&gt; as far as I can tell, it’s sound.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;heap-data&quot;&gt;Heap Data&lt;&#x2F;h2&gt;
&lt;p&gt;That’s all well and good, but what about Heap data like a &lt;code&gt;Vector&lt;&#x2F;code&gt; or a &lt;code&gt;String&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;By itself, you’d have to know at compile-time the type, but you could probably get away with just writing the contents of the pointer, and carefully reading them back. However, you’d have to be careful around cases where more space was allocated than used which would be annoying.&lt;&#x2F;p&gt;
&lt;p&gt;The main complications would come from if that heap data was stored inside a struct. You’d no longer be able to just pretend it was all just a series of bytes, and you’d have to put in lots of manual work to not accidentally just write a memory address that would become invalid the second the program finished&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-7-1&quot;&gt;&lt;a href=&quot;#fn-7&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and to read back the correct number of bytes. At that point, you’re better off just using something like &lt;a href=&quot;https:&#x2F;&#x2F;protobuf.dev&#x2F;&quot;&gt;&lt;code&gt;protobuf&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; or &lt;code&gt;serde&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing Thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;Whilst yes, this does work I would never recommend it for any production use where you couldn’t control it &lt;em&gt;very&lt;&#x2F;em&gt; finely. The main problem comes from what I briefly mentioned earlier about the Rust ABI not being stable. If the compiler updates, even if you don’t change your code, the in-memory representation of your struct could change and then you’d never have any way of recovering that written data other than downgrading your compiler version to ‘before it broke’. I’d also be careful about manually writing bytes by hand instead of outputting an existing struct - Rust does some really interesting optimisations which could lead to bit patterns being something completely different to what you expected - like &lt;code&gt;Option&amp;lt;bool&amp;gt;&lt;&#x2F;code&gt; which only takes 1 byte. It’s also undefined behaviour for certain types to be in invalid bit states (eg. 0x0 and 0x1 are fine for a &lt;code&gt;bool&lt;&#x2F;code&gt;, but 0x3 is invalid) because they’re often used for those optimisations.&lt;&#x2F;p&gt;
&lt;p&gt;As to why the UB never actually caused any issues, I’ve not a clue. There’s probably someone who could explain more but I’m not that person. Reading padding is undefined behaviour, and I couldn’t say why it didn’t cause any issues here.&lt;&#x2F;p&gt;
&lt;p&gt;Whilst you could make arguments around the use of &lt;code&gt;#[repr(C)]&lt;&#x2F;code&gt; to safeguard against this, there’s another problem - there’s no description of what this data is if anyone’s poking around the filesystem. Most file formats start with something to mark what format they are, but there’s nothing here if you’re trying to read data later. Even if you don’t go as far as to use a self-describing format like &lt;code&gt;JSON&lt;&#x2F;code&gt;, most serialisation methods (as far as I can tell) at least make it clear that they’re storing data. With this, unless you’re a rare programmer who actually writes thorough documentation, I can’t even tell if its a binary or a file.&lt;&#x2F;p&gt;
&lt;p&gt;I’ll finish off by saying that this article was also a bit &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Not_invented_here&quot;&gt;NIH&lt;&#x2F;a&gt; and if you want to actually do things like this, I’d have a gander at &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;bytemuck&quot;&gt;&lt;code&gt;bytemuck&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Anyways, that was fun to explore and try and get a better knowledge of UB and binary formats. Enjoy the new year!&lt;&#x2F;p&gt;
&lt;p&gt;Full final code can be viewed &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;BurntNail&#x2F;b46b5ecc65d5fdfb9097de2d01ad1966&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;errata&quot;&gt;&lt;em&gt;errata&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I posted a link to this on the subreddit &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;1913hsh&#x2F;some_fun_adventures_ive_had_in_ub_and_internal&#x2F;&quot;&gt;here&lt;&#x2F;a&gt; and received some comments - here are my responses.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;u-dkopgerpgdolfg&quot;&gt;u&#x2F;dkopgerpgdolfg&lt;&#x2F;h3&gt;
&lt;p&gt;This user pointed out one thing which makes me feel like a fool - if we know the length of our struct beforehand (which we do - it’s &lt;code&gt;std::mem::size_of::&amp;lt;ExampleData&amp;gt;()&lt;&#x2F;code&gt;), we can just read straight into the pointer:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_in_straight_to_pointer &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;file_name&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; std::io::Result&amp;lt;Option&amp;lt;ExampleData&amp;gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STRUCT_SIZE&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;= std::mem::size_of::&amp;lt;ExampleData&amp;gt;();
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LAYOUT&lt;&#x2F;span&gt;&lt;span&gt;: Layout = Layout::new::&amp;lt;ExampleData&amp;gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; ptr = std::alloc::alloc(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LAYOUT&lt;&#x2F;span&gt;&lt;span&gt;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;create a pointer to the heap struct
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; bytes_read_total = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;create a counter for how many bytes we&amp;#39;ve written - this is like the `len` of a Vec, where `STRUCT_SIZE` is the `cap`
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; reader = File::open(file_name)?; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;open a file
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; tmp = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;32&lt;&#x2F;span&gt;&lt;span&gt;]; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;create a stack for temporary reads - very little performance impact
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; reader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; tmp)? {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                n =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; n = n.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;min&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STRUCT_SIZE &lt;&#x2F;span&gt;&lt;span&gt;- bytes_read_total); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;ensure we don&amp;#39;t write past the memory we allocated
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..n {
&lt;&#x2F;span&gt;&lt;span&gt;                        ptr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(tmp[i]);
&lt;&#x2F;span&gt;&lt;span&gt;                        ptr = ptr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;                    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;              bytes_read_total += n;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; bytes_read_total == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STRUCT_SIZE &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;if there&amp;#39;s more to read, we don&amp;#39;t care
&lt;&#x2F;span&gt;&lt;span&gt;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;                    }
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; bytes_read_total &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STRUCT_SIZE &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            std::alloc::dealloc(ptr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LAYOUT&lt;&#x2F;span&gt;&lt;span&gt;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;if we didn&amp;#39;t read enough, then we need to remember to deallocate the block, as Rust won&amp;#39;t do it for us
&lt;&#x2F;span&gt;&lt;span&gt;            Ok(None)
&lt;&#x2F;span&gt;&lt;span&gt;        } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            ptr = ptr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STRUCT_SIZE&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;            Ok(Some(*Box::from_raw(ptr as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut&lt;&#x2F;span&gt;&lt;span&gt; ExampleData)))
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I’ve also added corrections from them in the rest of the article relating to alignment, leaking the vec and C undefined behaviour.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;u-hniksic&quot;&gt;u&#x2F;hniksic&lt;&#x2F;h3&gt;
&lt;p&gt;I’ve added corrections relating to C undefined behaviour.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-0&quot;&gt;
&lt;p&gt;At least, interesting to me ;) &lt;a href=&quot;#fr-0-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;and some semblance of a structure for you delightful readers. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;That is, they’re all in memory in one place without any pointers or memory addresses. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;That is, duckduckgo-ing for StackOverflow. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;That is, I didn’t realise this properly until I’d written far more of this article (the future bits are also super interesting). If you’ve read more of the article, this is why: if you pack the struct the alignment becomes 1 byte (because of the &lt;code&gt;u8&lt;&#x2F;code&gt;), which then means that it has the same alignment as the vec which makes the initial solution (using &lt;code&gt;Box::from_raw&lt;&#x2F;code&gt; with the &lt;code&gt;bytes.as_mut_ptr() as *mut ExampleData&lt;&#x2F;code&gt;) not unsound any more. &lt;a href=&quot;#fr-4-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;When the Rust vector reallocates, it doesn’t just add one to the capacity, it goes up in a pattern which is designed to amortise the allocation cost to be as low as possible. Because the &lt;code&gt;Box&lt;&#x2F;code&gt; only knows about the length, it won’t know to free the memory that’s in the &lt;code&gt;capacity&lt;&#x2F;code&gt; but not the &lt;code&gt;length&lt;&#x2F;code&gt;; &lt;a href=&quot;#fr-5-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-6&quot;&gt;
&lt;p&gt;100% correct 60% of the time &lt;a href=&quot;#fr-6-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-7&quot;&gt;
&lt;p&gt;Technically, you could modify the &lt;code&gt;ExampleData&lt;&#x2F;code&gt; from this post with any number of heap-based structures and it might still work. If the memory allocator didn’t de-allocate between you writing out the data (and dropping the old struct), and reading the memory address back I think it’d work? The problem would come from if you wrote on one run and read on another because that memory that it’s pointing to would no longer exist. &lt;a href=&quot;#fr-7-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>Comparative Thoughts on University Admissions</title>
          <pubDate>Mon, 18 Dec 2023 00:00:00 +0000</pubDate>
          <author>Jack Maguire</author>
          <link>https://maguire.tech/ramblings/us-and-uk-unis/</link>
          <guid>https://maguire.tech/ramblings/us-and-uk-unis/</guid>
          <description xml:base="https://maguire.tech/ramblings/us-and-uk-unis/">&lt;p&gt;As of writing (the 16th of December), I’ve just got back my MIT results - a deferral (which in this case means waiting until Pi Day for a more concrete result&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-0-1&quot;&gt;&lt;a href=&quot;#fn-0&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;). I’m now pretty confident in my thoughts on both systems of admissions, so to wait out the time I’ll be writing out my thoughts on their pros and cons. I might’ve briefly mentioned these in my &lt;a href=&quot;https:&#x2F;&#x2F;maguire.tech&#x2F;ramblings&#x2F;mit-interview&#x2F;&quot;&gt;other&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;maguire.tech&#x2F;ramblings&#x2F;cambridge-admissions&#x2F;&quot;&gt;two&lt;&#x2F;a&gt; blogs on University admissions, but this’ll be one place for what I wrote there in comparison &amp;amp; much more. If you haven’t read the other two and aren’t familiar with the admissions systems I’d recommend doing so - there’ll be things that I’ll be referencing without explaining.&lt;&#x2F;p&gt;
&lt;p&gt;As per usual, I’ll also mention that this post has my usual biases - I’ve been applying to a small number of highly selective universities from a position of relative privilege, so you’re experiences might have been different. I’ll try and vaguely organise it on the different stages of the admissions processes, but prepare for tangents 😉. I’ll also add that I probably didn’t perform as well on my admissions tests as I would’ve wanted to, which probably somewhat sours my opinion.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;essays&quot;&gt;Essays&lt;&#x2F;h2&gt;
&lt;p&gt;For MIT &amp;amp; Caltech, I’ve had to write a number of different essays that are all relatively short&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; which have been from a variety of prompts ranging from how I feel about their values to how I’ve helped and been helped by my community to why I want to study Computer Science. The main result of this is that students end up having to write &lt;strong&gt;a lot&lt;&#x2F;strong&gt; of essays, which I’ve heard can be incredibly draining. I’ve been somewhat insulated from this by limiting my US Admissions to only 2 universities, but I don’t really want to imagine what it must be like for the people applying to 20+ universities&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Whereas in the UK System, you only write 1 essay (known as the &lt;em&gt;Personal Statement&lt;&#x2F;em&gt;) about yourself. 4000 characters over 47 lines&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; with no prompt. UCAS &amp;amp; &lt;em&gt;The Universities&lt;&#x2F;em&gt; expect you to write about why you want to go for the course you’ve applied for, why you’d be good at that, why you’d be good for them and anything else interesting about you.&lt;&#x2F;p&gt;
&lt;p&gt;So here I’m pretty split. The US Essays seemed to care more about me as a person (which fits as you seem to mostly apply for a University rather than a Course) whereas my Personal Statement ended up being full of academics and waffle about how the I enjoyed the subjects I’m doing and how well they would transfer. That having been said, I got across most of what I wanted in my Personal Statement, and more of the struggle was getting it inside the character limit, rather than trying to examine my life with a microscope. I’ll also say that I think my Personal Statement came out better, purely because I could invest more time into it - it went through 11 drafts if I recall correctly because it was going to all of my UK Universities, whereas my MIT essays got far fewer drafts and so will my Caltech essays because there are more of them that go to fewer places.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;admissions-tests-grade-requirements&quot;&gt;Admissions Tests &amp;amp; Grade Requirements&lt;&#x2F;h2&gt;
&lt;p&gt;MIT &amp;amp; Caltech both take very different approaches here - MIT is test-mandatory, which means that as well as your recommendations, essays &amp;amp; general performance you need to complete either the &lt;a href=&quot;https:&#x2F;&#x2F;www.act.org&#x2F;content&#x2F;act&#x2F;en.html&quot;&gt;ACT&lt;&#x2F;a&gt; or the &lt;a href=&quot;https:&#x2F;&#x2F;satsuite.collegeboard.org&#x2F;sat&quot;&gt;SAT&lt;&#x2F;a&gt;. The idea here seems to be that they can get a standardised test performance metric for all students applying&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. One interesting difference is that you can take more than one SAT or ACT and &lt;em&gt;‘superscore’&lt;&#x2F;em&gt; them which means to take your best scores from each portion of the tests you’ve completed (eg. I can take a 36 in Science from my September sitting and a 35 in Maths from my November sitting), which I guess allows for if students have bad days? There are two ways of discouraging students from taking endless tests - the fact that they’re insanely expensive (my last ACT test was $171.50)&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; &amp;amp; the fact that the universities see all the tests that you submit, which makes it rather obvious. I ended up having the luxury to take two. Caltech is test-blind, which just means that they won’t even look at tests if you have submitted them.&lt;&#x2F;p&gt;
&lt;p&gt;Whereas, in the UK you get predicted grades from your teachers based on what they think your performance in your final exam will be. Those then go to all the universities, which makes it simple. Different schools work differently for how lenient they are with students requesting to go for higher grades. The way that schools are discouraged from giving everyone higher grades is that that tactic will only work for one year, as the universities &lt;em&gt;supposedly&lt;&#x2F;em&gt; keep records of how accurate the different schools are. You also must apply through your school so you can’t really get around it.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly enough, there are parts I do like and don’t about both systems - here are the UK Advantages:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;All courses at all universities post minimum grade requirements&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-6-1&quot;&gt;&lt;a href=&quot;#fn-6&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, so there isn’t much faffing around with applying to universities you know you can’t get into. This is in opposition to the US system, where at best I have the middle 50% from MIT and have to guess if I’m good enough.&lt;&#x2F;li&gt;
&lt;li&gt;In my humble opinion there’s less possibility for rich people just taking more and more tests to get the grades they want (ignoring the possibility of bribery&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-7-1&quot;&gt;&lt;a href=&quot;#fn-7&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Here, you’re also being evaluated on more long-term performance - it might just be a problem for me applying to both systems at the same time (and slightly prioritising the UK due to higher acceptance chances at my choices as well as the other advantages that come with going to university domestically&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-8-1&quot;&gt;&lt;a href=&quot;#fn-8&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;) I haven’t had as much time to revise for my ACTs but I feel that my Predicteds are more accurate.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And then the US:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The idea of evaluating student performance and potential for application to a pretty big university without any test scores (except for transcript related&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-9-1&quot;&gt;&lt;a href=&quot;#fn-9&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;) is pretty nice sounding to me.&lt;&#x2F;li&gt;
&lt;li&gt;A-Level &amp;amp; IB Exam Seasons are generally known to be a pretty hellish time of year for all involved - at my school the entire time between maybe mid-late February and July is all spent either revising, taking practice tests or taking actual papers. Its mixed as to whether it’s in school or out of school, but normally A-Level out-of-school revision &amp;amp; taking the exams is about a month and a half. As far as I can see, during this time at US High Schools you don’t do all that much?&lt;&#x2F;li&gt;
&lt;li&gt;Whilst I’m not 100% sure about the entrance tests, I can definitely see that they are standardised which I most definitely can’t say about teachers who might be deciding your grades.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Interesting systems across both sides of the pond there, and I’m really not sure which I prefer. Any preference I show for the UK is probably tinted by me just going with the devil I know over the devil I don’t.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;interviews&quot;&gt;Interviews&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve spoken &lt;em&gt;extensively&lt;&#x2F;em&gt; about interviews on both sides, so my opinion will be far shorter and simpler.&lt;&#x2F;p&gt;
&lt;p&gt;US wins, flat-out. I get that the competitive UK Universities want an idea of aptitude rather than just accomplishment for their courses due to rampant grade inflation&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-10-1&quot;&gt;&lt;a href=&quot;#fn-10&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, but I feel that the US one went better because it wasn’t as stressed. In the Cambridge interview I had, I could see that the interviewers had far more candidates than time and needed to get going. Part of that is also influenced by the setting - my US one was in a nice coffee shop (Gails&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-11-1&quot;&gt;&lt;a href=&quot;#fn-11&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; vibes at a lower cost) and my UK one was over a zoom&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-12-1&quot;&gt;&lt;a href=&quot;#fn-12&quot;&gt;13&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; which stressed me out because of the eternally-present technical issues which even a Computer Science applicant can’t overcome.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;application-structure&quot;&gt;Application Structure&lt;&#x2F;h2&gt;
&lt;p&gt;Here, the UK wins although it is a smaller country which probably makes it easier.&lt;&#x2F;p&gt;
&lt;p&gt;All applications here are handled through &lt;a href=&quot;https:&#x2F;&#x2F;www.ucas.com&#x2F;&quot;&gt;UCAS&lt;&#x2F;a&gt; - you can’t apply without using it. That only means one essay, one place to dump scores, one place to add admin details, one place to look for offers which reduces lots of the overhead from US&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-13-1&quot;&gt;&lt;a href=&quot;#fn-13&quot;&gt;14&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and one place to pay a relatively small cost (£20 for one university, or £25 for multiple) for applications. This is less cognitive load, and only one email address to have a heart attack about when you see it (&lt;code&gt;track@ucas.ac.uk&lt;&#x2F;code&gt; if you’re interested, and as far as I can tell this is used &lt;em&gt;exclusively&lt;&#x2F;em&gt; for offers which is convenient).&lt;&#x2F;p&gt;
&lt;p&gt;As opposed to the US where there are lots of different systems which means inputting my personal details in lots of times which isn’t too bad for 2 universities but I could imagine this getting pretty annoying. The fees are also way higher - to apply to &amp;gt; 13 US Universities (which doesn’t seem too high as far as I can tell), you’re looking at $1000 (going off a cost of $75, which is the MIT cost).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;receiving-results&quot;&gt;Receiving Results&lt;&#x2F;h2&gt;
&lt;p&gt;US Universities have specific timestamps for applications decisions (eg. MIT Early Action this year was the 16th of December at 12:16PM Boston time), and I think all the Oxford and Cambridge colleges follow this with their own timings. The rest of the UK Universities (for the most part), just release their results to you whenever they decide. There isn’t really even a proper deadline - if they don’t respond before the first of May then it just counts as a rejection 🤷.&lt;&#x2F;p&gt;
&lt;p&gt;There’s advantages and disadvantages either side, but I think the UK wins out. I was pretty stressed about my MIT decision from when I could become stressed about it although it turns out there is a limit to the number of things I can simultaneous stress out about&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-14-1&quot;&gt;&lt;a href=&quot;#fn-14&quot;&gt;15&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;! This ended up being after my Cambridge Interview. I had a look at their history and made a little spreadsheet and managed to successfully predict the date&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-15-1&quot;&gt;&lt;a href=&quot;#fn-15&quot;&gt;16&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. That having been said, at least after that date I could theoretically know for final&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-16-1&quot;&gt;&lt;a href=&quot;#fn-16&quot;&gt;17&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;? On the other hand, since you have no idea when your UK decisions are coming in, you can theoretically convince your brain to forget and focus on revision, but this does mean that you can’t plan for a nice place to possibly receive a rejection - you just have to politely excuse yourself and hope for the best.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing Thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;Since this whole post was just an extended set of closing thoughts for the other university posts, you aren’t going to get much more out of me here. Both systems seem to have their advantages and disadvantages but I’ve been talking about this wrong. I kinda don’t really get any choice in this matter and just have to go with whatever university I want to apply to says. Regardless, in the off chance that any admissions officers read this&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-17-1&quot;&gt;&lt;a href=&quot;#fn-17&quot;&gt;18&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; (in which case, thanks for getting to the end!), feel free to take anything or nothing. I think I’ve been speaking about this enough in person, and this was a lovely chance to get to just dump the contents of my brain and get focused on revision for my A-Level Mocks.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-0&quot;&gt;
&lt;p&gt;The odds aren’t great though - I think last year it was 146 admitted out of 7892 deferred, which is &amp;lt; 2%. &lt;a href=&quot;#fr-0-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Mostly maxing out at around 250 words, except for the Common App longer essay question. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;This is one small benefit of UCAS imho - you are limited to 5 which somewhat reduces the admin work required to keep up with admissions. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;Why 47? What is a line? idk ask UCAS it just happened to all work out for me. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;How do they score ACT vs SAT? Not a clue, but I’d be interested to know. &lt;a href=&quot;#fr-4-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;University applications favouring the wealthy? Never! &lt;a href=&quot;#fr-5-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-6&quot;&gt;
&lt;p&gt;As well as information on how those get reduced for Circumstantial Offers. &lt;a href=&quot;#fr-6-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-7&quot;&gt;
&lt;p&gt;If we allow bribery, then both systems get messed up so I’m ignoring that possibility - this is my blog post I can do what I want ^_^. &lt;a href=&quot;#fr-7-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-8&quot;&gt;
&lt;p&gt;And I’ll be honest, there are plenty of advantages ranging from being able to see my friends &amp;amp; family more often, not having to worry about visas as well as the fact that going to university in the US will probably be around 5-6x more expensive. &lt;a href=&quot;#fr-8-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-9&quot;&gt;
&lt;p&gt;Which in my case, is just predicted grades + GCSE scores. &lt;a href=&quot;#fr-9-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-10&quot;&gt;
&lt;p&gt;One of the few areas I disagree with the grade requirements - frankly for the top universities they aren’t realistic. Technically, I’ve applied to universities that are below by multiple grades what I had predicted, but realistically I’ll be lucky to get 3 or 4 offers including my insurance. Again though, I’m applying to highly competitive universities which might mean that my experience is different. &lt;a href=&quot;#fr-10-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-11&quot;&gt;
&lt;p&gt;Relatively posh british bakery&#x2F;coffee shop chain - the food is expensive but I’ve never had any other cinnamon rolls that come even close. &lt;a href=&quot;#fr-11-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-12&quot;&gt;
&lt;p&gt;I 100% get the reason they do this (make it easier for people who can’t get to Cambridge), but I still would have loved to visit in person. &lt;a href=&quot;#fr-12-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-13&quot;&gt;
&lt;p&gt;Yes, I’m aware of the &lt;a href=&quot;https:&#x2F;&#x2F;www.commonapp.org&#x2F;&quot;&gt;Common App&lt;&#x2F;a&gt;, and other such coalitions but they don’t cover &lt;em&gt;every&lt;&#x2F;em&gt; university. &lt;a href=&quot;#fr-13-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-14&quot;&gt;
&lt;p&gt;&lt;em&gt;at least consciously stress about, I fear for my heart.&lt;&#x2F;em&gt; &lt;a href=&quot;#fr-14-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-15&quot;&gt;
&lt;p&gt;The pattern for EA seems to be the saturday of the second full week (beginning Monday). &lt;a href=&quot;#fr-15-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-16&quot;&gt;
&lt;p&gt;&lt;em&gt;unless you get waitlisted, in which case it’s another three months yay!11!!!11!! (although I did bring this upon myself by applying earlier, and this is also definitely better than a straight rejection)&lt;&#x2F;em&gt; &lt;a href=&quot;#fr-16-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-17&quot;&gt;
&lt;p&gt;This is all going on my MIT &lt;a href=&quot;https:&#x2F;&#x2F;mitadmissions.org&#x2F;apply&#x2F;firstyear&#x2F;february-updates-notes-form&#x2F;&quot;&gt;FUN Form&lt;&#x2F;a&gt;, so the chances are non-zero I guess? &lt;a href=&quot;#fr-17-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>The British Uni Admissions Experience</title>
          <pubDate>Thu, 07 Dec 2023 00:00:00 +0000</pubDate>
          <author>Jack Maguire</author>
          <link>https://maguire.tech/ramblings/cambridge-admissions/</link>
          <guid>https://maguire.tech/ramblings/cambridge-admissions/</guid>
          <description xml:base="https://maguire.tech/ramblings/cambridge-admissions/">&lt;p&gt;I’ve recently finished my Cambridge interview and I’ll now make a vague attempt to document my experience, trials and tribulations. For reference, I applied for &lt;a href=&quot;https:&#x2F;&#x2F;www.undergraduate.study.cam.ac.uk&#x2F;courses&#x2F;computer-science&quot;&gt;Computer Science&lt;&#x2F;a&gt; to &lt;a href=&quot;https:&#x2F;&#x2F;www.chu.cam.ac.uk&#x2F;&quot;&gt;Churchill College&lt;&#x2F;a&gt;. This’ll probably end up following a similar structure to &lt;a href=&quot;https:&#x2F;&#x2F;maguire.tech&#x2F;ramblings&#x2F;mit-interview&#x2F;&quot;&gt;my MIT Post&lt;&#x2F;a&gt;. This is also specifically for the 2023-2024 admissions cycle, as apparently a few things are changing next year for the Personal Statement as well as the Admissions Tests.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-uk-system&quot;&gt;The UK System&lt;&#x2F;h2&gt;
&lt;p&gt;The UK System is so very different to the US System, so I’ll begin by giving a not-so-brief explanation of how our admissions processes work. I’ll begin by explaining school years, to eventually get to the important years for this discussion.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gcses-and-below&quot;&gt;GCSEs and Below&lt;&#x2F;h3&gt;
&lt;p&gt;In the UK, most people class schools into independent schools and state schools. Independent schools are typically selective and fee-paying, and state schools are paid for by the government and have free enrolment. Then, within state schools there’s the normal ones as well as &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Grammar_school&quot;&gt;Grammar Schools&lt;&#x2F;a&gt;, which are more selective but hard to get into due to the high demand. Then, independent schools can be classed in a number of ways - day schools vs boarding schools (all boarding schools are independent as far as I know), public vs private, or even by how expensive the fees are. Quick fun fact - a Public School in the UK is very different to a Public School internationally. Public Schools (as a group noun) refer to a set of schools that were originally open to students regardless of their parents’ jobs. Nowadays, this refers to a set of elite independent schools (like Eton or Harrow) that typically take children very young and continue on until they reach university age. &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Public_school_(United_Kingdom)&quot;&gt;See Wikipedia&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Most children start in reception aged 4 for a single year. Then mandatory school starts for everyone at a primary school for Years 1 through 6 where students are aged 5 through 11. They then go to secondary school for Years 7 through 11 aged 11 through 16. That having been said, the private school system can be different and they often take in children at a variety of ages - I’ve been at my current school since Year 3 and I’ll be leaving at the end of this year at the end of Year 13.&lt;&#x2F;p&gt;
&lt;p&gt;Usually for Year 9 and below, most end-of-year exams don’t contribute to much other than academic streaming for the next year or reports (with the exception of standardised tests at state schools, but I don’t know much about them). Once you get past Year 9, you typically then start directly working on your GCSE (General Certificate of Secondary Education) courses.&lt;&#x2F;p&gt;
&lt;p&gt;There are 3 compulsory subjects - Maths, English &amp;amp; Science. Maths is worth 1 GCSE, Science 2 (double award of 3 sciences), and English 2 (separate qualifications for Language and Literature). Typically though, students take more than just 5 GCSEs and will often take more subjects like languages, more complicated Maths or Science courses and different humanities&#x2F;creatives&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-0-1&quot;&gt;&lt;a href=&quot;#fn-0&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. These are rated 9-1 and theoretically a 9 is supposed to be the equivalent of an A** (with the below grades following like the traditional letters - 8 = A*, 7 = A, 6 = B etc), but grade inflation has impacted that to the point where you’ll hear about independent school students achieving 12 or even more 9s.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sixth-form&quot;&gt;Sixth Form&lt;&#x2F;h3&gt;
&lt;p&gt;After your GCSEs, there’s no requirement from the government for you to take any further education. You can’t just be unemployed at 17 if you’re filthy rich - you have to work a job, or get an apprenticeship but you don’t need to stay in school. However just over half&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; of students go to a Sixth Form&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; college (Called either Year 12 &amp;amp; Year 13 or Lower Sixth &amp;amp; Upper Sixth, but always Sixth Form as a collective for ages 16-18).&lt;&#x2F;p&gt;
&lt;p&gt;Most students in the Sixth Form study either A-Levels or IB Exams&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. A-Levels are separate examinations by separate boards and typically take around 2 years to complete. Most students take 3 or 4, but in some rare cases at top schools people take 5. There are zero requirements on variety of which exams you have to and don’t have to take, which means that there’s a huge variety so schools will likely offer a subset of the possible exams in common subjects. IB Exams are all set and managed by the International Baccalaureate Organisation, and they set strict requirements on subjects - you have to take at least 1 Science, 1 Mathematical Subject, 1 English Subject, 1 Language &amp;amp; 1 other Humanity. The IB Diploma also has a large emphasis on coursework (internal assessments in every subject, an extended essay, and a &lt;em&gt;Theory of Knowledge&lt;&#x2F;em&gt; exhibition) When you leave Sixth Form, the only things that stay on your record are the grades you achieved - the individual tests you took don’t matter beyond a desire for personal excellence and there’s no concept of a &lt;a href=&quot;https:&#x2F;&#x2F;www.timeshighereducation.com&#x2F;student&#x2F;advice&#x2F;what-gpa&quot;&gt;GPA&lt;&#x2F;a&gt;. When I’ve been doing US Applications and been learning more about their admissions system, the concept of a GPA terrifies me - every single test and assignment I do going to a number that goes to university? The stress must be unreal.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;applications-offers&quot;&gt;Applications&#x2F;Offers&lt;&#x2F;h2&gt;
&lt;p&gt;Most UK universities have a very similar process for admissions for most subjects. Here I’ll be going over a general overview with a few exceptions that I’ve become familiar with, but for example I won’t be touching Medicine with a 10-foot pole.&lt;&#x2F;p&gt;
&lt;p&gt;All of the UK Universities work through one system for undergraduate applications - the Universities and Colleges Admissions Service, commonly known as &lt;a href=&quot;https:&#x2F;&#x2F;www.ucas.com&#x2F;&quot;&gt;UCAS&lt;&#x2F;a&gt;. To submit an application through UCAS, you need to register through your school where the following items go onto your application (because they need to submit certain things, which I’ll get onto). Then, you need to submit the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Admin Details - these are simple details like where you live, your residency status and any widening access points.&lt;&#x2F;li&gt;
&lt;li&gt;Banking Details - the UCAS application costs £20 for one choice, or £25 for multiple. I just selected to have my centre pay, which means that it’ll end up on my school bill.&lt;&#x2F;li&gt;
&lt;li&gt;Personal Statement (this is one 4000 character essay about why you want to study that subject. You can take this any way you want, and I’m not going to provide advice because there are far better people to do that.)&lt;&#x2F;li&gt;
&lt;li&gt;Your 5 Choices. You get to choose up to 5 courses to go to - you could pick 5 courses at one university, 5 courses at 5 universities or any combination. There aren’t too many restrictions beyond the fact that you’re not allowed to simultaneously apply to Oxford &amp;amp; Cambridge (collectively known as Oxbridge), and you’re not allowed to apply to more than 4 medicine courses.&lt;&#x2F;li&gt;
&lt;li&gt;Your reference - typically your teachers write &amp;amp; submit this. Typically there’s a small level of collaboration between the reference writer and the student to make sure you the reference doesn’t overlap with the personal statement, although this is strictly at the start and should not influence the writer.&lt;&#x2F;li&gt;
&lt;li&gt;Your Predicteds or Achieved Grades. If you’ve already done your exams, then you just submit the actual grades, and if not then you submit your predicted grades.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;choosing-universities&quot;&gt;Choosing Universities&lt;&#x2F;h3&gt;
&lt;p&gt;There’s a huge variety of different ways to choose a university. First, you might look at the course you want to do (Computer Science for me) and check which universities offer it. There’s a huge number of different league tables which all prioritise different things. All universities are also required to post their minimum grade offers for all their different courses which can help to see if a university is above or below your standards if you compare that to your predicteds. However, sometimes there are other factors to consider (like the prestige of a university - Edinburgh lists A*A*A* for Computer Science, but is easier to get into than Cambridge which lists A*A*A). Most also offer contextual offers, which are for if you’re disadvantaged in some ways compared to your peers - this could be anything from grief affecting your performance to being underprivileged.&lt;&#x2F;p&gt;
&lt;p&gt;Then, when you’ve narrowed it down to a shortlist you’ll typically go to an Open Day. These are a few days a year that each university offers, where they’ll have lots of talks on about everything from the Student Union&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; to your course to accommodation. Most universities also offer individual tours around the year, but the open days typically offer more things as well as conveniences like more bus services between the local rail station and the university. If you know you’d want to visit a specific university, make sure to book their open day early - I think lots of the nicer slots for the St Andrews one were booked out only a few hours after it opened to booking.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;predicted-grades&quot;&gt;Predicted Grades&lt;&#x2F;h3&gt;
&lt;p&gt;Some people from outside the UK might’ve been reading this so far somewhat confused - you just apply with one essay and one reference? How do they know about your academic skills apart from GCSEs?&lt;&#x2F;p&gt;
&lt;p&gt;What happens in most schools is that at the end of your Lower Sixth, you take a set of internal exams (as in, not set by any exam board) which your teachers then use (in addition to your performance from the rest of the year, or things like coursework) to provide an estimate of what you’ll get in your final exams. Some schools use AS Levels for this purpose, which are designed to be taken at this point.&lt;&#x2F;p&gt;
&lt;p&gt;If you disagree then you can usually ask your teachers to change your grades, but the school has a vested interest in making sure that your grades are accurate. This is because the universities can see which school you applied from, and if schools consistently overpredict then the universities (theoretically) should remember and then discount those school’s opinions. The problem then occurs when somebody actually deserves the high prediction, but might not get the offer they want because of the traditional overestimations from that school.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;offers&quot;&gt;Offers&lt;&#x2F;h3&gt;
&lt;p&gt;Then, you submit your UCAS Application - the deadline&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; is the 31st of January, but my school set a far earlier internal deadline. The idea of that was that you’re stressing out about making a deadline that’s months before the actually important one so if you can’t make the deadline an extension isn’t an issue.&lt;&#x2F;p&gt;
&lt;p&gt;Then, the universities must reply to you by the 1st of May. They have 2 options - rejection or offer. If you’re rejected, then you won’t be going to that university. Typically, you can’t ask for feedback. Offers are slightly more complicated - if you’ve applied the year after you did your A-Levels, they’ll give an unconditional offer. If you’ve applied before finishing you’re A-Levels using your predicted grades, then they’ll give a conditional offer which will almost always be at or below your predicted grades and often similar to the minimum grades that they post.&lt;&#x2F;p&gt;
&lt;p&gt;Then, you’ve got 2 weeks to decide on your firm and insurance offers. You’ve got to pick 2 universities from the ones that replied to you - if you meet the grade requirements from your firm and want to go to university that year, then you can only go to that university. If you don’t meet those ones, but do meet the requirements for your insurance then you can only go there. If you meet neither, then you can either give up to apply the next year, or you can enter clearing. I don’t know much about clearing, but it seems to be where all students who want to can enter Clearing as a process, and then universities pick the students they want. Typically, the top universities don’t consider any applicants from clearing.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-brief-aside-on-accommodation&quot;&gt;A brief aside on Accommodation&lt;&#x2F;h3&gt;
&lt;p&gt;Almost all UK universities offer some form of accommodation in the first year - often in Halls of Residence, which can be self-catered, catered, co-ed, sharing, single and prices will change accordingly. Most of the time there’ll be a selection of Halls which have different &lt;em&gt;features&lt;&#x2F;em&gt; like what I mentioned above. THe notable exception is Durham with the colleges system (which I’ll elaborate more on later with the Cambridge stuff). Some universities restrict this to only be guaranteed accommodation if you apply with them as your firm choice.&lt;&#x2F;p&gt;
&lt;p&gt;Beyond the first year, you either have to submit an application to the few spaces not taken by first-years&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-6-1&quot;&gt;&lt;a href=&quot;#fn-6&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; or take a chance with the rental market which is pretty bad at lots of universities (London is especially bad at this - one of the main reasons I didn’t apply to Imperial&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-7-1&quot;&gt;&lt;a href=&quot;#fn-7&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;). The notable exception is Oxbridge, where almost all colleges offer accommodation to all undergraduates on-site although there’s nothing stopping you from renting if you see a lovely place or already have property in Cambridge&#x2F;Oxford.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cambridge-specific&quot;&gt;Cambridge-Specific&lt;&#x2F;h2&gt;
&lt;p&gt;Here, we get into the incredibly specific. So far, I’ve tried to make sure that this is pretty widely applicable, but here we’re going into detail on my specific application. I’ll go more and more specific as it goes on.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-colleges&quot;&gt;The Colleges&lt;&#x2F;h3&gt;
&lt;p&gt;Unlike every other university, you don’t just apply to Oxford or Cambridge - you apply to a specific college in your application. As far as I can tell, your supervisors and some of your professors will be from the college you applied to. There’s sports teams and societies which are college specific and for the whole university. One joked about bonus about going to Oxbridge is that you’ve got a higher chance of getting on &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;University_Challenge&quot;&gt;University Challenge&lt;&#x2F;a&gt; (a quiz show for British university students), as you’re only competing against the other people in your college rather than against everyone in your whole university &lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-8-1&quot;&gt;&lt;a href=&quot;#fn-8&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-application&quot;&gt;The Application&lt;&#x2F;h3&gt;
&lt;p&gt;Firstly, Oxbridge have a way earlier admissions deadline (the 22nd of October this year), and gives you decisions way earlier as well (mid-late January) although the acceptance date is the same. There’s the first difficulty.&lt;&#x2F;p&gt;
&lt;p&gt;The next difficulty comes from the admissions assessments. Since most people applying will have incredibly high grades and impressive personal statements, they need more ways to differentiate candidates.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-tmua&quot;&gt;The TMUA&lt;&#x2F;h3&gt;
&lt;p&gt;This takes place in different ways for different courses, but for Computer Science this involves taking the Test of Mathematics for University Admission - the &lt;a href=&quot;https:&#x2F;&#x2F;www.admissionstesting.org&#x2F;for-test-takers&#x2F;test-of-mathematics-for-university-admission&#x2F;&quot;&gt;TMUA&lt;&#x2F;a&gt;. This is a really difficult maths paper - 2 papers taken back-to-back, which each have 20 multiple choice questions to be done over 75 minutes. It’s all Maths based, but Paper 1 seems to be more about the foundations, and Paper 2 seems to be more about reasoning &amp;amp; logic.&lt;&#x2F;p&gt;
&lt;p&gt;My school ran preparation sessions, so I slowly worked my way through all of the old past papers (of which there are only 10, because it hasn’t been around for very long&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-9-1&quot;&gt;&lt;a href=&quot;#fn-9&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;), and prepared thoroughly for the exam. I had my half-term holiday start at the end of the week before the test so I got about 4 or 5 days to do nothing but TMUA preparation. That having been said, I was pretty sick for most of that period so I didn’t get all that much productive work done.&lt;&#x2F;p&gt;
&lt;p&gt;Then, when the day came around I took the exam at my school and then went for Kokoro with my friends&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-10-1&quot;&gt;&lt;a href=&quot;#fn-10&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, my lungs doing a seal impression the whole time 😔.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-interview&quot;&gt;The Interview&lt;&#x2F;h3&gt;
&lt;p&gt;From the outside, the cambridge admissions seem to work off a series of successive filters, and I’d just managed to pass the TMUA ones. A few days before I would get my TMUA result back I got an email from my college with my interview time and details.&lt;&#x2F;p&gt;
&lt;p&gt;I signed a very thorough non-disclosure (not sure if a solicitor&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-11-1&quot;&gt;&lt;a href=&quot;#fn-11&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; would call it that, but it’s probably close enough), so I’ll be pretty shy about any specific details to avoid invalidating my current application.&lt;&#x2F;p&gt;
&lt;p&gt;My interview ended up being about 30-40 minutes, and I had it over Zoom - this part gets interesting. So, historically most colleges have done in-person interviews at the Cambridge College, and I’ve had friends who’ve been to up to Cambridge recently for in-person interviews. However, over Covid most colleges switched to Zoom, and quite a few have stayed. It make sense when you think about it - I can pretty easily get to Cambridge from London, but someone living in North Scotland might have more troubles. This way, they can get the most skilled applicants regardless of geography getting in the way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing Thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;Having now gone through some pretty competitive admissions processes in multiple countries (all I’ve got to do now is wait for results 😬), I’m pretty happy to give my thoughts.&lt;&#x2F;p&gt;
&lt;p&gt;Doing both at the same time has been pretty stressful - I started off the term worrying about my Personal Statement, then I worried about the TMUA, then it was straight into MIT Essays then my MIT Interview then my Cambridge Interview and that was a challenge. During all that I still had lots of commitments to manage, ranging from being Vice-Captain of my school house to writing these blog posts (although this has been a vibey de-stresser) to a musical production where I took the pretty senior role of &lt;a href=&quot;https:&#x2F;&#x2F;maguire.tech&#x2F;ramblings&#x2F;technical-theatre-experience&#x2F;&quot;&gt;Stage Manager&lt;&#x2F;a&gt;. That having been said, I wouldn’t change it for the world because of all the knowledge I’ve gained.&lt;&#x2F;p&gt;
&lt;p&gt;I think that the US approach is a lot more work (because of the essays, as well as having to do their admissions test last year), but I kinda feel like MIT’ve got a far better idea of the nebulous concept of &lt;em&gt;Jack Maguire™️&lt;&#x2F;em&gt; than Cambridge. That having been said, I think Cambridge have a far better idea of my skills and capabilities - the interview was less casual and was with a professor and a supervisor, which was more stressful on my end but I almost feel more like if I get a rejection there wasn’t much more I could do (apart from being less stressed - that was far better in the MIT Interview, but you can’t really replicate coffee shop vibes in a zoom). I guess I’ll see what happens 😉.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-0&quot;&gt;
&lt;p&gt;I took English (Literature + Language), Maths, Further Maths, the 3 Sciences separately, Design &amp;amp; Engineering, Geography, Latin, French &amp;amp; Russian. &lt;a href=&quot;#fr-0-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;This is a holdover from more old fashioned naming systems still kept in place at some schools, where you progress through different &lt;em&gt;forms&lt;&#x2F;em&gt;, but these vary wildly from school to school. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;At time of writing, see &lt;a href=&quot;https:&#x2F;&#x2F;explore-education-statistics.service.gov.uk&#x2F;find-statistics&#x2F;16-18-destination-measures&quot;&gt;source&lt;&#x2F;a&gt;. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;There’s also &lt;a href=&quot;https:&#x2F;&#x2F;qualifications.pearson.com&#x2F;en&#x2F;about-us&#x2F;qualification-brands&#x2F;btec.html&quot;&gt;BTECs&lt;&#x2F;a&gt;, but I’ve not the foggiest on how they work. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;Most UK Universities have a Students Union. The level of involvement and importance varies, but these typically deal with everything from getting student conditions improved (eg. mental health as a valid excuse for missing an exam) to clubs &amp;amp; societies. Unlike (as far as I’ve seen), lots of US Universities, the senior student union positions cover the entire university and are taken as a sabbatical rather than concurrently with studies. &lt;a href=&quot;#fr-4-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;Technically, this is the &lt;em&gt;equal consideration&lt;&#x2F;em&gt; deadline. This means that all universities should consider all applications submitted before here equally and by consequence that they’re allowed to discriminate against late applications. &lt;a href=&quot;#fr-5-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-6&quot;&gt;
&lt;p&gt;Unlike the US there isn’t a system of Freshman -&amp;gt; Sophomore -&amp;gt; Junior -&amp;gt; Senior, it’s just first-years to second-years etc. &lt;a href=&quot;#fr-6-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-7&quot;&gt;
&lt;p&gt;Imperial is supposed to be insanely good for Computer Science (and their open day was &lt;strong&gt;impressive&lt;&#x2F;strong&gt;), and they’re in a lovely part of London in South Kensington, but it’s London. I’ve heard awful things about everyone being spread all over London in accommodation over an hour away from the main campus which then screws with lots of social stuff. &lt;a href=&quot;#fr-7-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-8&quot;&gt;
&lt;p&gt;I’m just going to politely pretend that I haven’t heard any stories about colleges which only submit postgraduates, or ones where the teams might have median ages of &lt;strong&gt;45&lt;&#x2F;strong&gt; 😱. &lt;a href=&quot;#fr-8-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-9&quot;&gt;
&lt;p&gt;And looks like it won’t be around for &lt;a href=&quot;https:&#x2F;&#x2F;www.admissionstesting.org&#x2F;news&#x2F;view&#x2F;reforms-to-cambridge-assessment-admissions-testing-from-2024&#x2F;&quot;&gt;much longer&lt;&#x2F;a&gt;. &lt;a href=&quot;#fr-9-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-10&quot;&gt;
&lt;p&gt;Those portions are &lt;strong&gt;huge&lt;&#x2F;strong&gt; &lt;a href=&quot;#fr-10-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-11&quot;&gt;
&lt;p&gt;British term for a non-court-based lawyer. Court lawyers are called Barristers - &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=iId5WDsYxZ4&quot;&gt;Saul Goodman&lt;&#x2F;a&gt; would be a Barrister, but the &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=d3qdju45udE&quot;&gt;blood-sucking lawyer from Jurassic Park&lt;&#x2F;a&gt; would probably be a solicitor. &lt;a href=&quot;#fr-11-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>Transport for London, for Dummies</title>
          <pubDate>Tue, 21 Nov 2023 00:00:00 +0000</pubDate>
          <author>Jack Maguire</author>
          <link>https://maguire.tech/ramblings/tfl-for-dummies/</link>
          <guid>https://maguire.tech/ramblings/tfl-for-dummies/</guid>
          <description xml:base="https://maguire.tech/ramblings/tfl-for-dummies/">&lt;p&gt;I’ve had the good fortune of living in an incredible city for most of my life. I’ve also had the fortune to go to lots of other different cities around the world, and most don’t even compare to London for me. The unique combination of food, people, my obvious bias and &lt;strong&gt;obviously&lt;&#x2F;strong&gt; most importantly London’s public transport.&lt;&#x2F;p&gt;
&lt;p&gt;I mean, look at the tube map alone!&lt;&#x2F;p&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;tfl_tube_map.png&quot;&#x2F;&gt;
    &lt;figcaption&gt;A work of Art!&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;
&lt;p&gt;If we then compare that to the NYC one, which is serving over double the population of London we can see that one is far better than the other.&lt;&#x2F;p&gt;


&lt;figure&gt;
    &lt;img class=&quot;no-hover&quot; src=&quot;&amp;#x2F;images&amp;#x2F;nyc_subway.png&quot;&#x2F;&gt;
    &lt;figcaption&gt;A bit mid.&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;
&lt;p&gt;This will mainly be focused (as per usual), on my experiences. I won’t be talking about the best specific routes, because you should always just use a travel app unless you’re &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;JxD88PflssA&quot;&gt;Jay Foreman&lt;&#x2F;a&gt;. I will also take a brief tangent to talk about the UK rail system because there are plenty of train stations in London.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;payment&quot;&gt;Payment&lt;&#x2F;h2&gt;
&lt;p&gt;The cheapest way to go for pay-as-you-go journeys is to use an Oyster card. These can be picked up at any tube stations, and you can just dump money onto them. You ‘tap-in’ when you get into a station, take all of your transport on that method&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; and then ‘tap-out’ when you get off. You can also tap in and out with contactless cards, Apple Pay &amp;amp; Google Pay. Important detail - only one person can travel per card (Apple Pay with a card counts differently to just that card contactless).&lt;&#x2F;p&gt;
&lt;p&gt;Please, for the sake of locals use a card. Its far less faff, far more reliable and most importantly it’s fast. You don’t want to know what I’ve heard from less polite Londoners about tourists. People remember British politeness, but also forget our nature of grumbling about problems.&lt;&#x2F;p&gt;
&lt;p&gt;For smaller train stations, you might not see actual barriers, and just pads to tap out on, or you might see all of the barriers open. You do still need to tap in and tap out - if they work out that you didn’t tap in or out then they’ll just charge you for whatever they think you did (&lt;a href=&quot;https:&#x2F;&#x2F;tfl.gov.uk&#x2F;fares&#x2F;how-to-pay-and-where-to-buy-tickets-and-oyster&#x2F;pay-as-you-go&#x2F;touching-in-and-out&quot;&gt;charges table here&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;tfl.gov.uk&#x2F;fares&#x2F;find-fares&#x2F;tube-and-rail-fares&#x2F;single-fare-finder&quot;&gt;single fare finder here&lt;&#x2F;a&gt;). Typically, they’ll be open if there isn’t a member of staff present - they need to be able to sort out issues or open the gates for emergencies so if nobody’s there then they have to keep them open.&lt;&#x2F;p&gt;
&lt;p&gt;Buses are only tap-on, tubes charge a fee based on which &lt;em&gt;zones&lt;&#x2F;em&gt; you start and finish in and I think trains work the same way&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-2&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. There are also numerous ways to reduce the cost, like getting an Oyster Photocard if you fit certain requirements, and children under 5 travel free. There’s the hopper fare where you can travel on any number of bus journeys within 1 hour once you’ve paid £1.75. There’s also the daily (and weekly) travel caps for the tube. These latter two are applied automatically so you don’t need to worry about them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;individual-methods&quot;&gt;Individual Methods&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;tube&quot;&gt;Tube&lt;&#x2F;h3&gt;
&lt;p&gt;The London tube map looks like confusing at first but that’s mainly due to two requirements - a need for it to be small enough that the stations are legible as well as wanting to vaguely conform to the real world station locations. It looks a mess, but you get used to the bits you use, and you can also just use a travel app for pathfinding.&lt;&#x2F;p&gt;
&lt;p&gt;Every tube will stop at every stop on its route (with exceptions like Turnham Green unfortunately) - if the tube you’re on will go past a stop then it will stop there. There are 3 main steps to navigation on the tube: the line, the direction and the terminal stop.&lt;&#x2F;p&gt;
&lt;p&gt;The line refers to which colour the tube is on the map - but in London they all have names&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; because of their unique history&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Most stations will serve at maximum two or three lines. The exceptions are the huge Network Rail stations (like Paddington, Euston, Kings Cross and Waterloo) which often serve five or more tube lines as well as trains.&lt;&#x2F;p&gt;
&lt;p&gt;Then, each line runs in two directions - either North&#x2F;South-Bound or West&#x2F;East-bound. Then, each tube station will have maps right next to the junctions for the different directions. Each tube will also have a map on the inside of just the line that that physical tube serves. The part that some people get confused on is the terminal stop. In each of the directions the tube serves, there will be one or more terminal stops. For example, when going West on the District Line, you can end up at Wimbledon, Richmond or Ealing Broadway. In Central London you don’t need to worry because you’ll be in the core where you can get on any train. You only really need to worry about the terminal stops for getting further outside central London. For example, if you’re going from the Science Museum in South Kensington to the Tennis in Wimbledon on the District Line you’ll need to make sure to catch a Wimbledon train rather than an Ealing Broadway one.&lt;&#x2F;p&gt;
&lt;p&gt;In Central London, the tube is &lt;em&gt;almost&lt;&#x2F;em&gt; always the fastest way to get around - faster than a taxi, faster than a bus and faster than walking.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bus&quot;&gt;Bus&lt;&#x2F;h3&gt;
&lt;p&gt;The buses (surprisingly enough) are more complicated but very similar in operation. Each number acts as its own line with a route of stops. You also get the same issue of terminal stops but these are far less of an issue compared to the tube. There are two main differences:&lt;&#x2F;p&gt;
&lt;p&gt;Firstly, buses will not stop at stops unless asked. Usually, this isn’t a problem (especially at larger stops), but if nobody presses the button and nobody is waiting then the bus will happily keep on going without letting you off.&lt;&#x2F;p&gt;
&lt;p&gt;Next, buses have individual stops for the two directions they will go in which can be quite far apart. If you’re trying to find the stop for Hyde Park Corner to hop onto a 22 to Oxford Circus, make sure to get to the right Hyde Park Corner to make sure you don’t end up in Putney Common.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;train&quot;&gt;Train&lt;&#x2F;h3&gt;
&lt;p&gt;Trains in the UK are the transport method with the most variability in fares because all of the train companies are operated separately (with exceptions of conglomerates) and integrate to different degrees with the larger TfL ecosystem. Trains typically have more seats, wider &amp;amp; longer carriages and possibly other amenities like toilets or bike racks.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re in London, you can just tap-in and tap-out as normal - be very careful though because there is a border for when you can and can’t tap in&#x2F;out. There also isn’t the same system with different terminal stops so that’s simple. The complexity comes with the fact that different trains stop at different stops on the same routes. The best bet is to check the departure board before you leave so you know that it stops at the stop you need it to stop at.&lt;&#x2F;p&gt;
&lt;p&gt;When buying tickets to go outside of London, most people would book via Trainline. Whilst this will definitely work, for some things they charge fees (like on certain refunds). Most people don’t realise that you can download one of the TOC&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;’s apps and book tickets for &lt;strong&gt;every other&lt;&#x2F;strong&gt; TOC. Then you don’t need to pay fees for some actions. If you can, I’d also recommend getting some kind of Railcard - there’s ones for students, couples, young people, old people, families and &lt;a href=&quot;https:&#x2F;&#x2F;www.railcard.co.uk&#x2F;&quot;&gt;more&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;river-boats&quot;&gt;River Boats&lt;&#x2F;h3&gt;
&lt;p&gt;Finally, the river boats. There are only 6 routes, and they stop at every station and every station goes both ways. They also get reliable mobile phone reception, often have cafes and toilets and also give a lovely riverside view of London. The disadvantages are that its insanely expensive (on the scale of public transport at least - on the order of £5&#x2F;6 per journey), and often slower than the tube or bus.&lt;&#x2F;p&gt;
&lt;p&gt;The main clientele is City of London workers who live near the river but don’t want to take a Black Cab (to be explained later). They enjoy it because they can get a fair bit of work done on it, unlike with the tube or bus. People also like using them because they’re a more comfortable and quieter ride compared to the tube&#x2F;bus and the cafes are always appreciated.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;private-hire&quot;&gt;Private Hire&lt;&#x2F;h3&gt;
&lt;p&gt;Private hire is pretty self-explanatory because most cities have it and it isn’t particularly different here.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Uber is the dominant app for quick &amp;amp; relatively cheap cabs and all Uber drivers are all supposed (iirc) to be licensed by TfL.&lt;&#x2F;li&gt;
&lt;li&gt;If you have the money, you can also get a Black Cab which is the famous London one - all the drivers are supposed to know Central London off by heart, and they can also use the bus lanes (other bus lane exceptions &lt;a href=&quot;https:&#x2F;&#x2F;tfl.gov.uk&#x2F;modes&#x2F;driving&#x2F;red-routes&#x2F;rules-of-red-routes&#x2F;bus-lanes&quot;&gt;here&lt;&#x2F;a&gt;). Black Cabs also have a very limited number of reasons for refusing fares and &lt;strong&gt;must&lt;&#x2F;strong&gt; have wheelchair ramps.&lt;&#x2F;li&gt;
&lt;li&gt;We also have bicycles to hire - &lt;a href=&quot;https:&#x2F;&#x2F;tfl.gov.uk&#x2F;modes&#x2F;cycling&#x2F;santander-cycles&quot;&gt;Boris bikes&lt;&#x2F;a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-6-1&quot;&gt;&lt;a href=&quot;#fn-6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; are the official ones, and you can also use the &lt;a href=&quot;https:&#x2F;&#x2F;www.li.me&#x2F;vehicles&#x2F;electric-bike&quot;&gt;Lime Bikes&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.humanforest.co.uk&#x2F;&quot;&gt;Forest Bikes&lt;&#x2F;a&gt; and more that I’ve probably forgotten.&lt;&#x2F;li&gt;
&lt;li&gt;There are also rickshaws. Please always be careful with them - some of them aren’t licensed and make sure to always check the prices &lt;strong&gt;before&lt;&#x2F;strong&gt; you start to avoid getting an insanely high fee for a short journey.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing Thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;London’s public transport is insanely good and one of the reasons I so love London - I can leave home, get to the nearest tube stop (via like 4 different buses) and get to anywhere in central London in under half an hour. Unlike in some other cities, the tube really makes the city feel tiny (also aided by the weird development of the city&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-7-1&quot;&gt;&lt;a href=&quot;#fn-7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;) - I can get to the West End, Harrods, Leicester Square, The Ritz, and all of the big tourist attractions with zero effort.&lt;&#x2F;p&gt;
&lt;p&gt;Whilst from these footnotes and bracketed sections it might seem that the only concrete rule with TfL is that there will always be exceptions these mostly don’t apply and when they do it’s relatively obvious.&lt;&#x2F;p&gt;
&lt;p&gt;I would also like to partially credit TfL with helping me to develop my independence - the ability to be able to go out anywhere anytime without needing to rely on other people has been incredible. TfL most definitely has problems (be it the exceptions, the inaccurate bus times, the long times for fixing things or the endless strikes), but I love it and wouldn’t wish to swap it with any other city’s public transport system.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;There are exceptions though - for example, the Heathrow Express has a ticketed system. Sometimes you can also get on a train via tapping in but you’ll need a ticket at the other end - watch out if you’re going beyond London. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-1-2&quot;&gt;↩2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;That having been said, you can sometimes transfer between different methods without going through a gate - these are signposted and you just need to tap the station on the platform. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;For some Londoners, it’s a point of pride to be able to correctly match all of the colours and the names. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;The London Tube is one of the oldest in the world and the lines have their names for a variety of reasons. For example, the Bakerloo Line used to just serve Baker Street &amp;amp; Waterloo, and the Jubilee Line was opened not too far (in time) from the one of the Queen’s Jubilees. &lt;a href=&quot;#fr-4-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;Train Operating Company (like South Western Rail, Avanti West Coast, Great Western) &lt;a href=&quot;#fr-5-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-6&quot;&gt;
&lt;p&gt;Technically they’re the Santander Cycles, but no self-respecting Londoner would ever call them that. The nickname comes from the Mayor of London who introduced them - Boris Johnson. &lt;a href=&quot;#fr-6-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-7&quot;&gt;
&lt;p&gt;Technically, the City of London is older than England itself. The Normans tried to create a new capital city (in what is now Westminster), but both grew and grew and eventually merged making the distinction pointless. London is technically a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Conurbation&quot;&gt;Conurbation&lt;&#x2F;a&gt; rather than just a normal city. &lt;a href=&quot;#fr-7-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>The Technical Theatre Experience</title>
          <pubDate>Mon, 13 Nov 2023 00:00:00 +0000</pubDate>
          <author>Jack Maguire</author>
          <link>https://maguire.tech/ramblings/technical-theatre-experience/</link>
          <guid>https://maguire.tech/ramblings/technical-theatre-experience/</guid>
          <description xml:base="https://maguire.tech/ramblings/technical-theatre-experience/">&lt;p&gt;Over the last few years, I’ve gone deep into Technical Theatre. This is the kind of blanket term for all the non-actors involved in a theatrical production. I’ve worked on a lot of productions (everything from tiny casts in small spaces to huge musicals in traverse), with a relatively small team and that’s led to me wearing an awful lot of hats. The plan is for me to write about all the roles I’ve done and give some opinions. I’ll then talk about my general experience.&lt;&#x2F;p&gt;
&lt;p&gt;I say this multiple times, but it’s good to mention from the start - this is all based off my experiences which are likely not reflective of yours - different shows run differently and people share different responsibilities. There are also probably countless roles I’ve missed - I’m trying to stick to roles I’ve actually had some hand in for the most part here. This is more about my experiences than what you might have done. That having been said, I’m always curious to learn about new things so email me if you’ve got a role I don’t mention here.&lt;&#x2F;p&gt;
&lt;p&gt;I’ll also add a warning here - if you actually want to know what to do, the best resource I’ve found is the &lt;a href=&quot;https:&#x2F;&#x2F;wiki.cuadc.org&#x2F;wiki&#x2F;Cambridge_University_Amateur_Dramatic_Club&quot;&gt;ADC Wiki&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;backstage&quot;&gt;Backstage&lt;&#x2F;h2&gt;
&lt;p&gt;First, I’ll be talking about all the roles that are on the ground, in the wings and with all the actors.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;stage-manager-sm&quot;&gt;Stage Manager (SM)&lt;&#x2F;h3&gt;
&lt;p&gt;The stage manager is the lead role - if something goes wrong, then the buck ultimately stops with you. This is the most senior technical role, and so can sometimes involve extra details around safety in case of serious on-stage problems or guiding audiences to a safe place.&lt;&#x2F;p&gt;
&lt;p&gt;Your job amounts to knowing exactly what happens when for the whole show in terms of props, set changes &amp;amp; who’s moving everything around. Then, when something inevitably gets forgotten you need to notice and take steps to a) make sure it isn’t forgotten again and b) try and somehow get it onstage subtly.&lt;&#x2F;p&gt;
&lt;p&gt;I’m currently preparing for a Stage Manager job, but I’ve never actually done it so we’ll see what happens.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;assistant-stage-manager-asm&quot;&gt;Assistant Stage Manager (ASM)&lt;&#x2F;h3&gt;
&lt;p&gt;The ASMs work for the SM, actually doing all of the set changes and prop pre-setting. Typically you’ll need to memorise transitions because the director will probably have some novel way of moving everything on and off stage. If you forget something, then get ready to be told so over headset from the SM.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve been ASM a few times - it’s often categorised by periods of boredom (because you need to stay by the stage to do transitions, but then can’t talk or do much) interspersed by brief periods of high activity. Depending on the show &amp;amp; director, you might only be needed for a few of the bigger transitions, or you’ll be on your feet for the whole night.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sound-2-3&quot;&gt;Sound 2&#x2F;3&lt;&#x2F;h3&gt;
&lt;p&gt;The main difference between Sound 2 &amp;amp; 3 is how much you’re responsible for - is it just mic-ing up actors or are you also worried about making sure all the packs have enough batteries and are at the right frequencies.&lt;&#x2F;p&gt;
&lt;p&gt;That having been said, a lot of the work is just making sure actors have microphones.&lt;&#x2F;p&gt;
&lt;p&gt;Depending on the size of the production this can be wildly different in difficulty. In smaller production with lots of talking roles, you might have mic changes with every other scene - once I think I had to do a mic change over about 2 or 3 lines.  In larger productions, you might not need to worry much apart from the start and end because you might be able to rent enough for everyone. This is why Sound 3 people can often end up doubling as ASMs.&lt;&#x2F;p&gt;
&lt;p&gt;This is one of the more wasteful areas of the theatre - I’ll write more about this later, but the environmental impact of the theatre is not to be understated. Specifically here the consistent director enforces rules around batteries - regardless of how long they’ve been used for they have to be replaced every night. For a 24 mic production, this means 48 AA batteries per night - if you account for rehearsals and say 6 production nights (which is relatively small), you’re then speaking in the quantities of hundreds of batteries. Do that multiple times a year and you’re into the thousands of batteries. And then at that scale, rechargeable batteries become impractical so most batteries just get binned.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sound-1&quot;&gt;Sound 1&lt;&#x2F;h3&gt;
&lt;p&gt;NB: I haven’t ever actually done this because I decided to specialise in lighting - I’ve dabbled and done mic work, but nothing much more so this is extrapolation based off what I’ve seen. I’ll try and keep the opinions to a minimum because I’ve got almost no experience here.&lt;&#x2F;p&gt;
&lt;p&gt;Sound 1 is the other major backstage role, although it’s more similar in nature to a box role, as you mainly stay put during the actual production. Before that point, you’ll be running around checking audio cables and making sure all of your equipment works precisely the way you think it does. The reason I’d qualify this as backstage is because you have to do your job from within the auditorium to make sure that you’re hearing the levels accurately.&lt;&#x2F;p&gt;
&lt;p&gt;During the actual production, your job is to manage the levels of all the different microphones - band &amp;amp; actors both. Recently, this has just been muting the band’s microphones because they’re so loud and getting the actors as loud as possible. That having been said, that’s probably because for the in-traverse musical&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, there are way fewer sound deafening seats than usual.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-box&quot;&gt;The Box&lt;&#x2F;h2&gt;
&lt;p&gt;I usually find that I prefer box roles more as you can sometimes get away with quiet conversation during quiet parts and sometimes even eating. The one time I’ve ever heard eating&#x2F;drinking being banned was as an intervention to stop the sound operator drinking so much coffee. It’s also often cooler because you sometimes have AC. There’s also usually a great view.&lt;&#x2F;p&gt;
&lt;p&gt;I will add one point to that though - this is mainly from my experiences with one box that is: sound-proofed, air-conditioned for several reasons, has a mini-fridge and large windows. I’ve also seen boxes that are small and stuffy where the fact that the windows opens is a godsend for heat reasons. I’ve done one production in a box that was centimetres away from an audience, and on that occasion roles were reversed because the ASMs and other backstage roles waited outside right next to a stage entrance.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lighting-designer&quot;&gt;Lighting Designer&lt;&#x2F;h3&gt;
&lt;p&gt;Lighting design involves looking at the stage and current lighting plans and deciding whether or not they’re sufficient. If not, then everyone gets involved to bring the lighting bars down and add new lights - either from storage, purchase or rental. This involves a whole lot of tape and safety chains to make sure the cables are as invisible as possible (that is, not drooping down from the bars) and takes a while. Then, they need to be put back in place and focused, a job I’ve never done but looks like it involves spanners and heights which makes me glad I’ve never had to do it - although I would one day like to do it, for curiosity’s sake.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lighting-programming&quot;&gt;Lighting Programming&lt;&#x2F;h3&gt;
&lt;p&gt;Lighting programming mainly involves a mastery of whichever lighting system the theatre uses to control the fixtures - trying follow what the lighting designer says, and tweaking it to fit with the lights installed.&lt;&#x2F;p&gt;
&lt;p&gt;Sounds pretty simple, and for smaller shows it definitely can be - the trouble comes with larger shows where me you might jump around in the various sections you’re programming - this can lead to (dun dun duunnununnn!!!) tracking issues! These are the worst bane of lighting programmers and result when cues are incorrectly updated and those changes can persist until that light is used again. You then need to go through every cue between and fix it, which can take a forever and a half.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lighting-sound-operator&quot;&gt;Lighting&#x2F;Sound Operator&lt;&#x2F;h3&gt;
&lt;p&gt;Lighting &amp;amp; Sound Operator are both very similar and quite simple - you just press the button to advance to the next cue when the Deputy Stage Manager tells you to.&lt;&#x2F;p&gt;
&lt;p&gt;The main difference is in the frequency of button-pushing - as a sound operator I once had time to make a cup of tea for the lighting operator, wait for him to drink it and then clean it all up between cues. Lighting changes are often more frequent - I think the longest gap I ever had was during a 7 minute duration cue which signified the transition between day &amp;amp; night.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;deputy-stage-manager-dsm&quot;&gt;Deputy Stage Manager (DSM)&lt;&#x2F;h3&gt;
&lt;p&gt;The DSM’s job is to call the lighting changes and communicate any possible on-stage issues to the SM in case they haven’t already noticed. This involves a very well marked up script (often called The Book), but doesn’t involve too much beyond that.&lt;&#x2F;p&gt;
&lt;p&gt;This is the most senior box-based role, and on smaller productions you’ll often see the director double up as the DSM to execute the cues exactly to their vision. I’ve seen some quite funny sights of DSMs getting very annoyed at the cast during rehearsals privately to the box crew (who are sworn to secrecy by tradition) once to the point of snapping the nib of their pen.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pre-production&quot;&gt;Pre-Production&lt;&#x2F;h2&gt;
&lt;p&gt;Unfortunately, I have no experience in costumes, set design, prop sourcing or lots of the aspects of the show that start long before production.&lt;&#x2F;p&gt;
&lt;p&gt;The only thing I can say is that set building &amp;amp; rigging lights has shown me that &lt;em&gt;Manual Labour&lt;&#x2F;em&gt; can be fun with friends.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing Thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve loved my last few years in technical theatres - including the production I’m working on right now I’ve done 9, as well as multiple events the theatre team is asked to do like running cable for fireworks night. I’m definitely going to continue on when I get to university but I probably need a bit of a healthier attitude towards it - last year I did literally everything I could apart from when it directly clashed with permanent-record acts and I’m a hair tired of it all.&lt;&#x2F;p&gt;
&lt;p&gt;Then, on the other hand what can you really be without hardship? I’ve learnt proper transferable skills like teamwork, a hair of leadership &amp;amp; prioritisation. I’ve got my calendar and todo list to a bulletproof state, partially because I’m just that guy, but also because if I didn’t then all the balls I’m carefully juggling would have fallen by now.&lt;&#x2F;p&gt;
&lt;p&gt;I haven’t even considered the impact on people other than me here - I’ve already mentioned the batteries earlier but there’s a far larger impact than that. I haven’t mentioned the tape (wouldn’t be surprised if we get through it by the 100s of metres per production and then that all goes in the bin). There’s the paint and the lights. I’ve worked on productions where the lights are so many and so bright that we don’t turn on the lights until right before the audience comes in for heat management. Even just from a heat perspective that’s more power than my computer probably consumes all year just in an evening.&lt;&#x2F;p&gt;
&lt;p&gt;All of that having been said, I’ve never quite found anything else that matches the stress, the teamwork &amp;amp; the eventual satisfaction when everything goes well in front of a paying audience. I love the thinking on your feet problem solving it a prop is left on stage, or a lighting cue goes one too early because there’s no time for dallying or indecisiveness. Some people get this by sports, but I’ve never quite had that experience so for now I’ll be staying in the theatre. I guess we’ll have to wait and see what the future holds for my theatrical career.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;This is where most of the seats are moved out of the way to have the actors act between 2 pairs of facing audience seats. Makes the show far more immersive at the cost of seating space. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>MIT Interview</title>
          <pubDate>Sun, 12 Nov 2023 00:00:00 +0000</pubDate>
          <author>Jack Maguire</author>
          <link>https://maguire.tech/ramblings/mit-interview/</link>
          <guid>https://maguire.tech/ramblings/mit-interview/</guid>
          <description xml:base="https://maguire.tech/ramblings/mit-interview/">&lt;p&gt;Recently, I’ve been going through the joy that is university admissions in 2023 applying simultaneously to US &amp;amp; UK systems. Trying to get in a halfway decent application for them both without sacrificing my studies and the theatre productions I’m involved in has been, to put it lightly, a little bit of a huge pain.&lt;&#x2F;p&gt;
&lt;p&gt;Here I’ll be writing about my experience applying to US universities, specifically MIT (and if plans hold, then a caltech post later this year) from the perspective of a Brit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;long-term-prep&quot;&gt;Long-Term Prep&lt;&#x2F;h2&gt;
&lt;p&gt;One thing that both systems seem to have in common is that you need to be an interesting person who can show passion for their subject. From a Computer Science view this means that I’ve spent the last few years making more projects than I can shake a stick at. I’ve tried to make a variety of projects, but the main focus has been on making sure that the project was fun to code over making it actually useful. I found this insanely helpful to make sure I actually ended up finishing these projects to an acceptable degree, rather than just having a halfway finished physics engine that I wasn’t really all that interested in. If you want to see what I’ve been cooking, I’ve got a few writeups on this site, with more coming.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve also kept up with computer science and general tech news, like making sure to flick through &lt;a href=&quot;https:&#x2F;&#x2F;this-week-in-rust.org&#x2F;&quot;&gt;TWIR&lt;&#x2F;a&gt; every week or listening to WAN show on my runs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;admissions-tests&quot;&gt;Admissions Tests&lt;&#x2F;h2&gt;
&lt;p&gt;This is the main difference between UK &amp;amp; US admissions as far as I can tell. I’ll take a bit here to explain both systems so everyone understands.&lt;&#x2F;p&gt;
&lt;p&gt;In the UK, at the end of the second-last year of school you take an internal set of exams and your school gives you a set of predicted grades - you send these to the universities with a personal statement and then universities hand out conditional offers. These are conditional in that the offer will have a set of requirements for grades which will normally be at or below the predicteds you submitted.&lt;&#x2F;p&gt;
&lt;p&gt;Whereas in the US (as far as I can tell), you take exams (like SAT or ACT exams) which get sent to the universities with a metric ton of uni-specific essays (apart from if they’re part of a coalition like Common App where there’s one common essay). Then, they send back unconditional offers. There appear to be loads of exceptions and weird bits though - like applications which are binding if they accept you, or some universities which are test-optional or test-blind.&lt;&#x2F;p&gt;
&lt;p&gt;So, I’ve got all my predicteds sorted because I go to a UK school, and then I took a few ACTs last year after doing a prep course.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;observations-from-a-brit&quot;&gt;Observations from a Brit&lt;&#x2F;h3&gt;
&lt;p&gt;It’s really interesting what the different systems prioritise. A-Level Physics is about a fundamental understanding of the subject with equations and some bits you’ve got to memorise whereas ACT Science is more about reading, understanding and then answering questions about those experiments. A-Level Further Maths is about long questions with problem solving elements, but ACT Maths is simpler and seems more solve this matrix than prove by induction that this matrix does that.&lt;&#x2F;p&gt;
&lt;p&gt;Part of that difference might be that the American Universities also ask about which courses you’ve done, and what your GPA is. I can’t answer them though because I don’t have a GPA. I also don’t have any AP classes because that isn’t really a concept in the UK. In some ways I don’t have to stress as much through the year because I don’t need to worry about every individual test affecting anything that goes on my record or to the universities, but equally if I mess up that one big test at the end of the year then I’m properly screwed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;recent-stuff&quot;&gt;Recent Stuff&lt;&#x2F;h2&gt;
&lt;p&gt;So I filled out my applications and wrote my essays, and ended up submitting early action - very slightly better odds and earlier knowledge of success or failure in return for earlier deadlines.&lt;&#x2F;p&gt;
&lt;p&gt;I then waited for a few anxious days and got a text &amp;amp; email from my EC (Education Counsellor - if I’ve seen worked out one thing about MIT so far, it’s that I’ll need to make a pretty big spreadsheet for acronyms). We had a chat, and eventually she sent me a calendar invite for about a week later on a Friday afternoon in a coffee shop.&lt;&#x2F;p&gt;
&lt;p&gt;This is another interesting difference - most UK universities seem to work off a series of successive filters, like grade requirements, or personal statement and then interviews. They are themselves a filter, but you’ve got to have passed through a fair few beforehand to make it to that stage so people consider it an achievement. Whereas in the US, every attempt is made to give everyone an interview which is just an interesting change.&lt;&#x2F;p&gt;
&lt;p&gt;This was when my MIT interview prep properly started (probably a bit late). If I were doing this again, I probably would’ve started reading the MIT blogs earlier because they’ve been insanely helpful, and you can find them over &lt;a href=&quot;https:&#x2F;&#x2F;mitadmissions.org&#x2F;blogs&#x2F;landing&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;. Over the last week and a half I’ve read more blogs than I can count, on everything from the best spots to cry or study to organising Splash to struggles with burnout. There are YouTube videos, but I haven’t really found many of them as useful. I also can’t lie - the student bloggers over there are definitely part of my inspiration for this.&lt;&#x2F;p&gt;
&lt;p&gt;I also started preparing answers to all kinds of questions from ‘Why MIT?’ to ‘where do you see yourself in 5 years’ to ‘How do you spend your free time’, and, especially relevant &lt;a href=&quot;https:&#x2F;&#x2F;www.npr.org&#x2F;2023&#x2F;06&#x2F;29&#x2F;1181138066&#x2F;affirmative-action-supreme-court-decision&quot;&gt;this year&lt;&#x2F;a&gt;, &lt;em&gt;The Community Question&lt;&#x2F;em&gt;. I’ll happily say that some of these questions were asked and some weren’t and that I also had a fair few questions I hadn’t prepared. What to prepare is kind of up to you - it’s not my place to tell you what questions because every interview will be different. I will say that if you’ve got topics that you’re planning on getting to, then make sure to be ready for them to ask follow up questions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-day-itself&quot;&gt;The Day Itself&lt;&#x2F;h2&gt;
&lt;p&gt;Since my interview wasn’t until 3PM, I did my usual friday morning classes rather than sleeping in. I do regret this - I wasn’t really able to focus for lots of that morning and I just felt stressed about when I was planning on leaving. One part that was quite funny was walking into one of my lessons knowing well that I could walk out whenever I damn pleased because I’d have a pretty decent excuse. That teacher had done one of my references so he was happy to just let me go without complaint.&lt;&#x2F;p&gt;
&lt;p&gt;I sprinted over and made good use of TfL to get to a Pret near my interview location about an hour and a quarter early. I was lucky that it had a decently sized bathroom which I made use of to get changed, before buying a sandwich and some food. I then realised - the Pret was full of people trying to do exactly what I wanted to do (using the Pret as a warm place to work that had food &amp;amp; sockets). Eventually a table opened up and I sprinted over to get my phone &amp;amp; laptop charging for later use.&lt;&#x2F;p&gt;
&lt;p&gt;Then, about 30 minutes before the scheduled start I went outside for a 10 minute talk to the interview place which was a way nicer café than the Pret I’d gone to - nice staff, better vibe &amp;amp; much better Hot Chocolate (I’d rate it as best I’ve ever bought).&lt;&#x2F;p&gt;
&lt;p&gt;Then, at about 15:00 on the dot, I instantly heard when my interviewer come in - a US West Coast accent stands out in a sea of Brits. I’d lucked out in this case and got an interviewer who was attended the same ‘School’ at MIT which I wanted to attend, which was the School of Engineering. She’d done Course 2 (Mechanical Engineering), and I want to do something in the Course 6 area (Computer Science).&lt;&#x2F;p&gt;
&lt;p&gt;I luckily got a chance to speak about pretty much everything I wanted, and I came up with some pretty decent answers to the questions I hadn’t prepared for. From what I’ve heard, my Cambridge (UK) interview will just be lots of Maths questions so I loved the opportunity to speak about things I’m really passionate about. It had definitely helped that I’d done practice questions in a vaguely interview-like format and from my end it seemed like she made an effort to just let me speak about anything &amp;amp; everything I wanted to which was really lovely.&lt;&#x2F;p&gt;
&lt;p&gt;As for the questions I asked her - I think I asked her about things like what she did for accommodation and the things she’d done for her extra requirements but the most interesting answer I got was definitely not from the question I expected.&lt;&#x2F;p&gt;
&lt;p&gt;That would have been when I asked if the vibe I’d gotten from the blogs was accurate - work hard, play hard. One of the main social activities for her was doing homework with friends which is certainly a contrast to what I’ve heard about other universities in the UK.&lt;&#x2F;p&gt;
&lt;p&gt;My interview ended up lasting a hair over 40 minutes, which went by at a speed you wouldn’t believe. I felt it lasted a good amount of time. I did have more to talk about but I wasn’t 100% sure how to fit it all in.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;all-done&quot;&gt;All done&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve got a few things I probably would’ve done differently if I could do it over, like mentioning a few of my outside of school hobbies that didn’t make it into my application but all the moping in the world isn’t going to change anything.&lt;&#x2F;p&gt;
&lt;p&gt;All I can do is nervously wait for mid-December. I had a peek at the stats last night, and I’ll share my interpretation - there’s about a 20-30% chance I’ll get outright rejected, which sounds incredible until you factor in that there’s still only a 6-7% chance of acceptance. The rest get waitlisted, and just dumped into the regular application pool. Of those waitlisted, it’s about a 2-3% chance of acceptance which is pretty slim, so a waitlisting isn’t all that far from a rejection 😭.&lt;&#x2F;p&gt;
&lt;p&gt;Out of all the international applicants, regardless of admissions stage, the chances are just 2% which is pretty small. That having been said, the UK seems to punch above its weight in terms of students in relation to the population and I can see that about 2 get admitted every year. It’s a shame that they don’t do applicants per country and not just current undergrads because then I could actually work out more stats. Then again, it’s probably not healthy to obsess over those stats so we’ll see what happens 🤷.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Vent</title>
          <pubDate>Sat, 11 Nov 2023 00:00:00 +0000</pubDate>
          <author>Jack Maguire</author>
          <link>https://maguire.tech/posts/vent/</link>
          <guid>https://maguire.tech/posts/vent/</guid>
          <description xml:base="https://maguire.tech/posts/vent/">&lt;p&gt;You know how recipes often have a reputation for rambling sections about the origin of those recipes? Well, let’s just say that I finally understand why.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BurntNail&#x2F;vent&quot;&gt;Vent&lt;&#x2F;a&gt; is my biggest project ever, at time of writing (over 4k LOC of Rust, not including the SQL or the templates 😲 which is pretty damn huge for me) and has been my baby for the last 8 months. It’s finally proper time that I actually show it off and explain the backend (this definitely isn’t a disguised way for me to re-familiarise  myself with the whole thing 😉).&lt;&#x2F;p&gt;
&lt;p&gt;You know the saying &lt;em&gt;Vexation breeds innovation&lt;&#x2F;em&gt;? Maybe not? Well, regardless it’s definitely true for this project. I’d just come into possession of a monstrous spreadsheet for managing various events, as well as a OneDrive folder where the photos got dumped. The old spreadsheet was exclusively for managing the details of the events and had no facilities for managing who was attending the event - this was dealt with by a series of newsletters that died out as people got bored and, in the late stages, teams messages which people were told to react with a 👍 to. The photos weren’t organised at all, were a pain to manage and nobody could see them unless you just asked and then they had to be manually dug out.&lt;&#x2F;p&gt;
&lt;p&gt;No more! To fix this, we go to a self-hosted 100% custom solution with &lt;code&gt;Rust&lt;&#x2F;code&gt; using &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;axum&quot;&gt;&lt;code&gt;axum&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;code&gt;postgres&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Jack, did you need to do this&lt;&#x2F;em&gt;? God no.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Jack, was anyone asking you to do this?&lt;&#x2F;em&gt; Also, no.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Weren’t there any prebuilt solutions?&lt;&#x2F;em&gt; Alas, I couldn’t bring myself to look when I saw the potential for such an exciting project.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The plan for the rest of this is to go over the project as it is now, then to go over the creation and some of my interesting hurdles.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;technical-details&quot;&gt;Technical Details&lt;&#x2F;h3&gt;
&lt;p&gt;As of right now, the project basically just acts as an access-managed front-end for a &lt;code&gt;postgres&lt;&#x2F;code&gt; database serving &lt;code&gt;GET&lt;&#x2F;code&gt; requests using &lt;a href=&quot;https:&#x2F;&#x2F;shopify.github.io&#x2F;liquid&#x2F;&quot;&gt;liquid&lt;&#x2F;a&gt;, and handles all interactive elements via &lt;code&gt;POST&lt;&#x2F;code&gt; requests. For CSS, I’m using &lt;a href=&quot;https:&#x2F;&#x2F;getbootstrap.com&#x2F;docs&#x2F;5.3&#x2F;getting-started&#x2F;introduction&#x2F;&quot;&gt;Bootstrap&lt;&#x2F;a&gt;, which feels 2015-esque but is the easiest way for me to get some vaguely-competent looking CSS. I like doing things myself rather than using pre-built solutions, but I’m willing to limit this project to one new main thing - the sentence above.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re wondering where I’m going to mention what Javascript framework I’m using, the answer is none. I’m a systems dude who’s trying to learn, and I’ll be honest - this is as much a project to learn the ropes of postgres, deployment, back-ends and the web as it is a project to manage events. I’ve tried lots of the java&#x2F;type-script-y frameworks, and they frankly don’t really appeal to me. I’ve become pretty damn hooked on the Rust programming language due to the package management, documentation, tooling and unique features like discriminated unions which are missing from loads of other languages so I didn’t want to really use any. I’ve tried &lt;em&gt;(trust me I’ve really actually tried)&lt;&#x2F;em&gt;, but I can’t quite get javascript to fit inside my head - I had the most success with &lt;code&gt;Svelte&lt;&#x2F;code&gt; but it just doesn’t work for me ;(.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;user-story&quot;&gt;User Story&lt;&#x2F;h3&gt;
&lt;p&gt;So, the main way this project works is through events and peoples’ links to events. An event has a number of properties (that came from the original spreadsheet - one of the project requirements was to be able to import stuff from that &lt;em&gt;relatively&lt;&#x2F;em&gt; easy), and then a bunch of links. They all have links to the people participating, the people looking managing the event, and the photos that have been added. Participant-Event links also can be marked as &lt;strong&gt;verified&lt;&#x2F;strong&gt; - this is useful for making sure people have actually attended the event. A manager-level user has to do that after the event, and in my experience the photo comes in very useful for this.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, there’s a rewards system where after completing a certain number of events, you can be eligible for different rewards. There’s also a system in place for two different entry points each of which have their own requirements for the rewards.&lt;&#x2F;p&gt;
&lt;p&gt;The access control works pretty sensibly imho - for example, someone with manager-level permissions can add and remove whomever they please from events to satisfy reality, but a participant-level user can only add and remove themselves. I won’t go into insane detail - just know that there’s 4 levels (Participant, Manager, Admin, Dev), where the admins can add &amp;amp; remove users, and the dev gets stuff that the admin wouldn’t find as interesting like reloading partial templates.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-story&quot;&gt;The Story&lt;&#x2F;h2&gt;
&lt;p&gt;Here’s the story of my application - a few items have been moved around to better tell the story, but it’s mostly accurate and if you want the 100% accurate version then feel free to read the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BurntNail&#x2F;vent&#x2F;commits&#x2F;main&#x2F;&quot;&gt;Commit History&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;beginning&quot;&gt;Beginning&lt;&#x2F;h3&gt;
&lt;p&gt;This project started with the beginners guide for the &lt;code&gt;axum&lt;&#x2F;code&gt; crate (for this was my first axum project which slowly expanded in capability as I learnt more about axum &amp;amp; async rust), where you get started with a basic GET&#x2F;POST which worked well for me. I then added a &lt;code&gt;liquid&lt;&#x2F;code&gt; based templating system inspired by &lt;a href=&quot;https:&#x2F;&#x2F;fasterthanli.me&quot;&gt;Amos Wenger&lt;&#x2F;a&gt; (specifically &lt;a href=&quot;https:&#x2F;&#x2F;fasterthanli.me&#x2F;articles&#x2F;a-new-website-for-2020&quot;&gt;this one&lt;&#x2F;a&gt; iirc), who’s writings I cannot recommend enough. I then slowly by surely added the &lt;em&gt;other things&lt;&#x2F;em&gt; like participants and photos. This part of the project was probably the second most fun, where I could move mountains with little effort - partially because I hadn’t done much yet so any change was big, and partially because I was free to look at all kinds of different approaches before I got entrenched in a pretty specific style.&lt;&#x2F;p&gt;
&lt;p&gt;I also had a few interesting constraints to work within:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I wanted to be able to run the whole thing on just the one tiny VPS (a Linode Nanode which has 1GB of RAM, 1 vCPUs and 25GB of storage) I rent whilst still keeping some space for other stuff (like this blog!). This was mainly an attempt to reduce both vendor lock-in as well as costs.&lt;&#x2F;li&gt;
&lt;li&gt;I wanted this to keep backwards compatibility with the existing spreadsheets - that meant making sure that I had lots of import&#x2F;export tools.&lt;&#x2F;li&gt;
&lt;li&gt;I wanted this to be easily used by lots of more non-technical users - a JSON feed would never be acceptable and I needed to put lots of work in to get something looking halfway decent (a challenge even with the aid of &lt;code&gt;Bootstrap&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;authentication&quot;&gt;Authentication&lt;&#x2F;h3&gt;
&lt;p&gt;I then took it to the person who actually had final say on adoption on this system and he said that I needed to follow all relevant guidelines that he had to, which in this case included making sure that you couldn’t see photos without logging in. My initial thoughts were something along the lines of &lt;em&gt;balls. i don’t really want to do this, because the more user data i store the more impact my screwups have&lt;&#x2F;em&gt;, but I wanted adoption so I just nodded and said yes. Turns out I was still right, just not in the way I thought I was.&lt;&#x2F;p&gt;
&lt;p&gt;At this point I was pretty happy with the general &lt;code&gt;axum&lt;&#x2F;code&gt; ecosystem, and I came across two main crates that seem to be used for logging in - &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;axum-auth&quot;&gt;&lt;code&gt;axum-auth&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &amp;amp; &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;axum-login&quot;&gt;&lt;code&gt;axum-login&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. &lt;code&gt;axum-auth&lt;&#x2F;code&gt; seemed to have more downloads but was just one rust file to check headers and get them. &lt;code&gt;axum-login&lt;&#x2F;code&gt; seemed to have more features and even &lt;strong&gt;drumroll please&lt;&#x2F;strong&gt; - Session Management, although it had fewer downloads. Generally, I like writing things myself (as has already been mentioned, often for the learning opportunity), but if I’ve learnt one thing in my years of Tom Scott&#x2F;Computerphile viewership - it’s that you leave password management to other people, preferably open source people with code that’s been explored &amp;amp; checked over. That having been said, it still wasn’t the easiest to work with - there were a few annoyances like having to rewrite the &lt;code&gt;PostgresStore&lt;&#x2F;code&gt; for sessions to work with my system, as well as getting passwords to work right. I started with the &lt;code&gt;0.6&lt;&#x2F;code&gt; version, which has recently been updated with more breaking changes than I’ve had hot dinners (future update coming - &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BurntNail&#x2F;vent&#x2F;issues&#x2F;187&quot;&gt;issue here&lt;&#x2F;a&gt;). I then used &lt;code&gt;bcrypt&lt;&#x2F;code&gt; to store the &lt;em&gt;hashed&lt;&#x2F;em&gt; passwords.&lt;&#x2F;p&gt;
&lt;p&gt;One fun solution to a problem is signing up. Since I know my entire userbase in advance, I can just import them all via CSV with blank passwords set. My original solution was to just set the password to whatever the user entered on first login, before I realised that I’d have a sea of password resets as people logged into other peoples’ accounts for shits &amp;amp; giggles. I eventually ended up going with emailed magic links to set the password.&lt;&#x2F;p&gt;
&lt;p&gt;Eventually I got all that working, with the access control coming not long after. As I alluded to earlier, there was still a pain point. This was just managing the access control levels across the whole application - I have checks in a whole lot of places to make sure someone’s not trying to be sneaky with direct &lt;code&gt;POST&lt;&#x2F;code&gt; requests to the server and making sure that no PII leaks.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-modern-web&quot;&gt;The Modern Web&lt;&#x2F;h3&gt;
&lt;p&gt;At this point though it was just something running on my machine, or just via direct HTTP from my registrar (originally &lt;a href=&quot;https:&#x2F;&#x2F;hover.com&quot;&gt;Hover&lt;&#x2F;a&gt;, but I transferred to &lt;a href=&quot;https:&#x2F;&#x2F;www.cloudflare.com&#x2F;en-gb&#x2F;learning&#x2F;dns&#x2F;what-is-cloudflare-registrar&#x2F;&quot;&gt;Cloudflare&lt;&#x2F;a&gt; for cheaper renewal fees) to my VPS (&lt;a href=&quot;https:&#x2F;&#x2F;www.linode.com&#x2F;&quot;&gt;Linode&lt;&#x2F;a&gt; seems to give a decent compromise between cost, configuration &amp;amp; ease of use). I &lt;em&gt;needed&lt;&#x2F;em&gt; HTTPS if I wanted people to send passwords through here - there’s nothing particularly important, and I’ve got the password hygiene not to use the same password everywhere but I can’t say that for all my users. Luckily, one of my very good friends (&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HandyHat&quot;&gt;HandyHat&lt;&#x2F;a&gt;) had experience here, and walked me through the entire setup of &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;Caddy&lt;&#x2F;a&gt; for Cloudflare using Reverse DNS to get HTTPS certificates.&lt;&#x2F;p&gt;
&lt;p&gt;You might’ve noticed that I’ve put all of my eggs into one basket - if Cloudflare goes down then I’m down. I understand the concern, but I also trust that if Cloudflare goes down then the one instance I run of Vent personally will be of little concerns.&lt;&#x2F;p&gt;
&lt;p&gt;I also chose to use a VPS here, rather than a Docker Container running on a &lt;a href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;products&#x2F;droplets&quot;&gt;Droplet&lt;&#x2F;a&gt; or something - this is for multiple reasons. First is that I’m definitely not just using the VPS for this so I save the more projects I use. I also find it insanely convenient to quickly fix small issues in things like SQL queries in production without needing some complicated deployment process - I just &lt;code&gt;ssh&lt;&#x2F;code&gt; in, edit the relevant file with &lt;a href=&quot;https:&#x2F;&#x2F;micro-editor.github.io&#x2F;&quot;&gt;&lt;code&gt;micro&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, then build the project and restart it in a &lt;code&gt;tmux&lt;&#x2F;code&gt; session I keep around.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;adoption&quot;&gt;Adoption&lt;&#x2F;h3&gt;
&lt;p&gt;Eventually, I started some user groups on the system and when nothing went wrong (apart from some misspelt usernames which were easily fixed) I went for the full rollout. Whilst some people still don’t mark themselves as planning to attend, it’s now the de-facto system and those people probably check when and where events are on the main page. I’m really happy with how it went.&lt;&#x2F;p&gt;
&lt;p&gt;No first plan survives contact with the enemy though, so I had to rapidly issue a few updates like publicly marking who uploads photos, and improving my logging infrastructure which at that point just forwarded whatever domain specific error it got from whatever caused the error via &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;thiserror&quot;&gt;&lt;code&gt;thiserror&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &amp;amp; the &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;tracing&quot;&gt;&lt;code&gt;tracing&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; ecosystem. You don’t want to know how long its taken to tune the logs 😔.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fun-technical-things&quot;&gt;Fun Technical Things&lt;&#x2F;h2&gt;
&lt;p&gt;You didn’t think I’d finish here, did you? Nah - I’ve got a few fun things which I’ll add to as I remember from the making of this project.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;threads-not-of-the-zuck-variety&quot;&gt;Threads (not of the Zuck variety)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;axum&lt;&#x2F;code&gt; has a &lt;code&gt;State&lt;&#x2F;code&gt; extractor you can use with all of your methods, and whilst from what I’ve seen most people don’t use it as a state manager and just use it as various components I’ve got it all tricked out. For example, I publish an ICS but don’t want the faff of re-making the file for every request (which definitely isn’t what I was doing for a while which caused event duplication issues 😉) so I have one persistent file that gets updated. How do I know when to update it? Every time an event gets updated in such a way that would affect the calendar, I call a function on the State which sends a blank message through a channel to the calendar updater.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve also got threads to delete old sessions (hopefully no longer needed in &lt;code&gt;axum-login&lt;&#x2F;code&gt; 0.7?), and send emails to users.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;templating&quot;&gt;Templating&lt;&#x2F;h3&gt;
&lt;p&gt;I’ve mentioned that I use liquid templating, but given no more insight than that. Currently, the partials get cached but the actual templates don’t (there’s an &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BurntNail&#x2F;vent&#x2F;issues&#x2F;180&quot;&gt;issue&lt;&#x2F;a&gt; and it’s next on my list after &lt;code&gt;axum-login&lt;&#x2F;code&gt; 0.7). The main reason for this is that &lt;code&gt;liquid&lt;&#x2F;code&gt; templates are entirely synchronous and the compiler is created in an environment with no way to access &lt;code&gt;async&lt;&#x2F;code&gt; APIs other than caching them beforehand 🤷, so if ever anyone looks at my code and gets confused then that’s why.&lt;&#x2F;p&gt;
&lt;p&gt;If you look over my templates, I’ve also got a couple of invariants (like people always being ordered by group in the view all page when logged in) that allow me to commit some &lt;em&gt;horrendous&lt;&#x2F;em&gt; crimes that make me giggle every time I look at them, and sigh every time I have to think about doing something with that part.&lt;&#x2F;p&gt;
&lt;p&gt;Having now got experience with liquid, I can say that it probably wasn’t the right choice - it can be annoyingly limited to work with (something like &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;handlebars&quot;&gt;&lt;code&gt;handlebars&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; might’ve been better in that respect), but I’m also happy to accept that it’s good enough and that maybe everything doesn’t always need to be perfect.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gotchas-for-future-me&quot;&gt;Gotchas for future me&lt;&#x2F;h2&gt;
&lt;p&gt;These are just a few pointers for people ever embarking on similar projects:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You need to setup a &lt;a href=&quot;https:&#x2F;&#x2F;developers.cloudflare.com&#x2F;support&#x2F;page-rules&#x2F;understanding-and-configuring-cloudflare-page-rules-page-rules-tutorial&#x2F;&quot;&gt;page rule&lt;&#x2F;a&gt; to turn off SSL for &lt;code&gt;DOMAIN&#x2F;.well_known&#x2F;acme_challenge&#x2F;*&lt;&#x2F;code&gt; because that prevents Caddy from setting up the certificate.&lt;&#x2F;li&gt;
&lt;li&gt;Linode blocks email-related ports (presumably for spam&#x2F;DDOS reasons?) and doesn’t ever say clearly (just in some &lt;a href=&quot;https:&#x2F;&#x2F;www.linode.com&#x2F;blog&#x2F;linode&#x2F;a-new-policy-to-help-fight-spam&#x2F;&quot;&gt;random blog post&lt;&#x2F;a&gt;) so you need to contact support to get them unblocked.&lt;&#x2F;li&gt;
&lt;li&gt;If you’re tee-ing JSON logs into a file and then serving that file, you might need to parse that file and reverse all the elements because otherwise all the most recent logs (which are probably the important ones) are right at the bottom.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;axum::debug_handler&lt;&#x2F;code&gt; compiles to nothing in release mode - cover your project in them because all they’ll do is slightly increase compile times and they’ll massively help in errors.&lt;&#x2F;li&gt;
&lt;li&gt;Use &lt;a href=&quot;https:&#x2F;&#x2F;dbeaver.io&#x2F;&quot;&gt;DBeaver&lt;&#x2F;a&gt; - it’s insanely useful for quickly editing database records and doing other database-adjacent things like complete migrations.&lt;&#x2F;li&gt;
&lt;li&gt;People aren’t joking about backups - you wouldn’t believe how easy it is to completely accidentally wipe something important from (or just wipe the whole) production database. It doesn’t matter how many flags you’ve setup in &lt;code&gt;DBeaver&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.hostinger.co.uk&#x2F;&quot;&gt;Hostinger&lt;&#x2F;a&gt; can shut off servers with too high activity - make sure to double check that doesn’t happen to you, because I didn’t get emailed about it or realise until I checked wanting to see the events and saw that production was down because &lt;code&gt;Docker&lt;&#x2F;code&gt; was being screwy.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
    </channel>
</rss>
