<?xml version="1.0" encoding="UTF-8" standalone="yes"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" ><channel><title>Rismosch</title><atom:link href="https://www.rismosch.com/rss.xml" rel="self" type="application/rss+xml" /><link>https://www.rismosch.com</link><description>Blog and Project-Collection of Simon Sutoris</description><lastBuildDate>Tue, 17 Feb 2026 19:59:11 +0100</lastBuildDate><image><url>https://rismosch.com/favicon.png</url><title>Rismosch</title><link>https://www.rismosch.com</link><width>32</width><height>32</height></image><item><title>The case for porting to Wii</title><link>https://www.rismosch.com/article?id=the-case-for-porting-to-wii</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">the-case-for-porting-to-wii</guid><pubDate>Tue, 17 Feb 2026 11:58:34 +0100</pubDate><description>I have this brainfart of an idea that I just can't get rid of.</description><content:encoded><![CDATA[<p>When writing a game engine, one thing you start to appreciate is the
simple UI of existing engines, like Unity. For example, adding a new
render target is as simple as attaching a camera to any game object.
Knowing how this stuff works under the hood, supporting multiple cameras
seems to me like an absolute nightmare to implement. The logistics are
the main problem: You require a render pass for each camera. Each one is
probably configured differently. A single hardcoded pass is already
difficult enough to set up. But having it be dynamically controlled?
That's something you don't build on a whim.</p>
<img src="https://rismosch.com/articles/the-case-for-porting-to-wii/unity.png" style="display: block; margin: auto; max-width: 100%;">
<p>Don't get me wrong, I like my engine. But at times I get lost in the
details, and I yearn for simpler times.</p>
<p>An idea that I've had last year, was to port my engine to the
Nintendo Wii. This appears to be a brainfart, but the more I think about
it, the more serious I am considering it.</p>
<p>My current biggest headache is the fact that I have no system
requirements. You see, if my engine were ever to produce a game, I would
like to have it run on as many machines as possible. No matter how
garbage your hardware, my game should be able to run on that.</p>
<p>I won't be able to go as low as the original Doom. It is a
masterpiece of programming, and it smartly took a lot of shortcuts to be
able to run on pretty much everything that has a processor. But exactly
because of these shortcuts, the graphics are too low fidelity for what I
want to do. I assume everyone who would like to play my game has a
machine that is capable to render much more complicated scenes.</p>
<img src="https://rismosch.com/articles/the-case-for-porting-to-wii/doom.jpg" style="display: block; margin: auto; max-width: 100%;">
<p>Anyway, I still want to depend on as little system requirements as
possible. If that sounds vague, well, that is because it is. I repeat
myself: I have no system requirements. I have no idea on what hardware I
need, to run my future game. And this causes me mental pain.</p>
<p>I could lean on <a
href="https://en.wikipedia.org/wiki/Wirth%27s_law" target="_blank" rel="noopener noreferrer">Wirth's law</a>, but
where's the fun in that?</p>
<p>I am reading up on cool rendering techniques all the time. Expensive
ones, that create high fidelity with little or no required consideration
for asset creation. But many new cool features require compute shaders.
If your GPU can't run these, then your out of luck. Virtually all modern
GPUs support compute shaders, but embedded systems often don't. And I
simply don't have the foresight to predict how platforms are going to
look like in 10 or more years. Especially with AI currently ruining
everything.</p>
<p>At this moment, I am betting everything on Vulkan. Its main criticism
is its verbosity. And even though I like the control, the complexity is
starting to drain on me. It is so much work to get something to render.
And this is motivation enough for people to leave. If Vulkan gets too
unpopular, support will end and future hardware won't run anything that
uses it. OpenGL is still kicking, but it is approaching its end more and
more, and I fear Vulkan will face the same fate.</p>
<p>It's a similar story with the OS. You can completely forget Apple and
Android, as they require binaries to be built for specific hardware
versions. Longevity is not achievable there. Linux isn't better, as its
OS protocols are in constant flux, meaning any binary you distribute
won't work on different/newer distros. Windows is stable, and Microsoft
has put in great effort into backwards compatibility. However,
considering how much slop that company has produced in the last year, I
have no trust that Windows will keep being stable.</p>
<p>With such unstable platforms, and me having no idea about system
requirements, I am seriously doubting whether PC should be my primary
target.</p>
<img src="https://rismosch.com/articles/the-case-for-porting-to-wii/wii.jpeg" style="display: block; margin: auto; max-width: 100%; width: 300px">
<p>Enter console gaming. Consoles have fixed hardware. Their chipset is
known and well defined. As long as hardware of a console exists, code
for it will keep runnning. People aren't ditching consoles, like they
are changing parts in a PC. People even go to great efforts to preserve
them. Also, emulators exist, making console games playable everywhere
where an emulator runs. And people are building new hardware,
specifically to physically emulate the original stuff.</p>
<p>So why exactly the Wii? Simply put: Nostalgia. I have very fond
memories on playing on the Wii. And I think it's capable enough for what
I have in mind.</p>
<p>I've been following <a href="https://www.youtube.com/@KazeN64" target="_blank" rel="noopener noreferrer">Kaze
Emanuar</a> and his rewrite of Super Mario 64. He is a prime example how
non-dead development for the Nintendo 64 is. I don't see why the Wiis
story would be different. This is especially true, since the Wii sold
more units than the Nintendo 64.</p>
<p>But, porting to the Wii comes with great drawbacks.</p>
<p>First, I need to rewrite my entire engine, or most of it. This would
be a lot of work, but a part of me thinks this would be manageable. Much
of the work has been gone in learning game engine architecture, not
writing it. By that I mean, if I were to start anew, reaching the point
I am standing now will take significantly less time, than all the time I
have already spend to get here.</p>
<p>The second and probably bigger drawback is, that I would need to
switch to C. <a href="https://github.com/rust-wii/ogc-rs" target="_blank" rel="noopener noreferrer">A Rust port
for Wii libraries exists</a>, but over a weekend I only managed to run a
Hello World triangle on the <a href="https://dolphin-emu.org/" target="_blank" rel="noopener noreferrer">Dolphin
Emulator</a>, not on original hardware. The error surely is on my side
somewhere, but the <a href="https://wiibrew.org/wiki/DevkitPPC" target="_blank" rel="noopener noreferrer">homebrew
compiler</a> just worked out of the box.</p>
<video style="width: 300px; max-width:100%; display: block; margin: auto;" loading='lazy' controls>
<source src="https://rismosch.com/articles/the-case-for-porting-to-wii/hello_world.mp4" type="video/mp4">
</video>
<p>This whole situation is kind of ironic. I previously <a
href="https://www.rismosch.com/article?id=rust-is-the-future" target="_blank" rel="noopener noreferrer">glazed
Rust</a> and talked about how <a
href="https://www.rismosch.com/article?id=the-empty-mind-between-milestones" target="_blank" rel="noopener noreferrer">I
don't understand why someone would rewrite their engine from
scratch</a>. And now I find myself exactly in the situation where I am
considering to drop Rust and rewrite everything. Fucking hypocrite.</p>
<p>Now, I haven't written C since university, and I am definitely
looking at it through rose tinted glasses. Ultimately I think Rust is
the better language, because of it's very strict typing and compiler
guarantees. But at the very least I imagine C to be much better than
C++. I hate C++. I dread it everytime I have to use it.</p>
<p>In any case, I am standing at a crossroad. Continuing with Rust would
be the easy choice. I already have a somewhat working engine, even if it
isn't feature complete. Working on that is the way of least resistance,
and it wouldn't require me to throw my entire progress into the garbage
bin. However, having a game run on the Wii would be hella cool.</p>
<p>These thoughts sprung into my head recently, probably because I
haven't written a single line of code this year. This gives me time to
think. Actually, I have been learning Blender, and I started to make
actual assets for my game. Here's a character I am currently
modelling:</p>
<img src="https://rismosch.com/articles/the-case-for-porting-to-wii/progress.png" style="display: block; margin: auto; max-width: 100%;">
<p>The closer I get to being feature complete, the less excuses I have
to finally start working on assets. For example, I previously postponed
the game object system almost an entire year. I did so, because of the
fear that with it completed, I had to actually make something
presentable. Working on a game engine is a very safe space to be in
mentally. I can have a superiority complex, without actually producing a
sellable product.</p>

<blockquote style="background-color:var(--pico-8-white); border: 5px solid var(--pico-8-cyan); padding: 20px;">
    <p>🤓 "Since I am making an engine and you don't, I am automatically better than you" \s</p>
</blockquote>

<p>But I did actually finish the game object system, and assets are
still waiting to be made. Turns out there is much more to a working game
than just game objects.</p>
<p>My current roadmap involves finishing to model the character in
Blender, including rigging, UV mapping and texturing. Then I'd like to
implement materials, followed by bones, skinned meshes and animations.
Somewhere I'd also like to work on lighting and shadows. And the terrain
renderer should finally be implemented.</p>
<p>This roadmap is absolutley subject to change. (Which it already has
as I am working through the C book…) And if I am going to switch to Wii,
then it will definitely delay everything else. But once the character is
done, we'll see if I actually try to switch, or if I'm too big of a
pussy to try.</p>
<p>Wish me luck!</p>
]]></content:encoded></item><item><title>The empty mind between milestones</title><link>https://www.rismosch.com/article?id=the-empty-mind-between-milestones</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">the-empty-mind-between-milestones</guid><pubDate>Tue, 18 Nov 2025 15:08:33 +0100</pubDate><description>A retrospective on my development journey thus far.</description><content:encoded><![CDATA[<p>Everyone says don’t make a game engine. It’s too much work. But no
one is telling you how much work it actually is. I am not going to argue
why you would write a game engine in the first place; I’ve done that
already <a
href="https://www.rismosch.com/article?id=why-i-make-my-own-game-engine" target="_blank" rel="noopener noreferrer">here</a>.</p>
<p>Overall, the progress feels fractal-like.</p>
<p>Making a custom game is easy actually! You just need two steps:</p>
<p>First, make the engine!<br />
Second, make the game!</p>
<p>So you get to work and consider the structure of your main loop. You
work out how startup and shutdown happens. You are feeling fancy and
make a restart mechanism. Nice. The mainloop runs 3 things: input,
logic, output. And you gotta find out how these 3 talk to each
other.</p>
<p>Okay. Let’s do one by one.</p>
<p>In the input you figure out how to handle HIDs and how to remap them
to usable actions. You even implement some custom rebind system, that
allows the user to rebind controls if they choose to do so. Then you
might also think about handling multiple controllers. You might also
think to implement an input buffer, for combos and such. Maybe even
consider rollback code. But that’s a lot of work, and since you are not
planning to make anything multiplayer, let alone competitive
multiplayer, any further consideration is out of scope and wont be
touched whatsoever.</p>
<p>Then you do logic. You want gameobjects. People talk about ECS a lot.
It’s where the money is at. But to this day you don’t understand it and
you think it’s a buzzword. Same with anything procedural. Man, the
internet loves the word “procedural”. Here’s a fun game: Spend some time
in the indiedev-wannabe circles and see how far you come before
encountering the word.</p>
<p>Anyway, you set your requirements. You want your gameobjects to be
flexible, extensible and performant. You go with flat arrays internally,
for cache locality. Ints as ids, for the fastest lookup possible. But
this is were it bites you, because of course you are one of the weird
kids and chose to build the engine in Rust. And Rust really doesn’t like
what concept you have cooked up. But after much pain you have a working
prototype, which (hopefully) is as expansible as you think it is. But
you won’t test it now. You’ll maybe get to it in 2 years.</p>
<p>Oh, what about output? Ah, that’s were you draw them pixels. You
already spent the better part of a year working on this thing and have
yet to display something. Because you have a phobia of external
libraries, you are going to implement all the math yourself. Vectors,
matrices and the beloved quaternions. Especially because you did not
choose C++, and all the Rust libraries today are ass anyway, you
convince yourself that writing it yourself is better. You make a flying
camera, a single cube, that’ll do it.</p>
<p>You want debugging, so you implement Dear ImGUI. A bit hacked
together. Can’t use any existing bindings, because your renderer is
custom. So the ImGUI implementation has to be custom as well. Anyway,
let’s draw some gizmos. Like primitive lines, that’ll make debugging a
later game very easy. Also write a gizmo for 3d text. You say to
yourself this is absolutely necessary. The renderer you have written a
year ago is ass, so it needs to be rewritten. No biggy, gives you the
opportunity to use a better Vulkan wrapper. You hate the previous Vulkan
wrapper you used, surely Vulkan wrapper 2.0 is better. Once the new
wrapper is implemented, you get back to the gizmos, and implement them.
They are ugly as hell, but they do their job. You imagine yourself using
that in the upcoming game you will write. But we will see about that in
2 years.</p>
<p>Also write a benchmarking tool. It produces HTML. It looks beautiful.
This will definitely be helpful. In 2 years.</p>
<p>But then you realize that all this debugging takes a lot of
performance. A shipped game is not going to require all of this, and
stripping it out will massively improve performance. So you look into
conditional compiling and guard every debug feature behind some
preprocessor. It works, and you are proud of how many frames you get in
an empty scene.</p>
<p>Anyway, time to display some meshes. Fuck, we need to load these in
first. So you roll up your sleeves and write an asset system. Turns out
all common file formats suck and none are optimized for fast loading.
So, you make your own serialization and tinker on an entire asset
pipeline, which is capable to convert editor assets to fast loading
runtime assets.</p>
<p>Also write an asset compiler. Because you see, IO is expensive, and
having a single handle to a file is faster. At least that’s what is
claimed, you have yet to do benchmarks. Damn, if only you had a
benchmarking tool to test that. Oh well. The compiled thing is a single
huge file that holds everything. It has a lookup! Which makes indexing
very very fast. Flat arrays for the win.</p>
<p>After some time later you have a barely working asset system. So lets
get back to meshes and load them. What kind of format are you going to
implement anyway? glTF. That seems to be the standard. So you read the
glTF spec from start to finish and write an importer that converts glTF
to your mesh format. It’s like a year since you first wanted to render
meshes, but now you finally have all the systems to do so. Hurray!</p>
<p>Eventually you say to yourself that you should start to make the
game, no? But what’s missing? Oh, not much:</p>
<ul>
<li>any gameplay logic</li>
<li>level loading</li>
<li>character movement controllers</li>
<li>skinned meshes</li>
<li>skeletons</li>
<li>animation systems</li>
<li>lighting (bruh)</li>
<li>sound</li>
</ul>
<p>Wait, sound? You produced songs in the past! You literally describe
yourself as a music enthusiast and you have yet to do anything sound
related? Well… it isn’t important for the prototype, so it’s shelved.
It’s been shelved for so long actually, that you are starting to wonder
if your musical ability took a hit. Anyway, that’s not important for
now, so let’s start making the game.</p>
<p>But oh no, you want the character to stand on something. We gotta
make the floor first. Prototype is shelved, it’s time for terrain
generation baby! This can’t be that difficult! 4 months later you
finally have a terrain generator finished, and have yet to render it.
God dammit. Time to finally implement materials and lighting. Why now?
Because if you were to write the terrain renderer now, you will have to
rewrite it <em>again</em> once your entire render pipeline has to be
adapted for materials. So the terrain has to wait.</p>
<p>You look back at the goal you set this year. You wanted to have a
playable prototype and yet you spent half of the year on a fancy <a
href="https://github.com/Rismosch/ris_terrain_generator" target="_blank" rel="noopener noreferrer">picture
generator</a>.</p>
<p>Anyway, how does the engine look like?</p>
<img src="https://rismosch.com/articles/the-empty-mind-between-milestones/engine_screenshot.png" alt="screenshot of the engine" style="display: block; margin: auto; max-width: 100%;"/>
<p><em>Sigh…</em></p>
<p>Looking at the screenshot fills you with dread. It encapsulates the
last 3 years of your life. How can so much work look like nothing? You
went the walk, you know all the shit that is required to display that
damn image above. Getting to this point is not easy. And yet, it’s
demoralizing. To be fair, you have a fulltime job and thus not much
freetime. But still.</p>
<p>You check online, to see how others are doing. People are posting
their game engines, and most often you just scoff at them. There exist
only 3 emotions:</p>
<ol type="1">
<li>The poster did not post their source code. You feel apathy and
disrespect towards them.</li>
<li>The poster did post their source code, but you quickly realize it’s
just an ECS library glued to a renderer library. Sometimes it even uses
ImGUI. How nice. You clone the repo, remove all third party libraries,
run it through a sloc counter and reveal that the repo has at most 2000
lines of code. Your engine has 39k, many of which have been beaten to
death, rewritten multiple times, so you are obviously better. Their
screenshots look nice, better than yours. But <em>actually</em> you are
superior, because <em>technically</em> they haven’t written their
“engine”.</li>
<li>The poster actually has something to show, and this is their
thousandth update. You give it an upvote, nod in approval, but spend no
longer than 10 seconds before going back to your own shit.</li>
</ol>
<hr />
<p>The progress really feels like a fractal.</p>
<p>Every tangent, no matter how small it seems, is a major rabbit hole,
with tangents on its own. I have written the paragraphs above in the
you-narrator, but it’s basically me. I’ve described my journey in a not
so chronological order. At every step in the journey, you think you just
need to take one step further, only to reveal that between your current
position and the step you wanted to take are 100 more steps that you
were oblivious to previously.</p>
<p>After all that work I have many loosely connected systems, which by
some sort of miracle have not yet collapsed under their own weight. This
is either a testament to my software architecture skills, or luck.
Anyway, everything still needs to be stresstested, which I still haven’t
done, because there is always a new system to write.</p>
<p>There is one somewhat common kind of post you’ll find in game engine
dev circles: People rewriting their <em>entire</em> engine. I just can’t
relate to that. There is too much stuff going on. Besides, <a
href="https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/" target="_blank" rel="noopener noreferrer">rewriting
your code is one of the worst things you can do as a software
developer</a> (if we are considering that you are not doing some
crypto/AI bullshit, scamming and actually hurting people). Like, sure, a
rewrite can make things easier when implementing new features. For
example when I am finally getting to implement skinned meshes,
materials, lighting, MDI, then my scene renderer is going to face a lot
of refactoring. But you know what doesn’t have to change? My gizmo and
ImGUI renderers. My startup-, shutdown- and restart logic does not need
to be touched. My gameobjects will function exactly the same.</p>
<p>Often I’ve heard the saying that this kind of work is a marathon, not
a sprint. However, I don’t agree with that idea. More fitting is like
that meme of the guy who climbs a mountain, only to realize it goes up
further:</p>
<img src="https://rismosch.com/articles/the-empty-mind-between-milestones/climbing.jpg" alt="climbing meme" style="display: block; margin: auto; max-width: 100%; width: 400px;" />
<p>Each dip is a finished system. And reaching one is what I think
enlightenment feels like. Months of constant thoughts about a specific
problem. All the branching ideas I’ve tried, all the decisions I’ve
made. And when the system is done, the thoughts disappear. When before
my head was full of voices, now it’s dead silent. It’s these moments
where there’s not a single thought in my mind. I am literally thinking
of nothing. It is bliss.</p>
<img src="https://rismosch.com/articles/the-empty-mind-between-milestones/now_what.jpg" alt="sisyphus reached the top meme" style="display: block; margin: auto; max-width: 100%; width: 400px;" />
<p>But the journey is not over, and after a few days the climb
continues. You take the courage, touch the boulder again and start
pushing. A new system is started or work on a current one proceeds, and
my head begins to fill with thoughts again.</p>
<img src="https://rismosch.com/articles/the-empty-mind-between-milestones/sisyphus.png" alt="sisyphus meme" style="display: block; margin: auto; max-width: 100%; width: 400px;" />
<p>One last thought: “I have to write everything on my own” is a
delusional idea. Let’s get back down to reality. This year at SIGGRAPH
2025 I met someone who is writing a Vulkan driver. I thought I was low
level, and yet this person does me one better. But after much
discussion, even they had to admit that you truly can’t write everything
on your own.</p>
<p>You are working with a programming language and its tooling. Someone
had to make that. You are working with a text editor and operating
system. And you are working with a computer, someone had to build that.
And I don’t mean stick the parts together. No, I mean someone had to
make the chips on these circuit boards. But even if you are doing a <a
href="https://www.youtube.com/@BenEater" target="_blank" rel="noopener noreferrer">Ben Eater</a> and literally
build your own computer, you still have to admit one crucial detail: You
are building on top of the <em>knowledge</em> of the ones before you.
You are not going to reinvent the graphics pipeline. You will learn how
it’s done and then give your own spin on it.</p>
<p>We are really standing on the shoulders of giants.</p>
<p>I am not saying that as an argument against building an engine. My
journey gave me understandings and proficiencies most other developers
don’t have. But it’s an anchor in reality that one should not lose.</p>
]]></content:encoded></item><item><title>How to create your own binary format</title><link>https://www.rismosch.com/article?id=how-to-create-your-own-binary-format</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">how-to-create-your-own-binary-format</guid><pubDate>Tue, 08 Apr 2025 14:24:57 +0200</pubDate><description>In this blogpost I am going over on how to go about creating your own custom binary format. It isn't difficult and the process is quite fast, I promise.</description><content:encoded><![CDATA[<p>So you want to serialize data. Chances are you considered some formats already, like JSON, YAML, XAML or something of that sort. Well, what about binary? Don't be scared. A custom binary format isn't that difficult to implement! Sure, there is an initial learning bump, but at the end of this post, you can do this easily yourself. And in terms of size and speed, a custom written serializer easily beats a general one.</p>

<p>I wanted to write this post for quite some time now, but I never wrote my thoughts down. Then my coworker specifically asked me about serialization. So you can thank him for the existence of this post. Thank you Mark :)</p>

<h2>The problem</h2>

<p>What are we even trying to do? What even is a binary format? Simply put, a binary format is an array of bytes. Nothing more, nothing less. Classes, structs and objects cannot be saved as files. Neither can they be sent over a network. Why that is, is complicated and out of scope of this blog post. (They keyword here is ABI.) Regardless, what is important is that a byte array CAN be saved or sent. So our challenge will be to find a solution, that translates our object into a byte array and back.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/problem.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;">

<p>Shouldn't be too difficult.</p>

<p></p>

<h2>What's a stream?</h2>

<p>Before we start with any kind of serialization, we should be talking about streams. We aren't going to modify the byte array directly. That would be cumbersome and difficult. Instead, we are going to use a container known as a "stream". It will make our life so much easier.</p>

<p>A stream consists of two things: Data and a cursor. The data can be anything: A file, a websocket, a port, whatever. But most importantly for us, the data can be a byte array. The cursor is simply an integer, and it represents the current position in the data. Think of it like the head of a <a href="https://en.wikipedia.org/wiki/Turing_machine" target="_blank" rel="noopener noreferrer">Turing machine</a>. Or the stylus of a <a href="https://en.wikipedia.org/wiki/Phonograph" target="_blank" rel="noopener noreferrer">record player</a>. I'll use "cursor" and "position" interchangeable from here on. They are pretty much the same concept.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/stream.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;">

<p>I'll be using the visualization above for all further examples. The boxes represent the data, the byte array, where each cell is a single byte. The red arrow is the cursor, the current position of the stream.</p>

<p>A stream comes with 3 functions: <code class="code">Seek</code>, <code class="code">Read</code> and <code class="code">Write</code>. What these do and how they work in detail, we'll see in a moment. Streams come in many different flavors. Some are <i>read-only</i>, meaning they don't implement <code class="code">Write</code>. Some are <i>write-only</i>, meaning they don't implement <code class="code">Read</code>. For our purposes, we will be using a "MemoryStream". It stores bytes, and it implements all three methods.</p>

<p>Because we will be using a stream in pretty much every example, I want you to understand how a stream works. So we are going to implement one from scratch. It will be barebones, naive and straight forward, but for our use case it will suffice.</p>

<p>All code examples will be in C#, because C# is a language, which Mark can read. If you dear reader have never worked with C# before, then that is fine. We won't be using complicated syntax, so I hope you can follow along.</p>

<p>Let's start by defining our stream:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">private byte</span>[] <span style="color: var(--pico-8-green)">_data</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">private int</span> <span style="color: var(--pico-8-green)">_position</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_data</span> = <span style="color: var(--pico-8-brown)">Array</span>.<span style="color: var(--pico-8-purple)">Empty</span>&lt;<span style="color: var(--pico-8-cyan)">byte</span>&gt;();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_position</span> = <span style="color: var(--pico-8-pink)">0</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_data</span> = <span style="color: var(--pico-8-green)">value</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_position</span> = <span style="color: var(--pico-8-pink)">0</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public byte</span>[] <span style="color: var(--pico-8-purple)">ToArray</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">_data</span>.<span style="color: var(--pico-8-purple)">ToArray</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// todo:</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// seek</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// read</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// write</span><br>
}
</code>

<p>I prefixed the stream with "Ris", because I am weird and most of the types in my public code are prefixed with the first syllable of my name. It also helps to distinguish my types from others. Anyway, as discussed, the stream consists of two parts: The data and the cursor or position. I also implemented two utility methods, that allow us to create a stream from existing bytes, or to retrieve the bytes once we are done modifying the stream.</p>

<p>We have three more methods to implement. Let's do this!</p>

<h2>Seek</h2>

<p><code class="code">Seek</code> does two things: It modifies the position, and then it returns the position <i>after</i> it has been modified. Modifying the position works by adding an offset to one of three locations in the stream:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public enum</span> <span style="color: var(--pico-8-brown)">SeekFrom</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">Begin</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">Current</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">End</span>,<br>
}
</code>

<p>With this, we can implement the <code class="code">Seek</code> method:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public int</span> <span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-cyan)">int</span> <span style="color: var(--pico-8-green)">offset</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span> <span style="color: var(--pico-8-green)">seekFrom</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">switch</span> (<span style="color: var(--pico-8-green)">seekFrom</span>)</br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">case</span> <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Begin</span>:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_position</span> = <span style="color: var(--pico-8-green)">offset</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">break</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">case</span> <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Current</span>:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_position</span> += <span style="color: var(--pico-8-green)">offset</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">break</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">case</span> <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">End</span>:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_position</span> = <span style="color: var(--pico-8-green)">_data</span>.<span style="color: var(--pico-8-green)">Length</span> + <span style="color: var(--pico-8-green)">offset</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">break</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">default</span>:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">throw new</span> <span style="color: var(--pico-8-brown)">ArgumentOutOfRangeException</span>(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">nameof</span>(<span style="color: var(--pico-8-green)">seekFrom</span>),<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">seekFrom</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">null</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// clamp the position, in case it falls out of range</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">if</span> (<span style="color: var(--pico-8-green)">_position</span> &lt; <span style="color: var(--pico-8-pink)">0</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_position</span> = <span style="color: var(--pico-8-pink)">0</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">if</span> (<span style="color: var(--pico-8-green)">_position</span> &gt; <span style="color: var(--pico-8-green)">_data</span>.<span style="color: var(--pico-8-green)">Length</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_position</span> = <span style="color: var(--pico-8-green)">_data</span>.<span style="color: var(--pico-8-green)">Length</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">_position</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>There are a few things to note here. First, notice how the <code class="code">switch</code> treats <code class="code">SeekFrom</code> differently. When applying an offset to <code class="code">SeekFrom.Begin</code>, the offset is pretty much where you want the position to be. When using <code class="code">SeekFrom.Current</code>, we are simply adding the offset to the current position. When using <code class="code">SeekFrom.End</code>, we are adding the offset from the end of our currently held data.</p>

<p>Using positive and negative offsets, we can walk back and forth in the stream. Due to the clamp however, negative offsets on <code class="code">SeekFrom.Begin</code> and positive offsets on <code class="code">SeekFrom.End</code> have no effect.</p>

<p>Why are we clamping anyway? Well, the allowed range for the position is <code class="code">0</code> to <code class="code">_data.Length</code>. The bounds are inclusive. Everything outside that range is invalid. We want the stream to be valid in all cases, and thus we need to prevent the position from falling out of the valid range.</p>

<p>Hold on a sec, doesn't <code class="code">_position == _data.Count</code> mean that our cursor is now pointing outside of our array?</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/stream_end_1.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;">

<p>Yes. In this case it does indeed point outside the array. But this is fully intentional. It allows us to get the current length of the stream by calling <code class="code">Seek(0, SeekFrom.End)</code>. It also makes reading and writing straight forward. And it also means that when <code class="code">_data</code> is empty, <code class="code">_position</code> being <code class="code">0</code> is a valid state.</p>

<p>Clamping is one way to keep the stream valid. Another way would be to throw exceptions, that's what <a href="https://learn.microsoft.com/en-us/dotnet/api/system.io.memorystream?view=net-9.0" target="_blank" rel="noopener noreferrer"><code class="code">System.IO.MemoryStream</code></a> does. But I don't like exceptions, so I clamp.</p>

<p>Most commonly, seeking is used like this:</p>

<ul>
<li><code class="code">Seek(0, SeekFrom.End)</code> to get to the end to the stream and/or to get its length,</li>
<li><code class="code">Seek(position, SeekFrom.Begin)</code> to set the position directly, and</li>
<li><code class="code">Seek(0, SeekFrom.Current)</code> to get the current position of the cursor</li>
</ul>

<h2>Read</h2>

<p>Now let's see how to read from the stream. As a parameter, <code class="code">Read</code> takes an <code class="code">int</code> that specifies how many bytes should be read. It then reads that many bytes, advances the position, and returns the bytes.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/stream_read.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;">

<p>Here's the implementation:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public byte</span>[] <span style="color: var(--pico-8-purple)">Read</span>(<span style="color: var(--pico-8-cyan)">int</span> <span style="color: var(--pico-8-green)">count</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// clamp to ensure enough bytes to read</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytesLeftToRead</span> = <span style="color: var(--pico-8-green)">_data</span>.<span style="color: var(--pico-8-green)">Length</span> - <span style="color: var(--pico-8-green)">_position</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">if</span> (<span style="color: var(--pico-8-green)">count</span> > <span style="color: var(--pico-8-green)">bytesLeftToRead</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// not enough bytes</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// only read whats left</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">count</span> = <span style="color: var(--pico-8-green)">bytesLeftToRead</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// read the bytes, by copying them to a new array</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytes</span> = <span style="color: var(--pico-8-cyan)">new byte</span>[<span style="color: var(--pico-8-green)">count</span>];<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">Array</span>.<span style="color: var(--pico-8-purple)">Copy</span>(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_data</span>,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// source</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_position</span>,&nbsp;<span style="color: var(--pico-8-dark-grey)">// source index</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">bytes</span>,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// target</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-pink)">0</span>,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// target index</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">count</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// count</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// advance the cursor</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_position</span> += <span style="color: var(--pico-8-green)">count</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">bytes</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>First, we are clamping <code class="code">count</code>. Then we copy the requested number of bytes into a new array. At last, but not least, we update the position and return the read bytes.</p>

<p>Copy operations can be a bit intimidating for new programmers. I hope the example below clarifies things a bit better:</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/copy_1.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;">

<p>Let's talk about the clamp for a moment. It is there specifically to prevent client code to read more bytes than are actually left in the stream. Reading more bytes than are present is an invalid operation, and we must decide what to do in such a case. Clamping like this provides valid default behavior, but requires client code to validate, if as many bytes were read as expected. Another viable approach would be to throw an exception. The exception comes with the benefit, that no operation will take place. My implementation above will always allocate an array and copy into it, regardless if the operation is sensical or not. But clamping has the benefit that you can read all remaining bytes by calling <code class="code">Read(int.Max)</code> on our stream.</p>

<p>You may have also noticed that I am returning an array. You may find that common stream implementations pass an array as a parameter instead, expecting the read method to fill it. This is done to prevent unnecessary allocations. My implementation will allocate an array for every single read operation that you will make. But the tradeoff is that client code will be significantly simpler. If you want, as homework, you can try to rewrite the read method such that it will take an array as a parameter. Its signature should look like this:</p>

<code class="code code_block"><span style="color: var(--pico-8-cyan)">public int</span> <span style="color: var(--pico-8-purple)">Read</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">buffer</span>, <span style="color: var(--pico-8-cyan)">int</span> <span style="color: var(--pico-8-green)">count</span>)</code>

<p>The returned <code class="code">int</code> is to indicate how many bytes were actually read. Whether you opt for a clamped- or exception-based error behavior (to prevent too many bytes being read), even a successful read may not fill your entire array. So make sure to return an <code class="code">int</code> to notify the client code.</p>

<p>Before we continue, I again want to stress that <code class="code">_position == _data.Count</code> is a valid state, in which our stream can find itself in. Assume for a moment that it wasn't, how would you determine if there are bytes left to read?</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/stream_end_2.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;">

<p>If we allow <code class="code">_position == _data.Count</code> to be valid, then things become very easy:</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/stream_end_3.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;">

<h2>Write</h2>

<p>Two of three methods implemented. Now let's look at <code class="code">Write</code>. <code class="code">Write</code> puts bytes into the stream at the position of the cursor, and then advances the cursor.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/stream_write.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;">

<p>Notice that writing can both grow the stream, as well as overwrite existing bytes.</p>

<p>I want to stress one last time that <code class="code">_position == _data.Count</code> is completely valid. If the cursor is at the very last position of the stream, then being outside the array allows us to append to the stream without overwriting anything:</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/stream_write_append.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;">

<p>This also allows appending onto an empty stream, without compensating for any edge cases when implementing it. <code class="code">_position == _data.Count</code> is indeed a very useful hack and very useful behavior a stream can have.</p>

<p>Enough yapping, let's see the implementation:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public void</span> <span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ensure the capacity is big enough</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">requiredCapacity</span> = <span style="color: var(--pico-8-green)">_position</span> + <span style="color: var(--pico-8-green)">value</span>.<span style="color: var(--pico-8-green)">Length</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">if</span> (<span style="color: var(--pico-8-green)">_data</span>.<span style="color: var(--pico-8-green)">Length</span> &lt; <span style="color: var(--pico-8-green)">requiredCapacity</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// capacity is not big enough</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// create an array that is big enough</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// copy the old into the new one</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">newDataArray</span> = <span style="color: var(--pico-8-cyan)">new byte</span>[<span style="color: var(--pico-8-green)">requiredCapacity</span>];<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">Array</span>.<span style="color: var(--pico-8-purple)">Copy</span>(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_data</span>,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// source</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">newDataArray</span>,&nbsp;<span style="color: var(--pico-8-dark-grey)">// target</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_data</span>.<span style="color: var(--pico-8-green)">Length</span>&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// count</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_data</span> = <span style="color: var(--pico-8-green)">newDataArray</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// write by copying the values into the array</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">Array</span>.<span style="color: var(--pico-8-purple)">Copy</span>(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">value</span>,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// source</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-pink)">0</span>,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// source index</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_data</span>,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// target</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_position</span>,&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// target index</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">value</span>.<span style="color: var(--pico-8-green)">Length</span>&nbsp;<span style="color: var(--pico-8-dark-grey)">// count</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// advance the cursor</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">_position</span> += <span style="color: var(--pico-8-green)">value</span>.<span style="color: var(--pico-8-green)">Length</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>First, we check whether our stream has enough bytes left to hold the data. If not, we must grow it. This is done by allocating a new array, which is big enough to hold all data, and then copying the old array into the new one. Then, we can copy the actual value into our data array.</p>

<p>Again, copy operations may intimidate the new programmer, so let's visualize them too. Here's an example for resizing the array:</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/copy_2.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;">

<p>And here is an example for copying the value into the array:</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/copy_3.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;">

<p>And that's it. This is everything that we are going need. A full implementation can be found here: <a href="https://github.com/Rismosch/RisSerialization/blob/main/RisSerialization/RisMemoryStream.cs" target="_blank" rel="noopener noreferrer">LINK</a></p>

<p>You may have noticed that I did not implement the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.io.stream?view=net-9.0" target="_blank" rel="noopener noreferrer">base class</a>. This is on purpose. I am targeting the lowest denominator of readers, and <code class="code">System.IO.Stream</code> is a tad too complicated for my taste. Also, we don't need the entire thing for the following chapters. The methods we have are enough for our use case.</p>

<p>If you are feeling confident in your ability, I leave the implementation of <code class="code">System.IO.Stream</code> as homework for you. Implementing the base class comes with the obvious benefit, that you can use all utility methods for streams on your stream as well.</p>

<p>I am going to use <code class="code">RisMemoryStream</code> for the following chapters. You are allowed to use your stream from your homework. You are also allowed to use <a href="https://learn.microsoft.com/en-us/dotnet/api/system.io.memorystream?view=net-9.0" target="_blank" rel="noopener noreferrer"><code class="code">System.IO.MemoryStream</code></a> from the standard library, which has a much more sophisticated implementation, with all the bells and whistles.</p>

<h2>Serialization: Baby Steps</h2>

<p>Let me introduce you to a new static class:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public static class</span> <span style="color: var(--pico-8-brown)">RisIO</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static int</span> <span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-cyan)">int</span> <span style="color: var(--pico-8-green)">offset</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span> <span style="color: var(--pico-8-green)">seekFrom</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">s</span>.<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">offset</span>, <span style="color: var(--pico-8-green)">seekFrom</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static byte</span>[] <span style="color: var(--pico-8-purple)">ReadUnchecked</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-cyan)">int</span> <span style="color: var(--pico-8-green)">count</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">s</span>.<span style="color: var(--pico-8-purple)">Read</span>(<span style="color: var(--pico-8-green)">count</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static byte</span>[] <span style="color: var(--pico-8-purple)">Read</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-cyan)">int</span> <span style="color: var(--pico-8-green)">count</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-purple)">ReadUnchecked</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">count</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">if</span> (<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">Length</span> != <span style="color: var(--pico-8-green)">count</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">throw new</span> <span style="color: var(--pico-8-brown)">ArgumentOutOfRangeException</span>(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">nameof</span>(<span style="color: var(--pico-8-green)">count</span>),<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">count</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">null</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static void</span> <span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">s</span>.<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>You may be asking: Is it really necessary to wrap these methods? No, it isn't necessary. But I like to have a uniform API. By wrapping them, regardless if we are reading/writing raw bytes or values like <code class="code">int</code>s and <code class="code">float</code>s, the calls will always look very similar: <code class="code">RisIO.ReadX(stream)</code> or <code class="code">RisIO.WriteX(stream, value)</code>. (This will be especially true when we are modifying them a bit later.)</p>

<p>Notice however, that I am throwing an exception in the read method. That is because <code class="code">Read</code> represents a checked operation, meaning it must produce an error if things don't go as expected. Unfortunately, error handling is difficult. And C# is not Rust. So despite me not being the biggest fan of exceptions, I will be falling back to them when the situation calls for it. <code class="code">ReadUnchecked</code> does no checks, and thus client code is at the mercy of whatever error handling the underlying stream uses. <code class="code">Read</code> is a safe alternative. Also notice that <code class="code">Read</code> does not catch the exception of the underlying stream. That is intentional, because exception is exception, regardless of who threw it. In any case, the client is notified on an error, which is good enough for us.</p>

<p>For you C++ nerds out there, yes, this isn't strongly exception safe. If you know what I mean by this, then you are clearly above my target audience. I leave it as a challenge for the reader to argument why it doesn't fulfill the strong exception safety guarantee.</p>

<p>I think strong exception safety isn't of importance here, as I consider any exception a failed deserialization. I like my programs to burn and crash on a (truly) unexpected error. We will generate streams on the fly, and none should outlive a serialization operation. If this bothers you, you can write strong exception safe implementations for this and all the coming methods. I will stick with simpler implementations, even if they are less rigorous.</p>

<h2>Integers</h2>

<p>Now let's serialize some data! Took us quite a while.</p>

<p>Since classes and structs are made from smaller types, let's see how these smaller types are serialized. Starting with the humble integer. On most platforms, including C#, an <code class="code">int</code> is made up of 32 bits or 4 bytes. So all we need to do is to retrieve these 4 bytes and then put them into our read/write methods. That should be easy. Right?</p>

<p><b>Jump scare: Endianness</b></p>

<p>Immediately, even before we serialize our first thing, we are met with an obstacle. Unfortunately, this won't be our last &#128531;</p>

<p>So what is endianness? Let me answer that question with an example and another question: The <code class="code">int</code> <code class="code">730797131</code> is comprised of the bytes <code class="code">43</code>, <code class="code">143</code>, <code class="code">20</code> and <code class="code">75</code>. Now, in which order should we store it?</p>

<code class="code code_block">
43, 143, 20, 75
</code>

<p>Or?</p>

<code class="code code_block">
75, 20, 143, 43
</code>

<p>As it turns out, both approaches are valid and reasonable. So now we are left to choose. Of course we could also scramble them, but that assumes that we know in which order the unscrambled bytes should be. You see, this is a CPU problem, and endianness determines in what byte order different CPUs represent a number. We must solve this. Chances are, that our binary format is stored as a file or sent as a package over the internet, read by a different computer that has a different endianness.</p>

<p>Since there are two orders, there are two types of endianness: Big-endian and little-endian. To figure out which is which, we need to look at the first and the last byte of our number. Sticking with the example <code class="code">730797131</code>, then <code class="code">43</code> is the "most significant byte" (MSB) and <code class="code">75</code> is the "least significant byte" (LSB). <code class="code">43</code> is the MSB, because it has huge effect on the number. On the other hand, <code class="code">75</code> is the LSB, because it has little effect. Look at what happens to <code class="code">730797131</code> when you add <code class="code">1</code> to either the MSB or LSB:</p>

<code class="code code_block">
43, 143, 20, 75 =&gt; 730797131<br>
43, 143, 20, <span style="color: var(--pico-8-red)"><u>76</u></span> =&gt; 73079713<span style="color: var(--pico-8-red)"><u>2</u></span><br>
<span style="color: var(--pico-8-red)"><u>44</u></span>, 143, 20, 75 =&gt; 7<span style="color: var(--pico-8-red)"><u>47574347</u></span>
</code>

<p>Adding <code class="code">1</code> to the LSB only adds <code class="code">1</code> to the whole number. Adding <code class="code">1</code> to the MSB however adds <code class="code">2^24</code>, which equals <code class="code">16777216</code>!</p>

<p>Here's why that's important: If you store the MSB first, you are using big-endian. If you are storing the LSB first, then you are using little-endian. A good way to remember this: If you are storing the big byte first, you are using big-endian.</p>

<p style="text-align: center">: ^)</p>

<p>What you choose is up to you. But whatever you do, stay consistent. Most modern mainstream CPUs use little-endian. But there exist exceptions, notably embedded systems. Older hardware might also use big-endian.</p>

<p>Let's see how this actually looks like in code:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public static class</span> <span style="color: var(--pico-8-brown)">RisIO</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static int</span> <span style="color: var(--pico-8-purple)">ReadInt</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytes</span> = <span style="color: var(--pico-8-purple)">Read</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-pink)">4</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">FixEndianness</span>(<span style="color: var(--pico-8-green)">bytes</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-brown)">BitConverter</span>.<span style="color: var(--pico-8-purple)">ToInt32</span>(<span style="color: var(--pico-8-green)">bytes</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static void</span> <span style="color: var(--pico-8-purple)">WriteInt</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-cyan)">int</span> <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytes</span> = <span style="color: var(--pico-8-brown)">BitConverter</span>.<span style="color: var(--pico-8-purple)">GetBytes</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">FixEndianness</span>(<span style="color: var(--pico-8-green)">bytes</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytes</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static void</span> <span style="color: var(--pico-8-purple)">FixEndianness</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// we are using little-endian</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// if our cpu is not little-endian, flip the bytes</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">if</span> (!<span style="color: var(--pico-8-brown)">BitConverter</span>.<span style="color: var(--pico-8-green)">IsLittleEndian</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">Array</span>.<span style="color: var(--pico-8-purple)">Reverse</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>Whenever you are dealing with raw bytes, you must keep endianness in mind. If you have ever read a spec before, which deals with raw bytes, then you know that they always mention what endianness their format uses. Well, at least every spec I've ever read mentioned it. Also, you can directly toggle endianness in most hex editors.</p>

<h2>Hex editors</h2>

<p>Speaking of hex editors, when writing your own binary format, you should probably start using one. To debug your binary format, you can simply write your serialized bytes into a file and then open that file with the hex editor of your choice. On windows I am using <a href="https://mh-nexus.de/en/hxd/" target="_blank" rel="noopener noreferrer">HxD</a>, and on Linux I am using <a href="https://apps.kde.org/okteta/" target="_blank" rel="noopener noreferrer">Okteta</a>.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/hxd_1.png" style="display: block; margin: auto; max-width: 100%;">

<p>Some hex editors have more features, some less, but most are split into 3 views. On the left you can view the actual bytes in hexadecimal. Also there are the offsets displayed in hexadecimal as well, to ease navigating large files and locating specific bytes at certain positions.</p>

<p>Right next to it, there is a decoded text interpretation. Most of the time, this is some form of ASCII. This decoding is mostly useful when your format uses text. If you are not storing text, the decoded text will be scrambled nonsense. But often the text can help you to spot patterns.</p>

<p>I assume that's why little-endian is practically the standard for modern CPUs. Small integers have their MSB set to <code class="code">0</code>. If you use little-endian, then it's easy to spot at a glance, where that integer begins. But that is pure conjecture on my part.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/hxd_2.png" style="display: block; margin: auto; max-width: 100%;">

<p>On the right side of the hex editor, you will usually find an inspector, which provides gazillions of interpretations of the currently selected byte. It may read multiple bytes to come to each interpretation. After all, the hex editor doesn't know how your binary format works, so it displays all the possibilities. You can toggle endianness and see how the values in the inspector change.</p>

<h2>Floats and other numbers</h2>

<p>Endianness was quite the big jump scare. But once we are aware of it, <code class="code">float</code>s are very straight forward:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public static class</span> <span style="color: var(--pico-8-brown)">RisIO</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static float</span> <span style="color: var(--pico-8-purple)">ReadFloat</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytes</span> = <span style="color: var(--pico-8-purple)">Read</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-pink)">4</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">FixEndianness</span>(<span style="color: var(--pico-8-green)">bytes</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-brown)">BitConverter</span>.<span style="color: var(--pico-8-purple)">ToSingle</span>(<span style="color: var(--pico-8-green)">bytes</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static void</span> <span style="color: var(--pico-8-purple)">WriteFloat</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-cyan)">float</span> <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytes</span> = <span style="color: var(--pico-8-brown)">BitConverter</span>.<span style="color: var(--pico-8-purple)">GetBytes</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">FixEndianness</span>(<span style="color: var(--pico-8-green)">bytes</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytes</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>As you can see, the implementation is very similar to that of the integer. I won't list the implementations for all the other numeric types here. If you need to read/write single <code class="code">byte</code>s, <code class="code">char</code>s, <code class="code">double</code>s, <code class="code">short</code>s or <code class="code">long</code>s, whether they are signed or not, I am sure you can figure out the correct implementation on your own.</p>

<p>Or you can ask an LLM to do that for you. I heard they are the hot craze right now. Not that I would endorse such steaming shit...</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/neil.webp" style="display: block; margin: auto; max-width: 100%;">


<h2>Enums</h2>

<p>As far as I am aware, most programming languages use integers for enums internally, including C#. A notable exception is Rust, where an enum is more akin to a union type, which we will come back to later.</p>

<p>An enum value is just a tag to the compiler, which improves readability for you the programmer. But behind the scenes it's just a number. As such, writing an enum is as easy as converting it to an <code class="code">int</code> and writing that:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public static class</span> <span style="color: var(--pico-8-brown)">RisIO</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static void</span> <span style="color: var(--pico-8-purple)">WriteEnum</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-brown)">Enum</span> <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">i</span> = <span style="color: var(--pico-8-brown)">Convert</span>.<span style="color: var(--pico-8-purple)">ToInt32</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">WriteInt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">i</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>Since we are using <code class="code">WriteInt</code> to write the number, all endianness problems are already taken care of &lt;3</p>

<p>Reading is done like so:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public static class</span> <span style="color: var(--pico-8-brown)">RisIO</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">T</span> <span style="color: var(--pico-8-purple)">ReadEnum</span>&lt;<span style="color: var(--pico-8-brown)">T</span>&gt;(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>) <span style="color: var(--pico-8-cyan)">where</span> <span style="color: var(--pico-8-brown)">T</span> : <span style="color: var(--pico-8-brown)">Enum</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">i</span> = <span style="color: var(--pico-8-purple)">ReadInt</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">if</span> (!<span style="color: var(--pico-8-brown)">Enum</span>.<span style="color: var(--pico-8-purple)">IsDefined</span>(<span style="color: var(--pico-8-cyan)">typeof</span>(<span style="color: var(--pico-8-brown)">T</span>), <span style="color: var(--pico-8-green)">i</span>))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">throw new</span> <span style="color: var(--pico-8-brown)">FormatException</span>(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-washed-grey)">$"<span style="color: var(--pico-8-black)">{<span style="color: var(--pico-8-green)">i</span>}</span> is not defined for enum <span style="color: var(--pico-8-black)">{<span style="color: var(--pico-8-cyan)">typeof</span>(<span style="color: var(--pico-8-brown)">T</span>)}</span>"</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = (<span style="color: var(--pico-8-brown)">T</span>)<span style="color: var(--pico-8-brown)">Enum</span>.<span style="color: var(--pico-8-purple)">ToObject</span>(<span style="color: var(--pico-8-cyan)">typeof</span>(<span style="color: var(--pico-8-brown)">T</span>), <span style="color: var(--pico-8-green)">i</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>The code above uses the most advanced syntax of all the examples in this post, because it makes use of generics. If you are not familiar with generics, think of them like this: This method accepts <i>any</i> enum. Now instead of using the specific enum type, <code class="code">T</code> represents every enum possible. No matter what enum you read from this method, the method will resolve it correctly.</p>

<p>Don't worry, we'll walk through this example: First, we read an <code class="code">int</code>. Then we check if the enum is actually defined for that <code class="code">int</code>. If it isn't, we throw an exception. If it is defined, we cast it to the enum and return it.</p>

<p>Instead of throwing an exception, you could return a default value. But I prefer the exception here, because a default value would obfuscate invalid data.</p>

<p>It should be noted, that this approach only works for enums that have unique values. Consider the following enum:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public enum</span> <span style="color: var(--pico-8-brown)">Fruit</span> {<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">Apple</span> = <span style="color: var(--pico-8-pink)">1</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">Banana</span> = <span style="color: var(--pico-8-pink)">2</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">Orange</span> = <span style="color: var(--pico-8-pink)">3</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">MyFavorite</span> = <span style="color: var(--pico-8-pink)">3</span>,<br>
}</code>

<p>In this case, when writing <code class="code">Fruit.MyFavorite</code> into the stream, you might read <code class="code">Fruite.Orange</code> out of it. This may be desirable, or it may not. In case it is not desirable, you need to read and write <code class="code">string</code>s instead of <code class="code">int</code>s. How to serialize a <code class="code">string</code> we'll see later.</p>

<h2>Booleans</h2>

<p>Now let's take a look at booleans. A <code class="code">bool</code> can only have 2 values! <code class="code">true</code> and <code class="code">false</code>! How hard can that be? This will be easy!</p>

<p><b>Narrator: <i>It will not be easy.</i></b></p>

<p>New programmers are often surprised to hear that booleans are stored as 1 or more bytes in memory, instead of 1 bit. If you didn't know this, now you know :) The reason why is, because the CPU cannot access single bits. A CPU operates in "words" which are 1 or multiple bytes long.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/the_more_you_know.jpg" style="display: block; margin: auto; max-width: 100%;">

<p>With our serialization, we face a similar reality: With our current API, we can only serialize bytes, not bits. So whenever we want to save a <code class="code">bool</code>, we waste at least 7 bits of space.</p>

<p>This may seem wasteful, but from my experience, this is a problem which you usually don't want to solve. As it stands, our serialization is "byte aligned", which means all chunks of information start and end with a byte. Once you introduce variable bitlength into your serialization, you face alignment issues. And I cannot stress enough that this is a major pain in the ass, and it really isn't worth solving.</p>

<p>To more effectively use all the space, there are 2 valid approaches: The first one is compression. We will talk about that at the very end of this post. The second is bitfields.</p>

<p>A byte consists of 8 bits. Since a <code class="code">bool</code> only requires 1 bit, it directly follows, that a single <code class="code">byte</code> can hold 8 <code class="code">bool</code>s. An <code class="code">int</code> has 32 bits, so it can hold 32 <code class="code">bool</code>s! A bitfield is a technique to store <code class="code">bools</code> in an integer. Using bit shift operations and masks you can set, clear and read specific bits and treat them as <code class="code">bool</code>s.</p>

<p>However, bitfields are tricky. And the syntax seems arcane for the uninitiated.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/operators_meme.webp" style="display: block; margin: auto; max-width: 100%;">

<p>I don't recommend a new programmer to deal with bitfields, as they are very easy to misuse. They are so tricky in fact, that Rust, the programming language with possibly the strictest type system of all available languages currently available, doesn't have a type for them. Instead, Rust users recommend external libraries that do bitfields for you.</p>

<p>You can read up on bitfields if you want to, but I will consider any further discussion to be out of scope for this post. If you want to read up on yourself, here's an <a href="https://en.wikipedia.org/wiki/Bit_field" target="_blank" rel="noopener noreferrer">Wikipedia article</a> and <a href="https://youtu.be/ZRNO-ewsNcQ" target="_blank" rel="noopener noreferrer">this amazing video by Creel</a>.</p>

<p>My recommendation is, even if it's wasteful, to store an entire byte for a single bool. So we will continue with that.</p>

<p>Ok, but oh no. We are not done yet with problems: What even is a <code class="code">bool</code>? Like, how does the CPU actually represent that in memory? The unfortunate answer is, that bools do not exist. Yes, you read that correctly. As far as the CPU is concerned, only words exist. At best, some special registers that store flags could be considered boolean, but they are used for a completely different use case, compared to the <code class="code">bool</code>s in your code. And unless you are writing assembly, you can't actually manipulate such flag registers.</p>

<p>Different programming languages compile <code class="code">bool</code>s differently. If you've ever tried to write interoperability between two programming languages, you might have run into this. But it gets worse: Not even the SAME programming language can agree on how a <code class="code">bool</code> should be represented. Different C compilers may produce different assembly. Newer C standards only define what behavior a <code class="code">bool</code> should have, not how it should be represented in memory.</p>

<p>Wild, isn't it?</p>

<video loop="true" autoplay="autoplay" muted="true" style="max-width:100%; display: block; margin: auto;" loading='lazy'>
<source src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/mind_blown.mp4" type="video/mp4">
</video>

<p>This absolute disaster has direct consequences for our serialization: Even if our programming language provides a method to convert a <code class="code">bool</code> to bytes and vice versa, we cannot rely on it. There is no guarantee that a different computer or a different program can understand our <code class="code">bool</code>. As such we must take the serialization of <code class="code">bool</code>s into our own hands. Luckily, this isn't difficult, as a <code class="code">bool</code> can hold only 2 different values.</p>

<p>There are many different strategies we could use here. We could use a bitfield, but as discussed, not recommended. Instead, I suggest to write a <code class="code">1</code> when the <code class="code">bool</code> is <code class="code">true</code>, and <code class="code">0</code> when the <code class="code">bool</code> is <code class="code">false</code>. When reading, <code class="code">1</code> means <code class="code">true</code>, <code class="code">0</code> means <code class="code">false</code>, and every other value leads to an exception.</p>

<p>If you want, you can use a different strategy. But whatever you do, make sure that it is consistent over all computers and programs that use your binary format.</p>

<p>Here's my implementation:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public static class</span> <span style="color: var(--pico-8-brown)">RisIO</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static bool</span> <span style="color: var(--pico-8-purple)">ReadBool</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytes</span> = <span style="color: var(--pico-8-purple)">Read</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-pink)">1</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">b</span> = <span style="color: var(--pico-8-green)">bytes</span>[<span style="color: var(--pico-8-pink)">0</span>];<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">switch</span> (<span style="color: var(--pico-8-green)">b</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">case</span> <span style="color: var(--pico-8-pink)">1</span>:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return true</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">case</span> <span style="color: var(--pico-8-pink)">0</span>:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return false</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">default</span>:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">throw new</span> <span style="color: var(--pico-8-brown)">FormatException</span>(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-washed-grey)">$"<span style="color: var(--pico-8-black)">{<span style="color: var(--pico-8-green)">b</span>}</span> is not a valid bool"</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static void</span> <span style="color: var(--pico-8-purple)">WriteBool</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-cyan)">bool</span> <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">if</span> (<span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-cyan)">new byte</span>[] { <span style="color: var(--pico-8-pink)">1</span> });<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">else</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-cyan)">new byte</span>[] { <span style="color: var(--pico-8-pink)">0</span> });<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<h2>Classes and structs</h2>

<p>We have come quite far. So much so, that we can start to serialize our classes and structs! Classes are ultimately just a list of smaller types (we are not going into what methods are or how they work, for that you can look up vtables). So, reading and writing this "field list" in a predefined order is enough to serialize our class. This is very easy actually. Here's an example:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">MyAwesomeClass</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public int</span> <span style="color: var(--pico-8-green)">MyNumber</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public float</span> <span style="color: var(--pico-8-green)">MyOtherNumber</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public bool</span> <span style="color: var(--pico-8-green)">MightNotBeTrue</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public byte</span>[] <span style="color: var(--pico-8-purple)">Serialize</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteInt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">MyNumber</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteFloat</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">MyOtherNumber</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteBool</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">MightNotBeTrue</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">s</span>.<span style="color: var(--pico-8-purple)">ToArray</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">MyAwesomeClass</span> <span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">MyAwesomeClass</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">MyNumber</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadInt</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">MyOtherNumber</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadFloat</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">MightNotBeTrue</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadBool</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>Very straight forward. Very simple. This is what I meant by "creating your own binary format is fast and easy". Sure, there was a somewhat steep learning curve. But once you understand these ideas, and have a collection of utilities like <code class="code">RisIO</code>, you can whip out a new binary format for everything in no time.</p>

<p>What do you say? I did not cover arrays? Strings? Pffff whaat? Who needs those? I certainly don't need arrays. That's for certain. No! Don't look at the scrollbar! We are practically done...</p>

<h2>Sized vs unsized types</h2>

<p>Welp. We are not, in fact, done. As it turns out there is quite a bit more to cover. But it is true though: Serializing classes and structs is as easy as calling the according IO methods in a predefined order. Everything from here on out covers special types that require specific strategies. It all boils down to sized vs unsized types.</p>

<p>Up until this point, we have only seen sized types. By that I mean, we know how big they are, how much memory they take up. A serialized <code class="code">int</code> has always a size of 4 bytes. A serialized <code class="code">bool</code> is always 1 byte. Last jump scare, I promise: There exist types with unknown sizes.</p>

<p>Let's take the array for example. How many bytes does an array take up? Think about it for a second. The answer is: It depends. If there are no elements in the array, then hurray, we don't need any memory actually. But if there are, idk, 10 items in it, then we require at least 10 times the size of whatever type we are storing.</p>

<p>This is what I mean by an unsized type. An unsized type is a type, that we don't know the size up front. To be specific: A type is unsized, if it's size cannot be determined at compile time.</p>

<p>Once our program runs and the array is actually loaded into memory, it does take up space. This means it does actually have a size, but it must be determined at runtime. To properly serialize an array, we need to store the number of elements, and then serialize each element individually.</p>

<p>Here's how that might look like:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">MyMostFavoriteBools</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">List</span>&lt;<span style="color: var(--pico-8-cyan)">bool</span>&gt; <span style="color: var(--pico-8-green)">Bools</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public byte</span>[] <span style="color: var(--pico-8-purple)">Serialize</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteInt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">Bools</span>.<span style="color: var(--pico-8-green)">Count</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">foreach</span> (<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">b</span> <span style="color: var(--pico-8-cyan)">in</span> <span style="color: var(--pico-8-green)">Bools</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteBool</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">b</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-green)">s</span>.<span style="color: var(--pico-8-purple)">ToArray</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">MyMostFavoriteBools</span> <span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">MyMostFavoriteBools</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">Bools</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">List</span>&lt;<span style="color: var(--pico-8-cyan)">bool</span>&gt;();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">count</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-brown)">ReadInt</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">for</span> (<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">i</span> = <span style="color: var(--pico-8-pink)">0</span>; <span style="color: var(--pico-8-green)">i</span> &lt; <span style="color: var(--pico-8-green)">count</span>; ++<span style="color: var(--pico-8-green)">i</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">b</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadBool</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">Bools</span>.<span style="color: var(--pico-8-purple)">Add</span>(<span style="color: var(--pico-8-green)">b</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}<br>
</code>

<p>You may notice that these are methods directly on the class itself, instead of <code class="code">RisIO</code>. Well, at the time of writing this post, I have not found a satisfying method signature that covers all the ergonomics that I want in a standalone IO method. As such, I typically serialize arrays like the example above, even if it may be verbose at times.</p>

<p>It should be noted, that often times, classes and structs are sized types as well. If you know the sizes of the fields, then you know the size of the entire class. For example, a class storing an <code class="code">int</code>, a <code class="code">float</code> and a <code class="code">bool</code> has always the size of 4 + 4 + 1 = 9 bytes. As such, it too can easily be stored in an array.</p>

<p>However, once a class stores even a single unsized type, the class will be unsized itself. More often than not, this is fine. Elements in an array are stored back-to-back. Reading one element after the other gives correct results, even if the array element is unsized. But it should be noted that you must deserialize ALL array elements in such a case. You cannot, for example, skip every second element via <code class="code">Seek(n, SeekFrom.Current)</code>, because you don't know the size of an element. If you absolutely need this behavior, then you can store the size first, and serialize the class second. The reader should read the size first, and then decide if it wants to skip or not.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/unsized_array.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;">

<h2>Strings</h2>

<p>Now we can finally serialize strings. Took us long enough.</p>

<p>I often see new programmers, who work with modern programming languages, taking strings for granted. Some even consider them to be a primitive type!</p>

<p><i>"Come on man. How hard can Strings possibly be?"</i></p>

<p>As it turns out, strings are very difficult. If you've ever worked with strings in C before, you know how non-primitive they actually are. Rust has hundreds of different string types! Well, I am exaggerating, but Rust indeed has a lot of different types of strings.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/string_meme.webp" style="display: block; margin: auto; max-width: 100%;">

<p>But even if we stay in the realm of C#, strings might still be tricky. Plain text isn't as plain text as you might think. "Plain Text" by Dylan Beattie is a good talk I recommend: <a href="https://youtu.be/gd5uJ7Nlvvo" target="_blank" rel="noopener noreferrer">LINK</a>. Another good resource is "The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)" by Joel Spolsky: <a href="https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/" target="_blank" rel="noopener noreferrer">LINK</a>. The rabbit hole goes quite deep, and strings are anything but simple.</p>

<p>But there are very good news for us: Practically, strings are a solved problem.</p>

<p>Thanks to Unicode, serialization of strings is actually very straight forward (as long as we stick with Unicode). To keep things brief, and to summarize Joels post, a string is a sequence of characters. Each character is defined by a codepoint. Codepoints are arbitrarily defined, and must be "encoded" before they can be stored in memory. As long as we know what encoding a given string uses, we can read and understand it.</p>

<p>There are many different encodings, but as long as we use the same encoding in the serialize and deserialize methods, we will be fine. I choose UTF-8, because it is ubiquitous. You don't need to know how UTF-8 works, but you can read up on it if you want. Here's a <a href="https://en.wikipedia.org/wiki/UTF-8" target="_blank" rel="noopener noreferrer">Wikipedia article</a>, here's the <a href="https://www.rfc-editor.org/rfc/rfc3629" target="_blank" rel="noopener noreferrer">official RFC</a> and here's <a href="https://youtu.be/MijmeoH9LT4" target="_blank" rel="noopener noreferrer">Tom Scott on Computerphile</a>.</p>

<p>Since strings are a solved problem, serialization is stupidly easy for us:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public static class</span> <span style="color: var(--pico-8-brown)">RisIO</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static string</span> <span style="color: var(--pico-8-purple)">ReadString</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">length</span> = <span style="color: var(--pico-8-purple)">ReadInt</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytes</span> = <span style="color: var(--pico-8-purple)">Read</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">length</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-brown)">Encoding</span>.<span style="color: var(--pico-8-green)">UTF8</span>.<span style="color: var(--pico-8-purple)">GetString</span>(<span style="color: var(--pico-8-green)">bytes</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static void</span> <span style="color: var(--pico-8-purple)">WriteString</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-cyan)">string</span> <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytes</span> = <span style="color: var(--pico-8-brown)">Encoding</span>.<span style="color: var(--pico-8-green)">UTF8</span>.<span style="color: var(--pico-8-purple)">GetBytes</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">WriteInt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytes</span>.<span style="color: var(--pico-8-green)">Length</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytes</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>Instead of serializing characters, we first encode our string into UTF-8 bytes and then store that as a dynamic array. We are storing the length first and then the bytes. To deserialize a string we read the length first and read that many bytes, which are then interpreted as a UTF-8 string and converted into a C# string. Easy :)</p>

<p>In case it isn't obvious, strings are unsized types, because they can have arbitrary lengths.</p>

<h2>Dynamic types</h2>

<p>Another kind of unsized types are dynamic types, i.e. types that are only known during runtime. Notable examples include polymorphism, by which I mean multiple classes that implement the same base class. This is very common in OOP languages. In other languages union structs fall into the same problem, like Rust enums for example. Here's some code to work with:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">Fruit</span> { <span style="color: var(--pico-8-dark-grey)">/* ... */</span> }<br>
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">Apple</span> : <span style="color: var(--pico-8-brown)">Fruit</span> { <span style="color: var(--pico-8-dark-grey)">/* ... */</span> }<br>
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">Banana</span> : <span style="color: var(--pico-8-brown)">Fruit</span> { <span style="color: var(--pico-8-dark-grey)">/* ... */</span> }<br>
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">Orange</span> : <span style="color: var(--pico-8-brown)">Fruit</span> { <span style="color: var(--pico-8-dark-grey)">/* ... */</span> }<br>
<br>
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">FruitBasket</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">List</span>&lt;<span style="color: var(--pico-8-brown)">Fruit</span>&gt; <span style="color: var(--pico-8-green)">Fruits</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
}
</code>

<p>Here, <code class="code">Fruit</code> is an unsized type, because any derivation may serialize to a different length. An <code class="code">Apple</code> might serialize differently than an <code class="code">Orange</code> for example. But because of polymorphism, both can be stored in the same List of <code class="code">FruitBasket.Fruits</code>. So we don't know at compile time how much memory a <code class="code">FruitBasket</code> would take up.</p>

<p>To solve this, we store the type as an enum and serialize based on that. This works:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public enum</span> <span style="color: var(--pico-8-brown)">FruitKind</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">Apple</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">Banana</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">Orange</span>,<br>
}<br>
<br>
<span style="color: var(--pico-8-cyan)">public abstract class</span> <span style="color: var(--pico-8-brown)">Fruit</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public abstract</span> <span style="color: var(--pico-8-brown)">FruitKind</span> <span style="color: var(--pico-8-purple)">GetKind</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public abstract byte</span>[] <span style="color: var(--pico-8-purple)">Serialize</span>();<br>
}<br>
<br>
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">Apple</span> : <span style="color: var(--pico-8-brown)">Fruit</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public override</span> <span style="color: var(--pico-8-brown)">FruitKind</span> <span style="color: var(--pico-8-purple)">GetKind</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-brown)">FruitKind</span>.<span style="color: var(--pico-8-green)">Apple</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public override byte</span>[] <span style="color: var(--pico-8-purple)">Serialize</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">Apple</span> <span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}<br>
<br>
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">Banana</span> : <span style="color: var(--pico-8-brown)">Fruit</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public override</span> <span style="color: var(--pico-8-brown)">FruitKind</span> <span style="color: var(--pico-8-purple)">GetKind</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-brown)">FruitKind</span>.<span style="color: var(--pico-8-green)">Banana</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public override byte</span>[] <span style="color: var(--pico-8-purple)">Serialize</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">Banana</span> <span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}<br>
<br>
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">Orange</span> : <span style="color: var(--pico-8-brown)">Fruit</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public override</span> <span style="color: var(--pico-8-brown)">FruitKind</span> <span style="color: var(--pico-8-purple)">GetKind</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-brown)">FruitKind</span>.<span style="color: var(--pico-8-green)">Orange</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public override byte</span>[] <span style="color: var(--pico-8-purple)">Serialize</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">Orange</span> <span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}<br>
<br>
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">FruitBasket</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">List</span>&lt;<span style="color: var(--pico-8-brown)">Fruit</span>&gt; <span style="color: var(--pico-8-green)">Fruits</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public byte</span>[] <span style="color: var(--pico-8-purple)">Serialize</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteInt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">Fruits</span>.<span style="color: var(--pico-8-green)">Count</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">foreach</span> (<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">fruit</span> <span style="color: var(--pico-8-cyan)">in</span> <span style="color: var(--pico-8-green)">Fruits</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">kind</span> = <span style="color: var(--pico-8-green)">fruit</span>.<span style="color: var(--pico-8-purple)">GetKind</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteEnum</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">kind</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytes</span> = <span style="color: var(--pico-8-green)">fruit</span>.<span style="color: var(--pico-8-purple)">Serialize</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytes</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-green)">s</span>.<span style="color: var(--pico-8-purple)">ToArray</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">FruitBasket</span> <span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">FruitBasket</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">Fruits</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">List</span>&lt;<span style="color: var(--pico-8-brown)">Fruit</span>&gt;();<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">count</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadInt</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">for</span> (<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">i</span> = <span style="color: var(--pico-8-pink)">0</span>; <span style="color: var(--pico-8-green)">i</span> < <span style="color: var(--pico-8-green)">count</span>; ++<span style="color: var(--pico-8-green)">i</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">kind</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadEnum</span>&lt;<span style="color: var(--pico-8-brown)">FruitKind</span>&gt;(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">Fruit</span> <span style="color: var(--pico-8-green)">fruit</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">switch</span> (<span style="color: var(--pico-8-green)">kind</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">case</span> <span style="color: var(--pico-8-brown)">FruitKind</span>.<span style="color: var(--pico-8-green)">Apple</span>:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">fruit</span> = <span style="color: var(--pico-8-brown)">Apple</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">break</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">case</span> <span style="color: var(--pico-8-brown)">FruitKind</span>.<span style="color: var(--pico-8-green)">Banana</span>:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">fruit</span> = <span style="color: var(--pico-8-brown)">Banana</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">break</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">case</span> <span style="color: var(--pico-8-brown)">FruitKind</span>.<span style="color: var(--pico-8-green)">Orange</span>:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">fruit</span> = <span style="color: var(--pico-8-brown)">Orange</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">break</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">default</span>:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">throw new</span> <span style="color: var(--pico-8-brown)">ArgumentOutOfRangeException</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">Fruits</span>.<span style="color: var(--pico-8-purple)">Add</span>(<span style="color: var(--pico-8-green)">fruit</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>Whenever a <code class="code">Fruit</code> is serialized, we first get its <code class="code">FruitKind</code> and store that first. Then we serialize the <code class="code">Fruit</code> afterwards. When reading, we read the <code class="code">FruitKind</code> first. Using a <code class="code">switch</code>, depending on the <code class="code">FruitKind</code> we are either deserializing an <code class="code">Apple</code>, a <code class="code">Banana</code> or an <code class="code">Orange</code>.</p>

<p>Notice how <code class="code">Deserialize</code> of each Fruit takes a <code class="code">RisMemoryStream</code> instead of a <code class="code">byte[]</code>. This is different from previous examples. The reason for that is because <code class="code">FruitBasket</code> does not know how big a serialized <code class="code">Fruit</code> is. By passing the stream into <code class="code">Fruit</code>s deserialization, the <code class="code">Fruit</code> can read as many bytes as it needs.</p>

<h2>An odd problem with a banger solution</h2>

<p>We are slowly inching closer to the end of this post. So let me present you with an odd, maybe somewhat complicated problem. Up until now, we haven't really used <code class="code">Seek</code>, did we? Well, in this chapter we are going to use it. And for a very cool reason actually. So cool in fact, that I hope this chapter blows your mind.</p>

<p>Let's say you have three classes: <code class="code">FooBase</code>, <code class="code">FooA</code> and <code class="code">FooB</code>. <code class="code">FooBase</code> stores a <code class="code">FooA</code> and a <code class="code">FooB</code>. Assume <code class="code">FooA</code> and <code class="code">FooB</code> have according serialize- and deserialize methods. <code class="code">FooBase</code> looks like this:</p>

<code class="code code_block">
<span style="color: var(--pico-8-green)">public class</span> <span style="color: var(--pico-8-brown)">FooBase</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">FooA</span> <span style="color: var(--pico-8-green)">A</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">FooB</span> <span style="color: var(--pico-8-green)">B</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public byte</span>[] <span style="color: var(--pico-8-purple)">Serialize</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytesA</span> = <span style="color: var(--pico-8-green)">A</span>.<span style="color: var(--pico-8-purple)">Serialize</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytesB</span> = <span style="color: var(--pico-8-green)">B</span>.<span style="color: var(--pico-8-purple)">Serialize</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytesA</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytesB</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-green)">s</span>.<span style="color: var(--pico-8-purple)">ToArray</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">FooBase</span> <span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">FooBase</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">A</span> = <span style="color: var(--pico-8-brown)">FooA</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">B</span> = <span style="color: var(--pico-8-brown)">FooB</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>Nothing too complicated. Looks kinda like the example in the "Classes and structs" chapter.</p>

<p>But here's my request: I have a stream that contains a serialized <code class="code">FooBase</code>, but I <i>only</i> want to read <code class="code">FooB</code> out of it.</p>

<p>This may seem like an odd request, but let's roll with it. Maybe <code class="code">FooA</code> is very big and very costly to deserialize, so I only want to deserialize <code class="code">FooB</code> and deal with <code class="code">FooA</code> some time later. I don't want to deserialize the entire <code class="code">FooBase</code>, when I just need <code class="code">FooB</code>. How would you implement this?</p>

<p>Well, we definitely need to change both <code class="code">Serialize</code> and <code class="code">Deserialize</code>. As it stands now, our binary format stores no information on where <code class="code">FooB</code> starts in the stream. Currently we have to deserialize <code class="code">FooA</code>, which advances the stream in such a way, that <code class="code">FooB</code> can be deserialized.</p>

<p>One thing we can do, is to store the length of <code class="code">FooA</code>s bytes right before it:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">FooBase</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">FooA</span> <span style="color: var(--pico-8-green)">A</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">FooB</span> <span style="color: var(--pico-8-green)">B</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public byte</span>[] <span style="color: var(--pico-8-purple)">Serialize</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytesA</span> = <span style="color: var(--pico-8-green)">A</span>.<span style="color: var(--pico-8-purple)">Serialize</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytesB</span> = <span style="color: var(--pico-8-green)">B</span>.<span style="color: var(--pico-8-purple)">Serialize</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteInt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytesA</span>.<span style="color: var(--pico-8-green)">Length</span>); <span style="color: var(--pico-8-dark-grey)">// store length</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytesA</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytesB</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-green)">s</span>.<span style="color: var(--pico-8-purple)">ToArray</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">FooBase</span> <span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">FooBase</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-pink)">4</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Current</span>); <span style="color: var(--pico-8-dark-grey)">// skip length</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">A</span> = <span style="color: var(--pico-8-brown)">FooA</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">B</span> = <span style="color: var(--pico-8-brown)">FooB</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>


<p>This way, we have information on how big <code class="code">FooA</code> actually is. So we can use it to skip <code class="code">FooA</code> entirely. Here's how that would look like:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">FooBase</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">FooB</span> <span style="color: var(--pico-8-purple)">DeserializeOnlyB</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytesLengthA</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadInt</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytesLengthA</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Current</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-brown)">FooB</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>Easy. Read the length, and skip that many bytes forward.</p>

<p>I am not satisfied with this solution however. What if we also have <code class="code">FooC</code>, <code class="code">FooD</code>, and so on? If we have thousands of <code class="code">Foo</code>s, and we only want to deserialize the last one, then we need to read and skip thousand lengths!</p>

<p>No, I have a better idea: Instead of storing the <i>length</i> of <code class="code">FooA</code>, let's store the <i>position</i> of <code class="code">FooB</code>:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">FooBase</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">FooA</span> <span style="color: var(--pico-8-green)">A</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">FooB</span> <span style="color: var(--pico-8-green)">B</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public byte</span>[] <span style="color: var(--pico-8-purple)">Serialize</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>();<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// placeholder</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteInt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-pink)">0</span>);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// serialize A</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytesA</span> = <span style="color: var(--pico-8-green)">A</span>.<span style="color: var(--pico-8-purple)">Serialize</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytesA</span>);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// serialize B</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">positionB</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-pink)">0</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Current</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytesB</span> = <span style="color: var(--pico-8-green)">B</span>.<span style="color: var(--pico-8-purple)">Serialize</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytesB</span>);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// go back to placeholder and write the actual position</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-pink)">0</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Begin</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteInt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">positionB</span>);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-green)">s</span>.<span style="color: var(--pico-8-purple)">ToArray</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">FooBase</span> <span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">FooBase</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-pink)">4</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Current</span>); <span style="color: var(--pico-8-dark-grey)">// skip position</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">result</span>.<span style="color: var(--pico-8-green)">A</span> = <span style="color: var(--pico-8-brown)">FooA</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">result</span>.<span style="color: var(--pico-8-green)">B</span> = <span style="color: var(--pico-8-brown)">FooB</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
}
</code>

<p>With this, we can directly jump to <code class="code">FooB</code>:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">FooBase</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">FooB</span> <span style="color: var(--pico-8-purple)">DeserializeOnlyB</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">positionB</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadInt</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">positionB</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Begin</span>); <span style="color: var(--pico-8-dark-grey)">// jump to B</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-brown)">FooB</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>This works. And it is actually quite useful. I use this technique in <a href="https://github.com/Rismosch/ris_engine" target="_blank" rel="noopener noreferrer">ris_engine</a>, in which I store all assets in a single file. At the beginning of the asset file, there is a lookup where each asset is stored. Loading an asset is as simple as seeking to the position of the according asset and reading from there. It's also quite helpful if you have quite complicated structs with many unsized types. Storing positions like this is quite the game changer.</p>

<p>And this is where I pull the rug from under you.</p>

<p>If you understood this concept of positions, then congratulations. You now understand pointers.</p>

<p>I am not kidding. This is no joke and I am fully serious. New programmers often struggle with pointers as a concept. From my experience, they even show pride in their unwillingness to understand what a pointer is. The argument I often hear is, that they don't intend to write C/C++, and therefore, pointers are not required to be understood.</p>

<p>But I want to stress again, this position concept we just implemented, is exactly what a pointer is. Somewhere in our stream <code class="code">FooB</code> is stored. At the start of the stream, we have written a pointer, which tells us exactly where <code class="code">FooB</code> is. To read <code class="code">FooB</code>, we use the <i>value</i> of the pointer to seek to the position where <code class="code">FooB</code> actually sits.</p>

<p>The same concept applies to actual pointers in languages like C/C++ and Rust. If you store a simple variable, you have direct access to it. You can read, modify and use it. No pointers required. If you have a pointer however, that variable sits somewhere in memory. Think of memory as a very long byte array, just like our stream. The pointer simply stores an index into that long byte array. To look up the value of our pointer, we look in the array at that index and voilà, we know what our pointer stores.</p>

<p>When people talk pointers, they often say "address" instead of "index". And people say "dereference" instead of "lookup".</p>

<table class="pointer" style="border-collapse: collapse; margin: auto">
<tr><th>pointer</th><th>stream</th><th>array</th></tr>
<tr><td>address</td><td>cursor / position</td><td>index</td></tr>
<tr><td>dereference</td><td>read / write</td><td>lookup</td></tr>
</table>

<p>I hope you could follow me. I think this was fun. And you can pat yourself on the back, for finally being able to understand pointers.</p>

<p>From now on, it's smooth sailing. The heavy lifting has been done. All that's left is to improve a bit on what we've learned and then discuss some useful strategies.</p>

<h2>Making it fat</h2>

<p>While we are at pointers now, I want to use the opportunity to widen your mind a little bit.</p>

<p>Right now, when storing a pointer, we are storing just a position. While this is sufficient, if misused, it can produce all kinds of headaches. Like, nothing stops the serializer to read and write outside our intended region. This may cause unintended bugs, but it can also be abused by mischievious actors. As a matter of fact, some of my previous deserialize code does allow such a bug. The astute reader may have caught it already.</p>

<p>Let me bring up the code again, so you have another chance to find it:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">FooBase</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">FooB</span> <span style="color: var(--pico-8-purple)">DeserializeOnlyB</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">positionB</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadInt</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">positionB</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Begin</span>); <span style="color: var(--pico-8-dark-grey)">// jump to B</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-brown)">FooB</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>Did you catch it? It may be hard to spot, since we are missing a crucial implementation, but the problem is right there. The fruits example from earlier suffers from the same bug actually...</p>

<p>As it stands now, the code is assuming that <code class="code">FooB.Deserialize</code> never seeks, or at least seeks in a way that is invisible to <code class="code">FooBase</code>. Since <code class="code">FooB.Deserialize</code> takes the <i>entire</i> stream as an input, it can seek, read and write wherever it wants, even outside its intended range.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/out_of_range.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;">

<p>Now we are reading in some place outside of our intended area, which is not good.</p>

<p>This error is called an out-of-bounds error, and it is one of the many reasons why C and C++ are considered unsafe. Pointers in C and C++ are just addresses, and nothing stops you from accessing <i>any</i> memory you want. You can dereference before and after your pointer willy nillingly.</p>

<p>To prevent such out-of-bound accesses, modern programming languages simply don't allow it. C# for example throws an exception if you try to access an array out of bounds. Not all hope is lost for C and C++ though, as modern operating systems utilize some clever tricks, like memory paging. But that's more of a band aid than an actual solution.</p>

<p>In our case, we want to prevent the deserializer to access an entire stream. We don't want it to modify the stream however it likes. The easiest way to accomplish this is to simply not give our serializer a stream, and only rely on byte arrays. But this implies that the one creating the array knows how many bytes a given deserializer needs. In one way or another, we have to store the length of our bytes somehow.</p>

<p>Let me introduce you to the <code class="code">FatPtr</code>. The <code class="code">FatPtr</code> is a fairly simple struct that stores two ints: An address and a length. The address is, well, the address. And the length describes how long the byte array at that address is. Since a normal pointer only stores a position, a <code class="code">FatPtr</code> is "fat", because it stores a length as well.</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public struct</span> <span style="color: var(--pico-8-brown)">FatPtr</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public int</span> <span style="color: var(--pico-8-green)">Address</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public int</span> <span style="color: var(--pico-8-green)">Length</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">FatPtr</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">Address</span> = <span style="color: var(--pico-8-pink)">0</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">Length</span> = <span style="color: var(--pico-8-pink)">0</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">FatPtr</span> <span style="color: var(--pico-8-purple)">WithLength</span>(<span style="color: var(--pico-8-cyan)">int</span> <span style="color: var(--pico-8-green)">address</span>, <span style="color: var(--pico-8-cyan)">int</span> <span style="color: var(--pico-8-green)">length</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">if</span> (<span style="color: var(--pico-8-green)">length</span> &lt; <span style="color: var(--pico-8-pink)">0</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">throw new</span> <span style="color: var(--pico-8-brown)">ArgumentOutOfRangeException</span>(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">nameof</span>(<span style="color: var(--pico-8-green)">length</span>),<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">length</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">null</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">FatPtr</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">Address</span> = <span style="color: var(--pico-8-green)">address</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">Length</span> = <span style="color: var(--pico-8-green)">length</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">FatPtr</span> <span style="color: var(--pico-8-purple)">WithEnd</span>(<span style="color: var(--pico-8-cyan)">int</span> <span style="color: var(--pico-8-green)">begin</span>, <span style="color: var(--pico-8-cyan)">int</span> <span style="color: var(--pico-8-green)">end</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">if</span> (<span style="color: var(--pico-8-green)">begin</span> &gt; <span style="color: var(--pico-8-green)">end</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">throw new</span> <span style="color: var(--pico-8-brown)">ArgumentOutOfRangeException</span>(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">nameof</span>(<span style="color: var(--pico-8-green)">end</span>),<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">end</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">null</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">FatPtr</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">Address</span> = <span style="color: var(--pico-8-green)">begin</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">Length</span> = <span style="color: var(--pico-8-green)">end</span> - <span style="color: var(--pico-8-green)">begin</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public int</span> <span style="color: var(--pico-8-purple)">End</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">Address</span> + <span style="color: var(--pico-8-green)">Length</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public bool</span> <span style="color: var(--pico-8-purple)">IsNull</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">Address</span> == <span style="color: var(--pico-8-pink)">0</span> && <span style="color: var(--pico-8-green)">Length</span> == <span style="color: var(--pico-8-pink)">0</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>This implementation also introduces some utility methods, which will be helpful later. For example, we can construct a <code class="code">FatPtr</code> via a beginning and an end. We also define that <code class="code">Address == 0 && Length == 0</code> means that we are dealing with a null pointer, which might be helpful in some instances. For example, if a field in our data class can be something or nothing, we can use a null pointer to indicate that the field stores nothing.</p>

<p>To support <code class="code">FatPtr</code>s, let's introduce two new methods to <code class="code">RisIO</code>:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public static class</span> <span style="color: var(--pico-8-brown)">RisIO</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">FatPtr</span> <span style="color: var(--pico-8-purple)">ReadFatPtr</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">address</span> = <span style="color: var(--pico-8-purple)">ReadInt</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">length</span> = <span style="color: var(--pico-8-purple)">ReadInt</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-brown)">FatPtr</span>.<span style="color: var(--pico-8-purple)">WithLength</span>(<span style="color: var(--pico-8-green)">address</span>, <span style="color: var(--pico-8-green)">length</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static void</span> <span style="color: var(--pico-8-purple)">WriteFatPtr</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-brown)">FatPtr</span> <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">WriteInt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">value</span>.<span style="color: var(--pico-8-green)">Address</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">WriteInt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">value</span>.<span style="color: var(--pico-8-green)">Length</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>The <code class="code">FatPtr</code> only stores two fields, so to serialize a <code class="code">FatPtr</code> we only need to serialize these two fields. And while we are at it, let's modify the regular <code class="code">RisIO.Write</code> method like so:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public static class</span> <span style="color: var(--pico-8-brown)">RisIO</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">FatPtr</span> <span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">begin</span> = <span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-pink)">0</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Current</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">s</span>.<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">end</span> = <span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-pink)">0</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Current</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">ptr</span> = <span style="color: var(--pico-8-brown)">FatPtr</span>.<span style="color: var(--pico-8-purple)">WithEnd</span>(<span style="color: var(--pico-8-green)">begin</span>, <span style="color: var(--pico-8-green)">end</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">ptr</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>We seek before and after the write, and construct a <code class="code">FatPtr</code> to it. This <code class="code">FatPtr</code> then points exactly at where we have just written some bytes. This significantly improves the ergonomics of client code, as we will see in the example. But before we take a look at that example, I want to add one last little helper to our <code class="code">RisIO</code> toolbox:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public static class</span> <span style="color: var(--pico-8-brown)">RisIO</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static byte</span>[] <span style="color: var(--pico-8-purple)">ReadAt</span>(<span style="color: var(--pico-8-brown)">RisMemoryStream</span> <span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-brown)">FatPtr</span> <span style="color: var(--pico-8-green)">fatPtr</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">fatPtr</span>.<span style="color: var(--pico-8-green)">Address</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Begin</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-purple)">Read</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">fatPtr</span>.<span style="color: var(--pico-8-green)">Length</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>This method takes a <code class="code">FatPtr</code>, which it uses to determine where to seek to and how many bytes should be read. This also will come in handy.</p> 

<p>With these tools under our belt, we can now implement a safe <code class="code">FooBase</code> like so:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">FooBase</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">FooA</span> <span style="color: var(--pico-8-green)">A</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public</span> <span style="color: var(--pico-8-brown)">FooB</span> <span style="color: var(--pico-8-green)">B</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public byte</span>[] <span style="color: var(--pico-8-purple)">Serialize</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>();<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// placeholders</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">fatPtrAPosition</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-pink)">0</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Current</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteFatPtr</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">FatPtr</span>());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">fatPtrBPosition</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-pink)">0</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Current</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteFatPtr</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">FatPtr</span>());<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// serialize</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytesA</span> = <span style="color: var(--pico-8-green)">A</span>.<span style="color: var(--pico-8-purple)">Serialize</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">fatPtrA</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytesA</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytesB</span> = <span style="color: var(--pico-8-green)">B</span>.<span style="color: var(--pico-8-purple)">Serialize</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">fatPtrB</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">bytesB</span>);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// go back to placeholders and write actual fatptrs</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">fatPtrAPosition</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Begin</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteFatPtr</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">fatPtrA</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">fatPtrBPosition</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Begin</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteFatPtr</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">fatPtrB</span>);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-green)">s</span>.<span style="color: var(--pico-8-purple)">ToArray</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">FooBase</span> <span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">FooBase</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">fatPtrA</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadFatPtr</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">fatPtrB</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadFatPtr</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytesA</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadAt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">fatPtrA</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytesB</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadAt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">fatPtrB</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">A</span> = <span style="color: var(--pico-8-brown)">FooA</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">bytesA</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">B</span> = <span style="color: var(--pico-8-brown)">FooB</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">bytesB</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">FooB</span> <span style="color: var(--pico-8-purple)">DeserializeOnlyB</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Seek</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-pink)">8</span>, <span style="color: var(--pico-8-brown)">SeekFrom</span>.<span style="color: var(--pico-8-green)">Current</span>); <span style="color: var(--pico-8-dark-grey)">// skip fatPtrA</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">fatPtrB</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadFatPtr</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytesB</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadAt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">fatPtrB</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-brown)">FooB</span>.<span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-green)">bytesB</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>Now, the deserialize methods of <code class="code">FooA</code> and <code class="code">FooB</code> take a <code class="code">byte[]</code> again. Because of that, <code class="code">FooA</code> and <code class="code">FooB</code> cannot do any out-of-bounds shenanigans.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/thumbs_up.webp" style="display: block; margin: auto; max-width: 100%;">

<h2>Some more strategies</h2>

<p>While we know enough now to serialize to our hearts desire, there are a few quality-of-life features that are very nice to have.</p>

<p>For example, we have a byte array, yes. But we would like to know what we are actually looking at, without deserializing the entire thing. Our binary format may be huge after all. If a user puts, idk, a PNG file into something that expects our custom format, it would be very nice to stop early before we are deserializing who knows what.</p>

<p>The easiest and most common solution to this problem is what's called a "magic value". A magic value consists of arbitrary bytes, which are written at the very beginning of our format. Thus, it's the first thing we can read.</p>

<p>For example, every PNG file starts with the bytes 137, 80, 78 and 71, which in escaped Unicode spells "\u0089PNG". As another example, every one of my assets in <a href="https://github.com/Rismosch/ris_engine" target="_blank" rel="noopener noreferrer">ris_engine</a> starts with the ASCII "ris_".</p>

<p>To serialize, we simply write the magic bytes first and then serialize after. To deserialize, we read the magic bytes and compare if they are as expected. If not, return an error. If they are as expected, continue deserialization. They may be called magic values, but there is no black magic to be found here.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/wizards.webp" style="display: block; margin: auto; max-width: 100%;">

<p>Another reason why a byte stream might not be as expected, is because of a version change. Maybe you are maintaining a program, which is in use for quite a while now and receives updates regularly. In that case the magic value of your format may stay the same, but you need to bump the version to prevent incompatible versions from breaking your program.</p>

<p>You can use different things for your version. A string is probably easiest, but the most wasteful. <a href="https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_asset_version" target="_blank" rel="noopener noreferrer">glTF</a> for example uses a string to identify its version. You can also use an integer, or multiple if you are going the <a href="https://semver.org/" target="_blank" rel="noopener noreferrer">semver</a> route. If you are clever, you can even put a MAJOR.MINOR.PATCH version in a single <code class="code">int</code>, like how <a href="https://registry.khronos.org/vulkan/specs/latest/man/html/VK_MAKE_API_VERSION.html" target="_blank" rel="noopener noreferrer">Vulkan</a> is doing.</p>

<p>But we may be overthinking things. The version is comparably small in relation to the rest of any format &#129300;</p>

<p>Another feature you may want is a header. A header consists of a number of bytes that are always there at the start of your format. The magic value and version is usually part of the header. But a header can hold additional information, for example the number of channels in an audio file or the dimensions of an image file.</p>

<p>Putting all these features into one code example, we might end up with something that looks like this:</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">MyCustomFormat</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">private static readonly byte</span>[] <span style="color: var(--pico-8-green)">ExpectedMagic</span> = { <span style="color: var(--pico-8-pink)">1</span>, <span style="color: var(--pico-8-pink)">2</span>, <span style="color: var(--pico-8-pink)">3</span>, <span style="color: var(--pico-8-pink)">4</span>, <span style="color: var(--pico-8-pink)">5</span> };<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">private const int</span> <span style="color: var(--pico-8-green)">ExpectedVersion</span> = <span style="color: var(--pico-8-pink)">42</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public byte</span>[] <span style="color: var(--pico-8-green)">Magic</span> = <span style="color: var(--pico-8-green)">ExpectedMagic</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public int</span> <span style="color: var(--pico-8-green)">Version</span> = <span style="color: var(--pico-8-green)">ExpectedVersion</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public string</span> <span style="color: var(--pico-8-green)">Meta</span> = <span style="color: var(--pico-8-washed-grey)">"some meta data"</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public byte</span>[] <span style="color: var(--pico-8-purple)">Serialize</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Write</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">Magic</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteInt</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">Version</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">WriteString</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">Meta</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">s</span>.<span style="color: var(--pico-8-purple)">ToArray</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">MyCustomFormat</span> <span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// magic</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">magic</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">Read</span>(<span style="color: var(--pico-8-green)">s</span>, <span style="color: var(--pico-8-green)">ExpectedMagic</span>.<span style="color: var(--pico-8-green)">Length</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">for</span> (<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">i</span> = <span style="color: var(--pico-8-pink)">0</span>; <span style="color: var(--pico-8-green)">i</span> < <span style="color: var(--pico-8-green)">ExpectedMagic</span>.<span style="color: var(--pico-8-green)">Length</span>; ++<span style="color: var(--pico-8-green)">i</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">left</span> = <span style="color: var(--pico-8-green)">ExpectedMagic</span>[<span style="color: var(--pico-8-green)">i</span>];<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">right</span> = <span style="color: var(--pico-8-green)">magic</span>[<span style="color: var(--pico-8-green)">i</span>];<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">if</span> (<span style="color: var(--pico-8-green)">left</span> != <span style="color: var(--pico-8-green)">right</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">throw new</span> <span style="color: var(--pico-8-brown)">FormatException</span>(<span style="color: var(--pico-8-washed-grey)">"magic does not match"</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// version</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">version</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadInt</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">if</span> (<span style="color: var(--pico-8-green)">version</span> != <span style="color: var(--pico-8-green)">ExpectedVersion</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">throw new</span> <span style="color: var(--pico-8-brown)">FormatException</span>(<span style="color: var(--pico-8-washed-grey)">"version does not match"</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// meta</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">meta</span> = <span style="color: var(--pico-8-brown)">RisIO</span>.<span style="color: var(--pico-8-purple)">ReadString</span>(<span style="color: var(--pico-8-green)">s</span>);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// deserialize the rest</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">MyCustomFormat</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">Magic</span> = <span style="color: var(--pico-8-green)">magic</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">Version</span> = <span style="color: var(--pico-8-green)">version</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-green)">result</span>.<span style="color: var(--pico-8-green)">Meta</span> = <span style="color: var(--pico-8-green)">meta</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>A header may be of any type and can contain as many fields as you want. To keep the example short and simple, I chose to use a single string as meta data.</p>

<p>At last, but not least, you might want to be backwards and forwards compatible between different versions. This is a beast of a problem, especially when multiple people over multiple generations are maintaining such a format. Infamously, the .docx file format from Microsoft Word solved this by simply using a zipped XML container. If you have a .docx file lying around, you can literally unzip it. You will get a directory structure, which you can easily view with any file explorer.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/unzipped_docx.png" style="display: block; margin: auto; max-width: 100%;">

<p>I have yet to implement such a format in binary, but I did something like it in XML though. So I have no experience on how you would develop such a format in binary. But I can tell you what I would try!</p>

<p>I would heavily rely on chunks. By which I mean: <code class="code">FatPtr</code>s everywhere. At the start of each chunk, an enum or its "kind" is stored, which determines what exactly this chunk is doing. If a deserializer reads a kind of chunk that it does not recognize, the chunk is ignored. If you are not using <code class="code">FatPtr</code>s, store them right after each other. Each chunk would then also store its size, such that a deserializer, who doesn't recognize a chunk, can skip it.</p>

<h2>Compression and encryption</h2>

<p>As I've hinted in the chapter about <code class="code">bool</code>s, our implementation is quite naive and simplistic, which wastes quite a bit of space. We can try to decrease the size of our data by compressing it. But I have to mention that not all data compresses equally. Some data is resistant to compression. Also, you may be interested in encryption, because you might store sensitive data.</p>

<p>Well, compression and encryption are two entirely different disciplines. Explaining each one in detail is waaaayy beyond the scope of this post. Either one is a rabbit hole on its own. For our use case, only this counts: Both compression and encryption are methods, which take a byte array and spit out a new byte array. Compression will reduce the amount of bytes, and encryption will scramble the bytes.</p>

<p>Since we deserialize into a byte array, compressing and encrypting is as easy as calling the according method on our byte array.</p>

<code class="code code_block">
<span style="color: var(--pico-8-cyan)">public class</span> <span style="color: var(--pico-8-brown)">MySmallAndEncryptedData</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">private static byte</span>[] <span style="color: var(--pico-8-purple)">Compress</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">private static byte</span>[] <span style="color: var(--pico-8-purple)">Decompress</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">private static byte</span>[] <span style="color: var(--pico-8-purple)">Encrypt</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">private static byte</span>[] <span style="color: var(--pico-8-purple)">Decrypt</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public byte</span>[] <span style="color: var(--pico-8-purple)">Serialize</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">//...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">bytes</span> = <span style="color: var(--pico-8-green)">s</span>.<span style="color: var(--pico-8-purple)">ToArray</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">compressed</span> = <span style="color: var(--pico-8-purple)">Compress</span>(<span style="color: var(--pico-8-green)">bytes</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">encrypted</span> = <span style="color: var(--pico-8-purple)">Encrypt</span>(<span style="color: var(--pico-8-green)">compressed</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">encrypted</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">public static</span> <span style="color: var(--pico-8-brown)">MySmallAndEncryptedData</span> <span style="color: var(--pico-8-purple)">Deserialize</span>(<span style="color: var(--pico-8-cyan)">byte</span>[] <span style="color: var(--pico-8-green)">value</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">decrypted</span> = <span style="color: var(--pico-8-purple)">Decrypt</span>(<span style="color: var(--pico-8-green)">value</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">decompressed</span> = <span style="color: var(--pico-8-purple)">Decompress</span>(<span style="color: var(--pico-8-green)">decrypted</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">s</span> = <span style="color: var(--pico-8-cyan)">new</span> <span style="color: var(--pico-8-brown)">RisMemoryStream</span>(<span style="color: var(--pico-8-green)">decompressed</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">var</span> <span style="color: var(--pico-8-green)">result</span> = <span style="color: var(--pico-8-brown)">new</span> <span style="color: var(--pico-8-brown)">MySmallAndEncryptedData</span>();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-dark-grey)">// ...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: var(--pico-8-cyan)">return</span> <span style="color: var(--pico-8-green)">result</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>And that's all there is to it. There are many different compression and encryption algorithms out there, many of which have dedicated libraries. You can pick and choose whatever you want. The sky is the limit.</p>

<p>Usually, you don't want to compress or encrypt the entire format. Usually, you want to keep the magic value, version and sometimes even the entire header readable. The reason is simple: You want the receiver to be able to identify what they are looking at, and that will be difficult when the data is mangled.</p>

<p>To take <a href="https://github.com/Rismosch/ris_engine" target="_blank" rel="noopener noreferrer">ris_engine</a> again as an example, all my internal formats have a 16-byte magic value at the start of each asset. Each one starts with "ris_" to identify them as one of my assets. The remaining 12 characters indicate what kind of asset one is looking at. Below is a screenshot of my "ris_scene" format. By the mangled nature of the bytes, one can guess that it was compressed. But the "ris_scene" at the start remains readable.</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/hxd_3.png" style="display: block; margin: auto; max-width: 100%;">

<p>If you want to learn more about compression and encryption, I leave you with these Wikipedia articles:</p>

<ul>
<li><a href="https://en.wikipedia.org/wiki/Data_compression" target="_blank" rel="noopener noreferrer">Compression</a></li>
<li><a href="https://en.wikipedia.org/wiki/Encryption" target="_blank" rel="noopener noreferrer">Encryption</a></li>
</ul>

<h2>Conclusion</h2>

<p>Wow, what a journey. It took some work, but now you should have everything that you need to build your own binary format. I am sure I have written something that you disagree with, and that is fine. Now, you have the knowledge to make adjustments to my code and implement what you actually need or want. And with these tools under your belt, it shouldn't be too difficult to cook up your own binary format.</p>

<p>I claimed in the intro that a custom binary format is easily smaller and faster than JSON. So I will leave you with a benchmark. It compares my serializer with an equivalent implementation using <a href="https://www.newtonsoft.com/json" target="_blank" rel="noopener noreferrer">Json.NET by Newtonsoft</a>, a popular JSON library for C#. The benchmark results are below. </p>

<p>(lower is better)</p>

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/benchmark_1.webp" style="display: block; margin: auto; max-width: 100%;">

<img src="https://www.rismosch.com/articles/how-to-create-your-own-binary-format/benchmark_2.webp" style="display: block; margin: auto; max-width: 100%;">

<p>I hope it is evident that a custom serializer easily outperforms a general one.</p>

<p>A complete implementation of the code in this post, including this benchmark, can be found here: <a href="https://github.com/Rismosch/RisSerialization" target="_blank" rel="noopener noreferrer">LINK</a></p>]]></content:encoded></item><item><title>Rust is the future</title><link>https://www.rismosch.com/article?id=rust-is-the-future</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">rust-is-the-future</guid><pubDate>Tue, 25 Feb 2025 14:05:59 +0100</pubDate><description>Ranting about bad programming languages and programmers.</description><content:encoded><![CDATA[<p>Recently, I finished the first working prototype of my game object system. I can say with confidence, that up to this day, this is the most complicated thing I have ever worked on. The amount of moving parts is absolutely insane. Let me give you a brief overview.</p>

<img src="https://www.rismosch.com/articles/rust-is-the-future/screenshot.webp" style="display: block; margin: auto; max-width: 100%;">

<p>A game object is essentially a frame of reference. It has a position, a rotation and a scale. This is the easy part. The difficult part is this: A game object may have children. This makes game objects hierarchical. Now, a game object references its children, but it also references its parent, enabling the hierarchy tree to be traversed up and down. While convenient for client code, this immediately creates a problem for the implementation. If you've heard anything about Rust, then you know that circular references like this are Rusts kryptonite. Unfortunately, this is the first of many problems.</p>

<p>A game object on its own doesn't do much. To give it behavior, you can attach components to it. These can be a variety of different types. And since most of them directly affect the game object, they also need to reference it. Another circular reference!</p>

<p>It gets worse though: One of the components is the <code class="code">ScriptComponent</code>, which allows custom user code to hook into the engine. Any given script can reference whatever, including itself, its game object, its parent or children, and any other component, script, asset or currently loaded object. This is not only a dependency nightmare, but a polymorphism nightmare as well.</p>

<p>But oh, we are not done yet. My chosen solution has its own set of problems: I chose to use a single scene object, which owns and thus stores <i>all</i> loaded objects. Any references between the objects are solved via handles. These easily copyable handles are simple token objects, which store information on how to get the according object from the scene. But of course, this requires a custom reflection-like solution, such that you can resolve the type of the handle at runtime. And because Rust doesn't have reflection, I was forced to implement it! While a single handle struct might've been enough, I want it to be type safe. I want that when you are trying to get a <code class="code">MeshComponent</code> with a <code class="code">ScriptHandle</code>, the compiler refuses to compile the code. Thus, generics and <a href="https://doc.rust-lang.org/std/marker/struct.PhantomData.html" target="_blank" rel="noopener noreferrer"><code class="code">PhantomData</code></a>s everywhere. As a direct consequence, I also use one too many <a href="https://doc.rust-lang.org/std/mem/fn.transmute.html" target="_blank" rel="noopener noreferrer"><code class="code">transmute</code></a>s, sailing very close to the unsafe brink of undefined behavior.</p>

<p>And then, the scene must also be thread safe. Wrap the entire thing in a <a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html" target="_blank" rel="noopener noreferrer"><code class="code">Mutex</code></a> and call it a day &#58;&#94;&#41; No, I chose interior mutability, to avoid congestion. For this, every object is stored in a custom thread safe <a href="https://doc.rust-lang.org/std/cell/struct.RefCell.html" target="_blank" rel="noopener noreferrer"><code class="code">RefCell</code></a>, with assertions removed for release builds, for maximum performance. (Premature optimization is the root of all evil you say? Never heard of it!) And the engine must hook into the scene in many different ways. All script callbacks need to be called from various locations in the game loop. And somehow the renderer must access the mesh components to render everything. To top it all off, the system must be flexible enough for extensions, such that more components can be added in the future.</p>

<p>Sheesh. That's a lot of stuff. But I've done it. And the API is squeaky clean. Here, take a look:</p>


<code class="code code_block">
<span style="color:var(--pico-8-dark-grey)">
<span style="color:var(--pico-8-washed-grey)">// create game object</span><br>
<span style="color:var(--pico-8-purple)">let</span> <span style="color:var(--pico-8-black)">game_object</span> = <span style="color:var(--pico-8-orange)">GameObjectHandle</span>::<span style="color:var(--pico-8-cyan)">new</span>(&<span style="color:var(--pico-8-black)">scene</span>)?;<br>
<br>
<span style="color:var(--pico-8-washed-grey)">// set name and position</span><br>
<span style="color:var(--pico-8-black)">game_object</span>.<span style="color:var(--pico-8-cyan)">set_name</span>(&<span style="color:var(--pico-8-black)">scene</span>, <span style="color:var(--pico-8-green)">"my awesome game object"</span>)?;<br>
<span style="color:var(--pico-8-black)">game_object</span>.<span style="color:var(--pico-8-cyan)">set_local_position</span>(&<span style="color:var(--pico-8-black)">scene</span>, <span style="color:var(--pico-8-cyan)">Vec3</span>(<span style="color:var(--pico-8-brown)">42.0</span>, <span style="color:var(--pico-8-brown)">-13.0</span>, <span style="color:var(--pico-8-brown)">123.0</span>))?;<br>
<br>
<span style="color:var(--pico-8-washed-grey)">// add script</span><br>
<span style="color:var(--pico-8-purple)">let</span> <span style="color:var(--pico-8-black)">my_script</span> = <span style="color:var(--pico-8-black)">game_object</span>.<span style="color:var(--pico-8-cyan)">add_script</span>::&lt;<span style="color:var(--pico-8-orange)">MyScript</span>&gt;(&<span style="color:var(--pico-8-black)">scene</span>)?;<br>
<br>
<span style="color:var(--pico-8-washed-grey)">// access and modify `MyScript::some_field`</span><br>
<span style="color:var(--pico-8-black)">my_script</span>.<span style="color:var(--pico-8-cyan)">script_mut</span>(&<span style="color:var(--pico-8-black)">scene</span>)?.some_field = <span style="color:var(--pico-8-green)">"hello world"</span>.<span style="color:var(--pico-8-pink)">to_string</span>();
</span>
</code>

<p>And the best part about it is, it just works. It runs, the unit tests succeed, and <a href="https://github.com/rust-lang/miri" target="_blank" rel="noopener noreferrer">miri</a> doesn't find undefined behavior. You can even double all of that, because all that runs without error in both debug and release builds! It simply works. It just does. And I really want you to appreciate that.</p>

<p>Every now and then, every couple of months, some indie dev team or company shares a hit piece on Rust, how they tried the language and had to abandon it because this, that and whatever reason. And the one reason that is always included is, that the borrow checker is stupidly difficult to work with. Having written the game objects I described above, I can sympathize with this argument. Anything sufficiently complicated is just such a pain in the ass. Rust evangelists will often tell you that <i>"you just don't understand how the borrow checker works"</i>, which is honestly such a farse. The borrow checker is easy. I believe any competent programmer will understand it in the first 10 minutes they spend with it. But the matter of fact is, its simple rules are very very hard to satisfy. And yet, if you manage to get your code to compile, it simply works. I can't be more clear than this. Pleasing the borrow checker results in less erroneous code.</p>

<img src="https://www.rismosch.com/articles/rust-is-the-future/C_Sharp_Logo_2023.svg" style="display: block; margin: auto; width: 200px; max-width: 100%;">

<p>This wasn't my first rodeo with hierarchical node systems. I've written one two years ago for my company. This version was written in C# and it is significantly simpler and more complex at the same time; it took me only a few days to get the first prototype working. But over time, problems started to creep up. I was tasked to include more features, which I were promised were absolutely necessary (spoiler alert, they weren't), resulting in messy implementations and spaghetti behind the scenes. Also some bullshit synchronization code was necessary, which needs to sync our nodes to 2 different node systems, and it must be easy to switch on and off, because of course it must. It also produces all kinds of events, whenever anything changes in the node, but this is unreliable and buggy as hell. No one fixes this, because nothing, and I mean NOTHING uses them. Yes, THE central node system, that sits in the center of our entire codebase has this huge complicated non-working deadweight attached to it.</p>

<p>These idiosyncrasies (and many more) make this C# node system such a pain to work with. But we can't fix it, because that requires time and money, which the company isn't willing to spent. So even though the initial implementation was a breeze to get working, over time the issues became apparent and years later we are still applying hacks to get around all the shortcomings. Compare that to the thing I've written in Rust: It was a major pain to get it to compile. But once it did, it just fucking works.</p>

<p>The Rust version frontloaded all the work, while the C# version revealed all the issues during the years.</p>

<img src="https://www.rismosch.com/articles/rust-is-the-future/rustacean-flat-happy.svg" style="display: block; margin: auto; width: 400px; max-width: 100%;">

<p>I don't want to dick ride Rust. As Bjarne Stoustroup famously said, I firmly believe that there are only two types of programming languages: The ones everyone complains about and the one no one uses. So here's a rundown of things I hate about Rust:</p>

<p><a href="https://www.rismosch.com/article?id=my-most-hated-feature-in-rust" target="_blank" rel="noopener noreferrer">Rust has no convenient base error type</a>; you need to download a crate or write your own. Speaking of errors, why can <a href="https://doc.rust-lang.org/std/sync/struct.PoisonError.html" target="_blank" rel="noopener noreferrer">mutexes be poisoned</a>? As far as I know, it's impossible to recover from this, so you might as well segfault. Yet, Rust forces me to handle poison errors anyway...</p>

<p>Rust is also infamous for its absolute dogshit syntax. It's already bad when you take a surface level glance at it, but have you seen the syntax for macros? At times it's worse than bash!</p>

<p>Anyway, who decided to use pipes for closure parameters?</p>

<code class="code code_block">
<span style="color:var(--pico-8-dark-grey)">
<span style="color:var(--pico-8-washed-grey)">
// this program prints:<br>
// i am a lambda<br>
// here's all the odd numbers: [2, 4, 6, 8]<br>
</span>
<span style="color:var(--pico-8-purple)">fn</span> <span style="color:var(--pico-8-cyan)">main</span>() {<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">// define and call lambda</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-purple)">let</span> <span style="color:var(--pico-8-black)">foo</span> = || <span style="color:var(--pico-8-pink)">println!</span>(<span style="color:var(--pico-8-green)">"i am a lambda"</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">foo</span>();<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">// iterator lambda example</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-purple)">let</span> <span style="color:var(--pico-8-black)">numbers</span> = [<span style="color:var(--pico-8-brown)">1</span>, <span style="color:var(--pico-8-brown)">2</span>, <span style="color:var(--pico-8-brown)">3</span>, <span style="color:var(--pico-8-brown)">4</span>, <span style="color:var(--pico-8-brown)">5</span>, <span style="color:var(--pico-8-brown)">6</span>, <span style="color:var(--pico-8-brown)">7</span>, <span style="color:var(--pico-8-brown)">8</span>, <span style="color:var(--pico-8-brown)">9</span>];<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-purple)">let</span> <span style="color:var(--pico-8-black)">odd_numbers</span> = <span style="color:var(--pico-8-black)">numbers</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.<span style="color:var(--pico-8-pink)">iter</span>()<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.<span style="color:var(--pico-8-pink)">filter</span>(|<span style="color:var(--pico-8-green)">x</span>| *<span style="color:var(--pico-8-green)">x</span> % <span style="color:var(--pico-8-brown)">2</span> == <span style="color:var(--pico-8-brown)">0</span>) <span style="color:var(--pico-8-washed-grey)">// yes, that's a lambda right here</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.<span style="color:var(--pico-8-pink)">collect</span>::&lt;<span style="color:var(--pico-8-orange)">Vec</span>&lt;<span style="color:var(--pico-8-orange)">_</span>&gt;&gt;();<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">println!</span>(<span style="color:var(--pico-8-green)">"here's all the odd numbers: {:?}"</span>, <span style="color:var(--pico-8-black)">odd_numbers</span>);<br>
}
</span>
</code>

<p>Also, why call it "closure"? Why not simply call it what every single other programming language calls it? Like "lambda", "anonymous function", "function pointer" or whatever?</p>

<p>Everything is so horribly nested! You have a match in a loop in a function in an impl in a mod and you are looking at 5-6 levels of indentation!</p>

<code class="code code_block">
<span style="color:var(--pico-8-dark-grey)">
<span style="color:var(--pico-8-pink)">mod</span> <span style="color:var(--pico-8-green)">MyPackage</span> {<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-purple)">struct</span> <span style="color:var(--pico-8-orange)">MyStruct</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-purple)">impl</span> <span style="color:var(--pico-8-orange)">MyStruct</span> {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-purple)">fn</span> <span style="color:var(--pico-8-cyan)">my_function</span>(&<span style="color:var(--pico-8-red)">self</span>) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-purple)">for</span> <span style="color:var(--pico-8-black)">option</span> <span style="color:var(--pico-8-purple)">in</span> <span style="color:var(--pico-8-cyan)">get_some_options</span>() {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-purple)">match</span> <span style="color:var(--pico-8-black)">option</span> {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">Some</span>(<span style="color:var(--pico-8-black)">value</span>) =&gt; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">println!</span>(<span style="color:var(--pico-8-green)">"6 levels of indentation!"</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">// some other code here</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_ =&gt; (),<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</span>
</code>

<p><code class="code">for</code> loops are nice at first glance, and they are, until you need a traditional one. For example when you conditionally want to increase <code class="code">i</code>. It gets worse in <code class="code">const</code> code, because <code class="code">for</code> isn't even supported there. The example below is legit code I had to write at one point. It's basically a desugared <code class="code">for</code> loop:</p>

<code class="code code_block">
<span style="color:var(--pico-8-dark-grey)">
<span style="color:var(--pico-8-orange)">const</span> <span style="color:var(--pico-8-brown)">HASH</span>: <span style="color:var(--pico-8-green)">u32</span> = {<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-purple)">let</span> <span style="color:var(--pico-8-orange)">mut</span> <span style="color:var(--pico-8-black)">hash</span>: <span style="color:var(--pico-8-green)">u32</span> = ...;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-purple)">let</span> <span style="color:var(--pico-8-orange)">mut</span> <span style="color:var(--pico-8-black)">i</span> = <span style="color:var(--pico-8-brown)">0</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-purple)">while</span> <span style="color:var(--pico-8-black)">i</span> < <span style="color:var(--pico-8-cyan)">get_length</span>() {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black)">hash</span> = ...;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black)">i</span> += <span style="color:var(--pico-8-brown)">1</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black)">hash</span><br>
};
</span>
</code>

<p>Amazing.</p>

<p>Or why do <code class="code">if</code> statements avoid brackets <code class="code">()</code>? Sure, it's less to type and one can get used to it. But the problem is, that no other programming language does this! Because of it, I can never build any muscle memory in both Rust and non-Rust languages. Sure, it isn't mandatory and I <i>can</i> use brackets in Rust if I want to, but <a href="https://doc.rust-lang.org/stable/clippy/usage.html" target="_blank" rel="noopener noreferrer">clippy</a> flags them as bad style. Do I look like someone who configures a fucking linting tool?</p>

<p>And then there is the turbofish. First, really stupid name. Second, you can't convince me that one absolutely needs the two double colons <code class="code">::</code> to denote a generic type. To use my game objects as an example:</p>

<code class="code code_block">
<span style="color:var(--pico-8-dark-grey)">
<span style="color:var(--pico-8-washed-grey)">// correct</span><br>
<span style="color:var(--pico-8-purple)">let</span> <span style="color:var(--pico-8-black)">my_script</span> = <span style="color:var(--pico-8-black)">game_object</span>.<span style="color:var(--pico-8-cyan)">add_script</span>::&lt;<span style="color:var(--pico-8-orange)">MyScript</span>&gt;(&<span style="color:var(--pico-8-black)">scene</span>)?;<br>
<br>
<span style="color:var(--pico-8-washed-grey)">// syntax error</span><br>
<span style="color:var(--pico-8-purple)">let</span> <span style="color:var(--pico-8-black)">my_script</span> = <span style="color:var(--pico-8-black)">game_object</span>.<span style="color:var(--pico-8-cyan)">add_script</span>&lt;<span style="color:var(--pico-8-orange)">MyScript</span>&gt;(&<span style="color:var(--pico-8-black)">scene</span>)?;<br>
</span>
</code>

<p>And I can go on and on. I hate Rust. But I continue to use it, because well, the sunken cost fallacy, but moreover because the borrow checker just leads to correct code.</p>

<img src="https://www.rismosch.com/articles/rust-is-the-future/ISO_C++_Logo.svg" style="display: block; margin: auto; width: 200px; max-width: 100%;">

<p>While my professional job is mostly C#, I do get to touch C++ from time to time. And every time I do so, I feel like a gun is pointed to my head. If I make a single incorrect assumption, BOOM, undefined behavior. In the best case it blows up in your face and crashes the program. In the worst case it quietly keeps working, until a customer submits a bug. And then you can't replicate it! I've been there! It sucks! It sucks so much! It's one of the worst bugs you can encounter! You can say skill issue, sure, but not even the greatest C++ wizard can avoid undefined behavior.</p>

<img src="https://www.rismosch.com/articles/rust-is-the-future/cpp.webp" style="display: block; margin: auto; max-width: 100%;">

<p><i>"Modern C++ is safe"</i> &#129299; says the C++ enthusiast, unwilling to acknowledge that they are in an abusive relationship. Sure, the newest C++ standard includes safety features, if you find a compiler that actually supports it. But when C++98 is the standard in your enterprise codebase, you're out of luck. Here's the kicker: Even if you use very modern C++, safety is still opt-in. You purposefully need to use the new safety features. Safety is not the default. No one is stops you from doing pointer arithmetic.</p>

<p>In Rust, safety is opt-out. Safety must purposefully be turned off by using <code class="code">unsafe</code>. <i>"If you are using unsafe you are writing Rust incorrectly"</i> &#128545; says the degenerate Rust evangelist. I do it all the time. It's no big deal. It's easy and I don't care. My point is this though: Safety is enabled by default. You can tell that a piece of code may cause undefined behavior, because it is clearly labeled by its <code class="code">unsafe</code> block. So, when you do a code review, you can point to it and yell at the junior why the fuck they thought it was necessary to include <code class="code">unsafe</code> code.</p>
    
<p>In C++ I write undefined behavior by accident. In Rust I write undefined behavior on purpose.</p>

<p><i>"Rust isn't 100% safe"</i> &#129299; says the educated Rust hater, pointing at bugs in the compiler. I mean, do I even have to argue about that? <i>Theoretically</i> Rust is safe (according to their own definition, which may be different than what you are thinking), but our world tends to be messy and not ideal. However, did you know that seatbelts aren't 100% safe either? It turns out, it's already a huge improvement when a new solution is safer than the current alternative, even if it isn't perfect.</p>

<p><i>"But Rust is not OOP"</i> &#128553; says the clean code obsessed, code smell avoiding programmer. I swear, the paradigm of the programming language doesn't matter, like at all. If C people can do polymorphism, so can you. Yet, OOP bros are acting like everything that isn't OOP is the devil incarnate. I constantly run into videos and articles about "bad code" and "how to avoid it". And they always spew nonsense like "avoid switch statements" and "you shouldn't use bools". What's next, "don't use variables"?!</p>

<p>You think I exaggerate? I am sorry to disappoint you, but these are talking points from messiah Uncle Bob himself:</p>

<ul>
<li><a href="https://youtu.be/2IotTzClOAQ" target="_blank" rel="noopener noreferrer">https://youtu.be/2IotTzClOAQ</a></li>
<li><a href="https://youtu.be/2Q9GRPxqCAk" target="_blank" rel="noopener noreferrer">https://youtu.be/2Q9GRPxqCAk</a></li>
</ul>

<p>I swear to God, if I hear one more time that a class should have no more than 100 lines of code I WILL FUCKING EXPLODE! I consistently write code that exceeds 200 lines per file, I'd say around 500 is my average. But I do so because I avoid oneliners, use many, MANY variables, and I like to keep related code in one place. I do not want to spread my code over multiple files, so that future me doesn't need a huge mental map and 100 active tabs to debug it. But OOP bros just cannot shut up about how many lines of code a single method should have. I am seriously starting to question: Do you guys even write software? Or do you just glue frameworks together?</p>

<p>Look, I take great issue with OOP bros trying to sell me "clean code". I am sorry, but I have seen the absolute disaster that these "programmers" produce. I have witnessed widget-based GUI applications written in Python, that despite having less than 7 buttons, somehow struggle to run at 5 FPS. And you are telling me, I am supposed to listen to their disgusting "code smells" and how I am supposed to structure my code?! Come on person, get a grip!</p>

<!--<video loop="true" autoplay="autoplay" muted="true" style="max-width:100%; display: block; margin: auto;" loading='lazy'>
<source src="squidward.mp4" type="video/mp4">
</video>-->

<img src="https://www.rismosch.com/articles/rust-is-the-future/programmers.jpg" style="display: block; margin: auto; max-width: 100%;">

<p>Anyway, this post has absolutely gone off the rails, hasn't it? What was the title of this post? Ah yes, Rust is the future. While writing, ranting seemed natural for this kind of topic. Kudos if you've actually read my incoherent ramblings. Let's come to an end and wrap things up.</p>

<p>Rust has one killer feature: The borrow checker. All arguments that you throw against Rust are immediately invalidated, because your preferred programming language simply does not have a borrow checker. I am going to make the prediction that C++ is going to lose relevance over the next decades. It won't die, simply because of its historical significance and wide adoption. But C++ will fade, for sure. C will never die, because it has transcended into the true and only low-level language (above assembly). C has become the de facto standard for interopability between any two programming languages. Higher level languages like Python, JavaScript and Java will stay around, because they are easy to program in. Garbage collected languages are inherently safe without any hassle. But C++ in particular will lose significance. If it isn't Rust, then another programming language with a borrow checker will take the place of C++. But as it stands today, Rust is the only programming language which is mature enough to compete with C++.</p>]]></content:encoded></item><item><title>My thoughts on Monstercat 001-030</title><link>https://www.rismosch.com/article?id=my-thoughts-on-monstercat-001-030</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Music]]</category><guid isPermaLink="false">my-thoughts-on-monstercat-001-030</guid><pubDate>Sun, 01 Dec 2024 15:17:58 +0100</pubDate><description>I was on a nostalgia trip and listened to all Monstercat compilation albums, 001 to 030. Here's what I think about each one.</description><content:encoded><![CDATA[<p>So, lately I've been on a nostalgia trip, meaning I've been on a quest to listen to music from 10 years ago. And that is primarily Touhou and Monstercat. Touhou is a different beast, which I am not ready to talk about yet, so I am just mentioning its name and leaving that as it is. Monstercat on the other hand is just music, and it's easy to just talk about music.</p>

<p>For context, back then I was really into Minecraft, which is the primary reason in my interest in programming nowadays. Anyway, YouTubers back then were using Monstercat music. These YouTubers shall not be named, for reasons that if you know you know. And as the music fanatic (snob) that I am, it was only a matter of time before I would check out this music.</p>

<p>So what is Monstercat? Simply put, a record label. Monstercat was founded in 2011. To this day, they release EDM tracks of different genres from various artists. Initially, they were simply a friends group. But the label expanded massively to include many other artists. Every couple of months, they would release an album, including the previously released songs. Later they would include a continuous mix of all the songs in each album. And it's these albums that I will cover in this post.</p>

<p>The albums are numbered from 001 to 030. I found them between the releases of 015 and 016, and I've been continually following till around 020. So my ratings are biased around that time. Obviously, I was able to check out their previous stuff, but around 020 my interest tapered off. I've been following a few select artists, but most stuff after 020 I went into somewhat blind.</p>

<p>Okay, that's it with the introduction. Without further ado, I will give you my thoughts on each of these 30 albums, in chronological order. At the end of the post, I've included a tier list. Let's go!</p>

<h2>001 Launch Week</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/001_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Playlist: <a href="https://youtube.com/playlist?list=PLe8jmEHFkvsafbwSh8YCVDdFG4McIB4Ke" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<p>Ah, humble beginnings. Way before my time and thus 0 nostalgia. 001 is Monstercats first and shortest album, clocking in at only 7 songs, which in total is about half an hour. Later albums eventually become 2 hours long, but since 001 is so short, it's very easy to relisten again and again. But honestly, I rarely do so. It is easily the most amateurish album. The music is not good, and it's only interesting to see where the bar was back then. People gotta start somewhere, and I don't hold that against them. It reminds me a lot of my own music, which is charming in a sense.</p>

<p>So yeah, the album is not good, thus easily bottom tier.</p>

<h2>002 Early Stage</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/002_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Playlist: <a href="https://youtube.com/playlist?list=PLe8jmEHFkvsYNjQl_66_c17eNgdwyHXKc" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/2euA3zfxoIQ" target="_blank" rel="noopener noreferrer">Matduke - Rock the House</a></li>
<li><a href="https://youtu.be/1x9VeneffTM" target="_blank" rel="noopener noreferrer">Noisestorm - Airwaves</a></li>
<li><a href="https://youtu.be/O3f10xcrZFU" target="_blank" rel="noopener noreferrer">Feint We Move</a></li>
<li><a href="https://youtu.be/sH36yjQyMBs" target="_blank" rel="noopener noreferrer">TwoThirds - Lost</a></li>
</ul>

<p>More amateurishness! I am considering this album more like a continuation of the previous one, because there are more new people with about the same skill level in music production, with the exception of Matduke and Project 46. These two were definitely ahead of everyone else. Their presence and quality of music gave me a huge whiplash. Noisestorm is also a notable artists. Long before I was aware of Monstercat, I knew about him and his music. Hearing his song <a href="https://youtu.be/1x9VeneffTM" target="_blank" rel="noopener noreferrer">Airwaves</a> really hit my nostalgia. But other than that, it's till an amateurish album, without the historical significance of 001. I was constantly thinking, that this is pretty much "Dubstep before it was cool". It doesn't even come close to Brostep, and I am very thankful for that. <a href="https://youtu.be/-hLlVVKRwk0" target="_blank" rel="noopener noreferrer">All my homies hate Skrillex</a> after all. One thing I am surprised about is how similar Stephen Walking sounds like to later in his career. His experience and quality obviously got better, but the style kept pretty much the same.</p>

<h2>003 Momentum</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/003_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Playlist: <a href="https://youtube.com/playlist?list=PLe8jmEHFkvsYSGKuY_Ii_4UbyF8uwueK_" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/CBwhH9EluXc" target="_blank" rel="noopener noreferrer">Matduke - Shivers</a></li>
<li><a href="https://youtu.be/Fy68No-L6Pg" target="_blank" rel="noopener noreferrer">Stephen Walking - Top of the World</a></li>
<li><a href="https://youtu.be/EwDIs6zTBeA" target="_blank" rel="noopener noreferrer">Feint - Formless</a></li>
<li><a href="https://youtu.be/vkYKPuOn8Uo" target="_blank" rel="noopener noreferrer">Obsidia - Android</a></li>
</ul>

<p>The quality starts to improve. Again, Matduke is much more ahead than the others. <a href="https://youtu.be/CBwhH9EluXc" target="_blank" rel="noopener noreferrer">Shivers</a> is the best song on this album and easily one of the best songs on Monstercat <i>ever</i>. I think this is the album where Monstercat is gaining momentum, pun not intended. Like, the music is still amateurish, but it's starting to gain character. I like the songs in the beginning and I really vibe with it. It's amazing. And then it rips the band-aid off with the drop of <a href="https://youtu.be/vkYKPuOn8Uo" target="_blank" rel="noopener noreferrer">Obsidia - Android</a>, which whiplashed me into fucking oblivion. It's so disjointed from the first 3 songs, which I find absolutely hilarious. The album drops off a bit in the end and it becomes somewhat boring. Though, Stephen Walking definitely does not drop off. <a href="https://youtu.be/Fy68No-L6Pg" target="_blank" rel="noopener noreferrer">Top Of The World</a> is definitely one of his best songs. I understand why out of his entire discography, this is the one he decided to remaster 2 years later. Absolute legend.</p>

<h2>004 Identity</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/004_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Playlist: <a href="https://www.youtube.com/playlist?list=PLe8jmEHFkvsZnCLg1m_M0ISXPdbMyqbXO" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/PFH1aEjKfjE" target="_blank" rel="noopener noreferrer">DotEXE - Run Away From Me</a></li>
<li><a href="https://youtu.be/-LXwodhuZrU" target="_blank" rel="noopener noreferrer">Neilio - Outside This World</a></li>
</ul>

<p>Very forgettable. I don't think 004 has a single good track. As such, I don't have much to say about it. The only thing I want to note is <a href="https://youtu.be/PFH1aEjKfjE" target="_blank" rel="noopener noreferrer">DotEXE - Run Away From Me</a>. Its melody reminds me of a German pop song, which I wont name, because the song is garbage and I hate it. However, I really like the melody, and I've considered multiple times to remix the song. But for that, I need to get back to making music, which I can't, <a href="https://www.rismosch.com/article?id=why-i-make-my-own-game-engine" target="_blank" rel="noopener noreferrer">because I'm a masochist</a>. Other than that, <a href="https://youtu.be/-LXwodhuZrU" target="_blank" rel="noopener noreferrer">Neilio - Outside This World</a> is decent and worth mentioning.</p>

<h2>005 Evolution</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/005_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Album Mix: <a href="https://youtu.be/P1wZEvOP0Sw" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/Hag2JWC8qZ0" target="_blank" rel="noopener noreferrer">Arion - Internet Rebellion</a></li>
<li><a href="https://youtu.be/6d9h867DAMM" target="_blank" rel="noopener noreferrer">23 - Fresh</a></li>
<li><a href="https://youtu.be/JjOeSzktwJs" target="_blank" rel="noopener noreferrer">Noisestorm - Renegade</a></li>
<li><a href="https://youtu.be/b2jwJ1FOaHA" target="_blank" rel="noopener noreferrer">Kings Of The City - Make Me Worse (Muzzy Remix)</a></li>
</ul>

<p>First album that got a continuous mix. And to be honest, this album is an absolute banger. It's full to the brim with amazing tracks. While still at an amateurish level, the quality is good enough to be recommended wholeheartedly. And the transitions between the songs are very decent, which is commendable. Ahem, 010, ahem. I can't stress enough how much I love this album. <a href="https://youtu.be/Hag2JWC8qZ0" target="_blank" rel="noopener noreferrer">Arion - Internet Rebellion</a> probably radicalized me. Today I am very much in favor of abolishing copyright. With his remix, Muzzy introduced me to <a href="https://youtu.be/DpV0ci7PR1g" target="_blank" rel="noopener noreferrer">Kings Of The City</a>, a band which disbanded, but which I hold to a very high regard. Also, <a href="https://youtu.be/6d9h867DAMM" target="_blank" rel="noopener noreferrer">23 - Fresh</a> goes so hard. Tristam is amazing. And so much more songs, that are all "Dubpstep before it was cool".</p>

<p>All around a very solid album. I recommend it. A-Tier.</p>

<h2>006 Embrace</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/006_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Album Mix: <a href="https://youtu.be/6usL6hCjL2I" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/MRkUw3uc324" target="_blank" rel="noopener noreferrer">Televisor - Rock The Flock</a></li>
<li><a href="https://youtu.be/WOPEbIIQRRI" target="_blank" rel="noopener noreferrer">Hot Date! & Chrisson - Overcome (This Time)</a></li>
<li><a href="https://youtu.be/M_aueYyzpCw" target="_blank" rel="noopener noreferrer">Tristam - Talent Goes By</a></li>
<li><a href="https://youtu.be/P8fFkzYvBPg" target="_blank" rel="noopener noreferrer">Project 46 M.O.A.B.</a></li>
</ul>

<p>One of the first albums I bought was <a href="https://youtu.be/MRlDXlECX0s" target="_blank" rel="noopener noreferrer">Monstercat Best of 2012</a>. This was mainly laziness, as it included many past songs. Listening to the Best-of, I didn't need to actually listen to all the previous albums. I am mentioning this, because 006 is the first album that has tracks on this Best-of album. With 001 - 004, I mostly felt indifference and slight annoyance, but with 006 and the albums thereafter, I could do one of <a href="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/Leonardo_DiCaprio.jpeg" target="_blank" rel="noopener noreferrer">these</a>. But other than that, the album is somewhat underwhelming. It has some absolute bangers, like Televisor, who never disappoints. <a href="https://youtu.be/WOPEbIIQRRI" target="_blank" rel="noopener noreferrer">Hot Date! & Chrisson - Overcome (This Time)</a> is amazing. But other than that, I am not really feeling this album. Now typing this out and only seeing my picked highlights, I can't remember anything else about this album.</p>

<h2>007 Solace</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/007_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Album Mix: <a href="https://youtu.be/WR2PHbvS3GQ" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/G1qO2pxzHNE" target="_blank" rel="noopener noreferrer">Tristam - I Remember</a></li>
<li>Overwerk - House</li>
<li><a href="https://youtu.be/ihDkZC5PmiA" target="_blank" rel="noopener noreferrer">Feint & Boyinaband feat. Veela - Time Bomb</a></li>
<li><a href="https://youtu.be/XN4WpPd-Ek0" target="_blank" rel="noopener noreferrer">Tut Tut Child - Maelstrom</a></li>
</ul>

<p>This is THE best album Monstercat has ever released. Period. This is quite a jump, considering that I've called 006 mid. 007 wasn't new when I got into Monstercat, so it has absolutely no novelty. But the tracks are just so amazing that it was only a matter of time before I stumbled over this album. And then, I just couldn't stop listening to it. Every now and then I came back to this album, even before I went on this nostalgia trip. It is honestly that good. This album also introduced me to <a href="https://youtube.com/playlist?list=PLa4yK1a5RlqK6jHDH474RdT731M5hTnOJ" target="_blank" rel="noopener noreferrer">Overwerk</a>, who genuinely makes good house music. Funnily enough, he wants to be fully independent. He requested his song, House, to be removed from Monstercat. As such, you can only find reuploads on YouTube but not the original. I wont link them, but if you search you'll find it.</p>

<p>Choosing highlights for this one was rather difficult. I don't want to include too many songs per album. So while I absolute love everything on this album, I had to decide, and the songs above are what I landed on.</p>

<h2>008 Anniversary</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/008_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Album Mix: <a href="https://youtu.be/NoJg0wPp8vM" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/ou03DhIp3zI" target="_blank" rel="noopener noreferrer">DotEXE - Hipster Cutthroat</a></li>
<li><a href="https://youtu.be/7NeYe7j02ME" target="_blank" rel="noopener noreferrer">Muzzy & Day One - Black Magic</a></li>
<li><a href="https://youtu.be/CzQkLV6QdYc" target="_blank" rel="noopener noreferrer">Pegboard Nerds - Rocktronik</a></li>
<li><a href="https://youtu.be/t0cIUupoDEo" target="_blank" rel="noopener noreferrer">Rogue - Daybreak</a></li>
</ul>

<p>I think this album marks a point, where Monstercat officially loses its amateurish status. 007 already was rather good, obviously. But 008 was better sound quality wise, even if it isn't nearly as amazing. The mixing is good, but none of the songs wow me. As such 008 fell somewhat flat for me. But I have to highlight this one song: <a href="https://youtu.be/ou03DhIp3zI" target="_blank" rel="noopener noreferrer">DotEXE - Hipster Cutthroat</a>. The song isn't that good and somewhat boring, but the first drop is absolutely hilarious. I can never not laugh when I hear it. It's amazing and I won't spoil it for you. Go listen to it.</p>

<h2>009 Reunion</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/009_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Album Mix: <a href="https://youtu.be/TplQtfgGK1k" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/FTUVjaZ3xAs" target="_blank" rel="noopener noreferrer">Ephixa - Awesome To The Max</a></li>
<li><a href="https://youtu.be/xU5lV8iBe64" target="_blank" rel="noopener noreferrer">Rogue - Nightfall</a></li>
<li><a href="https://youtu.be/irOuRCkO0nQ" target="_blank" rel="noopener noreferrer">Pegboard Nerds - Fire in the Hole</a></li>
<li><a href="https://youtu.be/JoVSsGgbVK4" target="_blank" rel="noopener noreferrer">Krewella - One Minute (DotEXE 'Dopest Dope' Remix)</a></li>
</ul>

<p>I have very mixed feelings on this album. The start is very weak and forgettable. In the middle it starts getting good and peaks with <a href="https://youtu.be/FTUVjaZ3xAs" target="_blank" rel="noopener noreferrer">Ephixa - Awesome To The Max</a>. But then it does very questionable transitions between songs. So yeah, half of the album is good, the other not so much. And the mix isn't a joy to listen to. I don't have much else to say about it, other than 009 really annoys me. Maybe I should listen to the individual songs and not the mix.</p>

<h2>010 Conquest</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/010_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Album Mix: <a href="https://youtu.be/xkE4aYclKEA" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/cvq7Jy-TFAU" target="_blank" rel="noopener noreferrer">Feint - Snake Eyes (feat. CoMa)</a></li>
<li><a href="https://youtu.be/cj73hUrwM1s" target="_blank" rel="noopener noreferrer">Tristam - Truth</a></li>
<li><a href="https://youtu.be/80_tv-_OPT4" target="_blank" rel="noopener noreferrer">Skifonix - Flatline</a></li>
<li><a href="https://youtu.be/LrgLyiwnFWU" target="_blank" rel="noopener noreferrer">Rezonate - The Phoenix</a></li>
</ul>

<p>From bad to worse. 009 is not good, but 010 is somehow worse. I have very bad feelings about this one. In the complete opposite direction of 009, the beginning is strong, but then it just falls of a cliff. The songs are nice, but then the transitions are just such ass. I am just wondering what happened here? 005 was the first album with a mix, and the mixes were decent thus far, but this album just sucks. It sucks so much. The most egregious thing in the entire album however, is the disservice to <a href="https://youtu.be/cvq7Jy-TFAU" target="_blank" rel="noopener noreferrer">Feint - Snake Eyes (feat. CoMa)</a>. Don't get me wrong, the song is absolutely amazing and one of the best songs on Monstercat ever, but 010 decided put <i>only</i> 45 seconds of it into the mix. Like wtf is this? I am annoyed. I don't like this. I don't like this at all.</p>

<h2>011 Revolution</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/011_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Album Mix: <a href="https://youtu.be/2HC3xBgP8qw" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/C9o_ODo-380" target="_blank" rel="noopener noreferrer">AZEDIA - Precipitate</a></li>
<li><a href="https://youtu.be/xZCJiI9JsO0" target="_blank" rel="noopener noreferrer">Stereotronique - Stock & Pull</a></li>
<li><a href="https://youtu.be/Y1KR09vmvNk" target="_blank" rel="noopener noreferrer">Eminence - Falling Stars</a></li>
<li><a href="https://youtu.be/3QXzwSSmz7Q" target="_blank" rel="noopener noreferrer">Ramases B - Come & Go (feat. Charlotte Haining)</a></li>
</ul>

<p>Amazing album. A-Tier. Not much more to say. It's just a very solid album with nothing to complain. The songs are stupidly amazing, and so are the transitions. I recommend 011. Go listen to it.</p>

<h2>012 Aftermath</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/012_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Chaos Album Mix: <a href="https://youtu.be/_XvR6urk9UA" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Order Album Mix: <a href="https://youtu.be/MD3ROlR6k8I" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/exCO9225g20" target="_blank" rel="noopener noreferrer">Project 46 - No One (feat. Matthew Steeper)</a></li>
<li><a href="https://youtu.be/JJvdp0XpSj0" target="_blank" rel="noopener noreferrer">Pegboard Nerds ft. Splitbreed - We Are One</a></li>
<li><a href="https://youtu.be/R0P_f0gXXqs" target="_blank" rel="noopener noreferrer">Vicetone - Heartbeat (feat. Collin McLoughlin)</a></li>
<li><a href="https://youtu.be/ZVg4QgKh3Hg" target="_blank" rel="noopener noreferrer">Hellberg - Get Up</a></li>
<li><a href="https://youtu.be/zk4xgu03dBs" target="_blank" rel="noopener noreferrer">TwoThirds - Origami</a></li>
</ul>

<p>The first 2-hour album! Split between two mixes, each being one hour long. This will be the standard for all remaining albums. More music!</p>

<p>Anyway, 012 is decent. B-Tier. Everything is good, but nothing on it really wows me. I keep batting on transitions, but that's because a good one can go a long way. What I mean by that, take the transition between <a href="https://youtu.be/wFNrVFt3DjE" target="_blank" rel="noopener noreferrer">Day One - World's End</a> and <a href="https://youtu.be/a4-Tb4rHZt8" target="_blank" rel="noopener noreferrer">Tut Tut Child - Hummingbird (feat. Augustus Ghost)</a> as an example. Here's a link with a timestamp: <a href="https://youtu.be/MD3ROlR6k8I?t=312" target="_blank" rel="noopener noreferrer">https://youtu.be/MD3ROlR6k8I?t=312</a>. Honestly, this is THE best transitions on all Monstercat albums. Period. The scales between the songs don't quite match, resulting in some very harsh dissonance. Combine that with the low energy of World's End and it achieves some really deep sadness. But then it cuts, which suddenly resolves the dissonance. Immediately afterwards the vocalist on Hummingbird goes strong and loud. This clash of dissonance being resolved and the mix shifting into such a high gear is simply amazing.</p>

<h2>013 Awakening</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/013_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Dawn Album Mix: <a href="https://youtu.be/BA7_Td0Mxgk" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Dusk Album Mix: <a href="https://youtu.be/c3n3a_Muzcc" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/-JNDliFODF4" target="_blank" rel="noopener noreferrer">Stephen Walking - Short Shorts</a></li>
<li><a href="https://youtu.be/QqbMT9NNYWk" target="_blank" rel="noopener noreferrer">Feint - Lonesong</a></li>
<li><a href="https://youtu.be/QMokMQ8Bu7Y" target="_blank" rel="noopener noreferrer">Pegboard Nerds & Tristam - Razor Sharp</a></li>
<li><a href="https://youtu.be/4G10QL3VBrw" target="_blank" rel="noopener noreferrer">Protostar & MakO - No Fire (feat. Rachel Hirons)</a></li>
<li><a href="https://youtu.be/U1GMKGjMt3o" target="_blank" rel="noopener noreferrer">Hellberg & Deutgen vs Splitbreed - Collide</a></li>
</ul>

<p>Very good album. I was surprised by how much I liked it actually. I was at first very torn giving it A or B-Tier. But now relistening to the highlights, I am placing it much higher in solid of A-Tier. 013 graced us with this absolute Masterpiece: <a href="https://youtu.be/-JNDliFODF4" target="_blank" rel="noopener noreferrer">Stephen Walking - Short Shorts</a>. The music video is simply brilliant. Stephen Walking proved to us that he is indeed worthy of his name. One thing that you might know about me, is that I don't have a driver's license. I am literally walking everywhere. Maybe, just maybe, this video radicalized me to a point that I never considered getting a driver's license. Nonetheless, Short Shorts is funny, and I love it.</p>

<p>Very cool album. Out of all of the ones in this nostalgia trip, 013 is the one I already went back to multiple times. I think I've found a new favorite.</p>

<h2>014 Discovery</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/014_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Odyssey Album Mix: <a href="https://youtu.be/qNDYQs1vvY4" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Journey Album Mix: <a href="https://youtu.be/eTiiHSGMUWc" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/fgx_MWjhF1A" target="_blank" rel="noopener noreferrer">7 Minutes Dead - Delayed Friend Request</a></li>
<li><a href="https://youtu.be/SQRIaztIf3E" target="_blank" rel="noopener noreferrer">Lets Be Friends - Manslaughter (VIP Mix)</a></li>
<li><a href="https://youtu.be/GjTlEM99rv8" target="_blank" rel="noopener noreferrer">Mr FijiWiji & Direct - Hysteria</a></li>
<li><a href="https://youtu.be/5-t5s6i4vTA" target="_blank" rel="noopener noreferrer">Falcon Funk - Leophant</a></li>
<li><a href="https://youtu.be/u_kT0uR64GA" target="_blank" rel="noopener noreferrer">Televisor - Old Skool</a></li>
</ul>

<p>Decent Album. Nothing to complain about. But somewhat forgettable. It has not many cool tracks that I celebrate. It's main saving grace is twofold: First, it was one of the albums I owned as a kid, and second, I freaking love DnB. Even though I am fairly familiar with it, I just can't love this album. The transitions are super smooth. Especially between <a href="https://youtu.be/1iXZ8i86AyU" target="_blank" rel="noopener noreferrer">Razihel - Bad Boy</a> and <a href="https://youtu.be/f5Gul3UVFeg" target="_blank" rel="noopener noreferrer">Bustre - Riftwalk</a>, or <a href="https://youtu.be/GjTlEM99rv8" target="_blank" rel="noopener noreferrer">Mr FijiWiji & Direct - Hysteria</a> and <a href="https://youtu.be/g7rtC0Cjo08" target="_blank" rel="noopener noreferrer">Televisor - Dream Soda</a>. Here are the transitions if you wanna listen:</p>

<ul>
<li><a href="https://youtu.be/qNDYQs1vvY4?t=1185" target="_blank" rel="noopener noreferrer">https://youtu.be/qNDYQs1vvY4?t=1185</a></li>
<li><a href="https://youtu.be/qNDYQs1vvY4?t=3560" target="_blank" rel="noopener noreferrer">https://youtu.be/qNDYQs1vvY4?t=3560</a></li>
</ul>

<p>Retrospectively, I am surprised by how much DnB is in the Odyssey mix. If it weren't for that, I probably would've given this album C-Tier. One thing that I am very proud about myself is my very broad taste in music. I am not stupid enough to claim that I listen to all genres, but I listen to heck of a lot. But if I had to pick a favorite, it's probably DnB. From <a href="https://youtu.be/IgdPuvltiRE" target="_blank" rel="noopener noreferrer">Jungle</a> to <a href="https://youtu.be/BNVg9nO2R0o" target="_blank" rel="noopener noreferrer">Intelligent DnB</a>, <a href="https://www.youtube.com/playlist?list=OLAK5uy_mM-TYvpChVGiYiTwM-HzIUmuujJd2ae9o" target="_blank" rel="noopener noreferrer">early Breakcore</a> or <a href="https://www.youtube.com/playlist?list=OLAK5uy_n6JbLO7UGHU982Ls6kyLYVXwe8R6jEC0k" target="_blank" rel="noopener noreferrer">modern Breakcore</a>, <a href="https://www.youtube.com/watch?v=I8CclT_16G0&list=OLAK5uy_nQDBv6d8yGaRObX_mIKW05ksSHOh-txQU&index=24" target="_blank" rel="noopener noreferrer">Neurofunk</a> or whatever other DnB subgenres there are, I just fucking love breakbeats. Funnily enough, I put no DnB songs into 014s highlights lol. Probably because single DnB songs are rarely bangers, and entire mixes are usually much more enjoyable. As a kid, I remember not really enjoying Bustres kind of DnB. But now that I am older, his DnB matches more to what I've linked above, and Bustre is now one of my all-time favorites. How time changes.</p>

<p>Odyssey is definitely the better half of this album. Journey is mid.</p>

<h2>015 Outlook</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/015_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Reflection Album Mix: <a href="https://youtu.be/hoGBSUxj55M" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Visionary Album Mix: <a href="https://youtu.be/qDmNwooRjuM" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/e0XY1kLMy7o" target="_blank" rel="noopener noreferrer">Project 46 - Motionless (feat. Seri)</a></li>
<li><a href="https://youtu.be/1dcXmkco5ko" target="_blank" rel="noopener noreferrer">Braken - To The Stars</a></li>
<li><a href="https://youtu.be/IbtMWez8svU" target="_blank" rel="noopener noreferrer">Droptek & Tut Tut Child - Drop That Child</a></li>
<li><a href="https://youtu.be/rwG39LNbT0A" target="_blank" rel="noopener noreferrer">Mitchell Claxton - Wuxia</a></li>
<li><a href="https://youtu.be/V_8E0QXzebc" target="_blank" rel="noopener noreferrer">Haywyre - Back and Forth</a></li>
</ul>

<p>A-Tier. Easily. As the last album before I discovered Monstercat, it was foreseeable that I rank this one highly, no? Good tracks. Decent transitions and oh my god, the nostalgia! I cannot stress enough how much this album hit the spot. But even with my rose-tinted glasses, I couldn't put it into S-Tier. It has some very odd songs, which are really hit or miss. But my nostalgia makes up for it. I enjoy this album very much.</p>

<h2>016 Expedition</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/016_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Arrival Album Mix: <a href="https://youtu.be/n0ABE5XA95c" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3> Album Mix: <a href="https://youtu.be/iIQgFpKfo7Y" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/i0Ew3cl1gyc" target="_blank" rel="noopener noreferrer">Rezonate - Canvas</a></li>
<li><a href="https://youtu.be/59M5z0c8YtE" target="_blank" rel="noopener noreferrer">Tristam - Once Again</a></li>
<li><a href="https://youtu.be/k1IaGHfZ4YU" target="_blank" rel="noopener noreferrer">Bustre - Shadow</a></li>
<li><a href="https://youtu.be/PhGtxxxorPk" target="_blank" rel="noopener noreferrer">7 Minutes Dead - Peacock</a></li>
<li><a href="https://youtu.be/oO10eNicsfQ" target="_blank" rel="noopener noreferrer">Lets Be Friends - FTW</a></li>
</ul>

<p>Oh boy. The first album after I discovered Monstercat. For me, this hits, and it hits hard. I know all the songs by heart. Even the ones that I didn't like at first have finally grown on me. The songs are amazing. The transitions are great. All around a very awesome package. Out of all albums, choosing the highlights for this was stupendously difficult. Because no matter how I choose, I had to sacrifice all the other songs I loved. If you allow my indulgence, I want to write a small paragraph for each song and why I chose it. Thanks.</p>

<p><a href="https://youtu.be/i0Ew3cl1gyc" target="_blank" rel="noopener noreferrer">Rezonate - Canvas</a> is possibly the most chill song I've ever heard. And it's catchy! While I enjoy calm music from time to time, it isn't my first pick when I want to listen or share "good music". I want to be stimulated, and calm music does the opposite: It relaxes. Canvas is not like that. It penetrates my unfair standard that I've set for my blog post and I always look forward to this song when listening to 016. The best song Monstercat has ever released is <a href="https://youtu.be/Fkwtq2uhbmU" target="_blank" rel="noopener noreferrer">Ramases B - Transformations</a>, which is on 016 but not on my list, because it didn't fit the vibe of what I am going for here. But if it weren't for Transformations, Canvas is the best song on 016.</p>

<p>Tristam was always a fan favorite. His music is melodic and grandiose. When I first heard <a href="https://youtu.be/59M5z0c8YtE" target="_blank" rel="noopener noreferrer">Once Again</a> 10 years ago, it was weird. Like the harmony was something I've never heard before. It didn't resolve immediately and it really isn't that dissonant. It's a flavor that stuck with me. Today I'm into much more <a href="https://youtu.be/m00GvZzRCb4" target="_blank" rel="noopener noreferrer">weird stuff</a> than in the past, but Once Again was a first for me. The ending of the song is absolutely brilliant. When the last drop is a 10 in terms of energy, then outro is an 11. It always gives me chills.</p>

<p><a href="https://youtu.be/k1IaGHfZ4YU" target="_blank" rel="noopener noreferrer">Bustre - Shadow</a> had to grow on me. As I've said in 014, Bustre was definitely not my favorite. His DnB simply didn't have the punch like all the others, and it is comically simple. The song has drums, and it has bass. But with time, I started to appreciate simplicity. In music and in life aswell. Now, being so deep in the DnB rabbit hole that I am, Shadow is probably one of my most favorite DnB tracks. The drums are brutal. The bass is disgusting. Everything around it gives it an atmospheric feeling. The descending synths in the background are very eerie. But the best part is the second drop, where the bass doesn't even try to play a melody anymore and slowly descends, while the percussion just hammers it into you. It's amazing. It really is.</p>

<p>I do like me some complicated music, <a href="https://www.youtube.com/playlist?list=OLAK5uy_kbZGSBbrHtrgH3-K3YbKQNSGc73S4CPt0" target="_blank" rel="noopener noreferrer">Math Rock</a> for example. But for the love of god, I couldn't make or play it. My musical talent peaked in school. I produced a bit of synth stuff, but now I am just programming and my musical ability begins to fade. No matter though, other people can play funky chords for me. 7 Minutes Dead is difficult to describe. His style is so unlike everything else. Different to Monstercat, and different to everything outside of it. I can't compare it to anything I know, I just can't. <a href="https://youtu.be/PhGtxxxorPk" target="_blank" rel="noopener noreferrer">Peacock</a> doesn't seem to have structure? It has a beat, but it constantly switches, stops playing and starts again. No parts repeat, and melodies weave in and out. Half way in and I think: <i>"Wait, this sounds completely different from how this song started!"</i> But it works. It works so well.</p>

<p><a href="https://youtu.be/oO10eNicsfQ" target="_blank" rel="noopener noreferrer">Lets Be Friends - FTW</a> doesn't get a novel like above. It is simply bonkers. Very hype. Very loud. I directly blame this song for <a href="https://youtu.be/GpiHKnH2uGk" target="_blank" rel="noopener noreferrer">the shit I like today</a> and my love for <a href="https://youtu.be/QxygIDS9Khk" target="_blank" rel="noopener noreferrer">autistic furry music</a>.</p>

<h2>017 Ascension</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/017_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Abyss Album Mix: <a href="https://youtu.be/pRcsbaiGSCU" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Zenith Album Mix: <a href="https://youtu.be/tyduw-LJbBc" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/SCD2tB1qILc" target="_blank" rel="noopener noreferrer">Tristam & Braken - Frame of Mind</a></li>
<li><a href="https://youtu.be/TKfKWzCBTm4" target="_blank" rel="noopener noreferrer">Haywyre - The Schism</a></li>
<li><a href="https://youtu.be/h-T__qXRXXk" target="_blank" rel="noopener noreferrer">Droptek - The Covenant</a></li>
<li><a href="https://youtu.be/BrCKvKXvN2c" target="_blank" rel="noopener noreferrer">Aero Chord - Surface</a></li>
<li><a href="https://youtu.be/5lLclBfKj48" target="_blank" rel="noopener noreferrer">Pegboard Nerds - Hero (feat. Elizaveta)</a></li>
</ul>

<p>Ascension is quite a funny name, considering the cat in the album art is literally underground. But I digress. I have some unreasonable hate for this album. I remember vividly when 017 came out, people really liked it. But it just didn't grok with me. It has some insanely popular tracks, with millions of views each, but I somehow just can't enjoy this album. As such, 017 marks a turning point in my tier list. Every album that I rate below below 017 is an album that I don't quite enjoy. And if I want to listen to Monstercat, I'd much rather pick anything above 017.</p>

<p>Nevertheless, one song I want to single out is exactly <a href="https://youtu.be/5lLclBfKj48" target="_blank" rel="noopener noreferrer">Pegboard Nerds - Hero (feat. Elizaveta)</a>. This one will always be stuck in my head, because of Corridor Digitals video <a href="https://youtu.be/H0Ib9SwC7EI" target="_blank" rel="noopener noreferrer">Superman With a GoPro</a>, which in my opinion is one of the best videos on YouTube of all time. It's a rather simple video, especially nowadays, as drones have become quite ubiquitous. But they weren't that common back in the day, especially for amateur YouTubers. Either way, the effect works and the video is such a joy to watch.</p>

<p>Other than that, <a href="https://youtu.be/SCD2tB1qILc" target="_blank" rel="noopener noreferrer">Tristam & Braken - Frame of Mind</a> is an absolutely amazing song. It's up there, with the best of the best songs on Monstercat.</p>

<h2>018 Frontier</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/018_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Horizon Album Mix: <a href="https://youtu.be/of7vnz3YS-k" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Pinnacle Album Mix: <a href="https://youtu.be/BFjgsvM2gZ0" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/cZYkSc5JG7o" target="_blank" rel="noopener noreferrer">Grabbitz - Here With You Now</a></li>
<li><a href="https://youtu.be/F_QrKYAv1NE" target="_blank" rel="noopener noreferrer">Mr FijiWiji, Laura Brehm & AgNO3 - Pure Sunlight</a></li>
<li><a href="https://youtu.be/7XoxIDw5xEo" target="_blank" rel="noopener noreferrer">Stonebank - Moving On (feat. EMEL)</a></li>
<li><a href="https://youtu.be/ddFAIkUb7A0" target="_blank" rel="noopener noreferrer">Varien - Valkyrie (feat. Laura Brehm)</a></li>
<li><a href="https://youtu.be/BQQupaQbiVY" target="_blank" rel="noopener noreferrer">Stephen Walking - Shark City</a></li>
</ul>

<p>It surprised me. And I really did not expect this. But, 018 is breathtakingly amazing. I remember that I never had any problems with this album. I didn't expect much, and I kinda forgot about it. But I was genuinely surprised by how well everything fits. Relistening to it blew me away so much, I am honestly ranking this one higher than 016.</p>

<p>Here's the thing: Whenever I tell people about what music I listen to, I always stress how important albums are. Not playlists that you create yourself, but albums that are created by the artist. Single songs are highlights at best, but the whole picture is much more enjoyable when it tells a story. A good album has ups and downs, with highs and lows. The lower the lows, the higher the highs. For example, one of my most favorite albums is <a href="https://youtube.com/playlist?list=OLAK5uy_mmur-sfAHplBP_YT42RwHq0bah6Yr28fM" target="_blank" rel="noopener noreferrer">Cardiacs - Sing to God</a>. This album easily sits in my top 3. It goes so hard, loud and crazy so many times. But it can only go this hard, because it also goes equally silent. You can only be loud in relation to something else, because the listener controls the volume knob.<br>On the radio, every song competes with every other. As such, the loudness wars are under way with every song trying to be better than the other. The result is that everything is equally loud. The listener turns the volume knob down, and now all the songs are silent. Bummer. But in a well-constructed album, you can deliberately hit pauses, and with them you can reach amazing highs, that you could never do with the stupid radio.</p>

<p>Where was I going with this? Ah yes, 018 tells a story. The transitions are amazing, the songs flow so well into each other, from house, to future bass and back to hard hitting hardstyle. 010 may have good songs, but it absolutely fell flat with the story. 018 may not have that many good tracks, but it makes up for it by having absolutely stellar composition. The highs hit hard, because the Future Bass tracks in between provide a calm and necessary rest.</p>

<p>One of the highlights I want to single out is <a href="https://youtu.be/cZYkSc5JG7o" target="_blank" rel="noopener noreferrer">Grabbitz - Here With You Now</a>. Upon on release, I hated the drop of this song. But <a href="https://youtu.be/oGN4juGQ-0A" target="_blank" rel="noopener noreferrer">repetition legitimizes</a>, and I started to like the song the more I listen to it. Grabbitz in general makes very cool tracks, that have amazing verses and buildups, and then just go fucking apeshit with the drop. It's almost comical how annoying his drops are, but I started to appreciate it.</p>

<h2>019 Endeavour</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/019_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Aspire Album Mix: <a href="https://youtu.be/OMyjVVE8KYE" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Venture Album Mix: <a href="https://youtu.be/y_o2Evoroa4" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/DECxluN8OZM" target="_blank" rel="noopener noreferrer">Au5 - Snowblind (feat. Tasha Baster)</a></li>
<li><a href="https://youtu.be/ebw-_peGnZ4" target="_blank" rel="noopener noreferrer">Draper - Coloured Glass</a></li>
<li><a href="https://youtu.be/cqzRFsqWYDs" target="_blank" rel="noopener noreferrer">Astronaut & Far Too Loud - War</a></li>
<li><a href="https://youtu.be/mN0TvP2ZgIg" target="_blank" rel="noopener noreferrer">Case & Point - Error Code</a></li>
<li><a href="https://youtu.be/NLukRvKWBeA" target="_blank" rel="noopener noreferrer">Rootkit - Against the Sun (feat. Anna Yvette)</a></li>
</ul>

<p>Mixed feelings on this album. It has some very questionable songs, that are not fun to listen to. They are just so distracting to everything else. But what made me give 019 A-Tier anyway, is because of Didrick. Jesus fucking Christ my dude, his <a href="https://youtu.be/Rch4cbV0yK8" target="_blank" rel="noopener noreferrer">Monstercat Live Performance</a> is pure nostalgia, concentrated up to a lethal level. I wasn't really enjoying 019 as a whole, but then this compilation plays as the last track, and it hits me like a fucking truck. I was so high in my nostalgia trip, and this song just amplified it further. I had to stop everything I was doing and I just listened to the damn song. I had this stupid shit eating grin across my face. I recognized all the catchphrases, the samples, all the melodies, and after it was over I was exhausted. I have never taken drugs before, but that's how I imagine it to be. God damn.</p>

<p>So yeah, the album is mid. Not so good. But this single song elevated it to a higher tier.</p>

<h2>020 Altitude</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/020_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Elevation Album Mix: <a href="https://youtu.be/6ZgmN4Oq8Dc" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Stratosphere Album Mix: <a href="https://youtu.be/9o6dWX8oJjA" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/FYyCbKZIkgc" target="_blank" rel="noopener noreferrer">Vicetone - What I've Waited For (feat. D. Brown)</a></li>
<li><a href="https://youtu.be/KqNiUmnZaAU" target="_blank" rel="noopener noreferrer">Stephen Walking - Top Of The World 2</a></li>
<li><a href="https://youtu.be/RJOkI8k_VU0" target="_blank" rel="noopener noreferrer">LVTHER - One Look (feat. Mammals)</a></li>
<li><a href="https://youtu.be/KtMNcZwLGwM" target="_blank" rel="noopener noreferrer">Puppet - Scribble (Extended Mix) (feat. the Eden Project)</a></li>
<li><a href="https://youtu.be/btoT-btf9Dc" target="_blank" rel="noopener noreferrer">Rich Edwards - Sweetest Addiction (feat. We Ghosts)</a></li>
</ul>

<p>Ah, the beginning of an end. After this album my interest in Monstercat dropped. I continued to listen to songs after that, but my consumption gradually declined. I followed a few select artists, like Puppet or <a href="https://youtu.be/dlgqTJb406Y" target="_blank" rel="noopener noreferrer">Karma Fields</a>, but my interest faded eventually. I discovered <a href="https://youtu.be/1RaKSRU60bw" target="_blank" rel="noopener noreferrer">Caravan Palace</a> and <a href="https://youtu.be/FxnO8SXQmpo" target="_blank" rel="noopener noreferrer">Modest Mouse</a>, my taste went on a wild journey and I haven't listened to EDM for quite a while after that. Anyway, 020 is full of many amazing house tracks, similar to 011. I wouldn't call 020 peak, but with as solid as it is, I must put it very close to 011. Afterall, 011 was also full of house tracks, so the styles kinda match.</p>

<p>I have to highlight <a href="https://youtu.be/FYyCbKZIkgc" target="_blank" rel="noopener noreferrer">Vicetone - What I've Waited For (feat. D. Brown)</a>, which also is the best of the best. Absolutely amazing song. While I haven't returned to 020 that often, I routinely come back to this one exact song.</p>

<p>Also, did I seriously put <a href="https://youtu.be/KqNiUmnZaAU" target="_blank" rel="noopener noreferrer">Top Of The World</a> into the Highlights again? Hell yeah I did!</p>

<h2>021 Perspective</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/021_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Aspect Album Mix: <a href="https://youtu.be/-0JUcnzwz5U" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Vantage Album Mix: <a href="https://youtu.be/QEbPypyT2dI" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/j8F1NwrHBIU" target="_blank" rel="noopener noreferrer">Draper - Pressure (feat. Laura Brehm)</a></li>
<li><a href="https://youtu.be/UGeNoml0OHc" target="_blank" rel="noopener noreferrer">Haywyre - Insight</a></li>
<li><a href="https://youtu.be/8dZDdW7v4Q8" target="_blank" rel="noopener noreferrer">Excision & Pegboard Nerds - Bring The Madness (feat. Mayor Apeshit)</a></li>
<li><a href="https://youtu.be/I1NuCWfYeYc" target="_blank" rel="noopener noreferrer">Stonebank - Stronger (feat. EMEL)</a></li>
<li><a href="https://youtu.be/gtmqFmXPysI" target="_blank" rel="noopener noreferrer">Ramases B - Mountains (feat. Veela)</a></li>
</ul>

<p>The last album I know most songs from, and the last mix I listened to during my Monstercat phase. Back then, it was the first one that did not manage to convince me to buy it. Tracks are mostly forgettable. No nostalgia. Nothing. I don't have much more to say about it. 021 is not ass, but it isn't good either. Vantage is definitely the better half of this album, the other sucks in comparison. But I want to single out two songs: <a href="https://youtu.be/j8F1NwrHBIU" target="_blank" rel="noopener noreferrer">Draper - Pressure (feat. Laura Brehm)</a> is one of Monstercats all time greats. After all this time, I still knew all the lyrics by heart, which is amazing. But speeding up the end of it in the mix really annoyed me. And <a href="https://youtu.be/UGeNoml0OHc" target="_blank" rel="noopener noreferrer">Haywyre - Insight</a> is the goat. It's Haywyres best song, and since it's actually performed, it's such a joy to watch him go apeshit on his keyboard.</p>

<h2>022 Contact</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/022_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Connection Album Mix: <a href="https://youtu.be/1YVKR_ai5ZE" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Essence Album Mix: <a href="https://youtu.be/hwi0zyHHwP8" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/ig44rDYo8IM" target="_blank" rel="noopener noreferrer">Bustre - Combine</a></li>
<li><a href="https://youtu.be/4T28WgVqdrA" target="_blank" rel="noopener noreferrer">Grabbitz - Way Too Deep</a></li>
<li><a href="https://youtu.be/mj2XuEdGCgA" target="_blank" rel="noopener noreferrer">Puppet & The Eden Project - The Fire</a></li>
<li><a href="https://youtu.be/81leOXZ0hYE" target="_blank" rel="noopener noreferrer">Rich Edwards - We Are (feat. Danya Nadeau)</a></li>
<li><a href="https://youtu.be/1eXGv_wa7DE" target="_blank" rel="noopener noreferrer">Trivecta - Evaporate (feat. Aloma Steele)</a></li>
</ul>

<p>The first album I only know half the songs on. I never listened to the 022 mix in my Monstercat phase. Somewhat forgettable. The tracks don't stick in my head. With as far as Monstercat has come with its quality in sound production, I can't put 022 anything below B-Tier. Puppet is an artist that I've kept following for a bit. With <a href="https://youtu.be/KtMNcZwLGwM" target="_blank" rel="noopener noreferrer">Scribble</a> on 020 and <a href="https://youtu.be/mj2XuEdGCgA" target="_blank" rel="noopener noreferrer">The Fire</a> on 022 he collaborated with and thus introduced me to <a href="https://www.youtube.com/playlist?list=PLUIv-2K7wcpQZS-D5_NAhdGrqqWB4xQP1" target="_blank" rel="noopener noreferrer">EDEN</a>. EDEN makes sad music, filled with angst. That shit was emo enough already, and fortunately I didn't go deeper than that in this style of music. Other than that, I have literally nothing else to say on 022.</p>

<h2>023 Voyage</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/023_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Passage Album Mix: <a href="https://youtu.be/E25Hcc-7lkM" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Excursion Album Mix: <a href="https://youtu.be/E_qt-M7oaAE" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/BUV2sRIcnqw" target="_blank" rel="noopener noreferrer">Muzzy - Feeling Stronger (feat. Charlotte Colley) (High Maintenance Remix)</a></li>
<li><a href="https://youtu.be/oKbChvqADd0" target="_blank" rel="noopener noreferrer">Aero Chord - 4U</a></li>
<li><a href="https://youtu.be/VGh5DV0D3wk" target="_blank" rel="noopener noreferrer">Nitro Fun - Final Boss</a></li>
<li><a href="https://youtu.be/zMHvZXirECc" target="_blank" rel="noopener noreferrer">Laszlo - Law Of The Jungle</a> &#9888; VOLUME WARNING &#9888;</li>
<li><a href="https://youtu.be/SDiJiGuUeBo" target="_blank" rel="noopener noreferrer">Pegboard Nerds - Swamp Thing</a></li>
</ul>

<p>For some reason, the YouTube video for Laszlo - Law Of The Jungle is much louder than everything else. It's a cool song, but be careful.</p>

<p>Label me surprised. To my amazement, I recognize quite a few songs on 023. I was certain after 021 most would be new to me. But to my utter shock, quite a significant amount of songs I was already familiar with. And to top it off, it's quite a solid album. I wanted to write everything after 021 off as trash, not worth listening to. But 023 proved to me otherwise. The Passage mix starts very strong, but then at the half time mark it just bombs. I simply hate <a href="https://youtu.be/gbcwXRNOx-E" target="_blank" rel="noopener noreferrer">Rootkit - Concrete Jungle</a>. I mean, wtf is this song?</p>

<h2>024 Vanguard</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/024_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Forefront Album Mix: <a href="https://youtu.be/GmaHp-kB8WE" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Presage Album Mix: <a href="https://youtu.be/PgZPwsNHRIk" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/SItIaWAjI_4" target="_blank" rel="noopener noreferrer">Feint - We Won't Be Alone (feat. Laura Brehm)</a></li>
<li><a href="https://youtu.be/F7Uz_XD3Lhk" target="_blank" rel="noopener noreferrer">Priority One & Two Thirds - Hunted (feat. Jonny Rose)</a></li>
<li><a href="https://youtu.be/LgXH44UE5Ho" target="_blank" rel="noopener noreferrer">Stephen Walking - OneMan Moon Band</a></li>
</ul>

<p>Dogshit album. There I said it. With 023 I had very high hopes to enjoy later parts of Monstercat. Unfortunately, I was greatly disappointed. I boasted about my broad music taste. But there is a specific kind of music, that I vocally hate: Pop music. I hate what it is, how it is made, the people and companies behind it, it's role in society, everything.</p>

<p>As someone who knows how the sausage is made, nothing infuriates me more than people pretending to sound good or talented, when in fact they are not. It's all a large game of pretend. I know one or two people, who sometimes share music with me, and it's always some stupid music video of some person playing the guitar in the video and "their amazing voice", but then the song is the most overproduced bullshit imaginable. Do you know how many effects are put on vocals? More than you can guess. And for what? To sound "natural"? Dude, the moment you put an EQ on a vocal it isn't natural anymore!</p>

<p>I don't hate the effects. Take <a href="https://youtu.be/ebw-_peGnZ4" target="_blank" rel="noopener noreferrer">Draper - Coloured Glass</a>. The pitch correction on that gives it that tactile sound which is quite interesting. Or dial it up to 11 and do what <a href="https://youtu.be/1Bw2dTY3SsQ" target="_blank" rel="noopener noreferrer">100 gecs</a> is doing. Layer it, put a chorus on top and you'll end up with something like <a href="https://youtu.be/8GznlD5jTqY" target="_blank" rel="noopener noreferrer">Fox Stevenson</a>. Everything super artificial, but everything very amazing. No I don't hate the effects. I hate that pop pretends that this is what a natural "talented" singer sounds like. My hate on pop is so significant, that if it remotely sounds "too good", it creates this visceral disrespect deep in my soul. I'd much prefer creative usages of effects, or <a href="https://youtu.be/0J2QdDbelmY" target="_blank" rel="noopener noreferrer">little to no effects at all</a>.</p>

<p>But this is what 024 is. It sounds too much like pop. And as such I hate it. And the stuff that does not sound like pop is just bland. 024 has one or two good songs, especially <a href="https://youtu.be/SItIaWAjI_4" target="_blank" rel="noopener noreferrer">Feint - We Won't Be Alone</a>, which is one of Monstercats all time greats. But everything that is not in my highlights is trash. If 001 - 004 wouldn't be so amateurish and low in sound quality, 024 would be bottom tier.</p>

<h2>025 Threshold</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/025_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Collision Album Mix: <a href="https://youtu.be/ONdnfgHs_4s" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Encounter Album Mix: <a href="https://youtu.be/eFQRoVE-tWU" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/eAro3t2ABCA" target="_blank" rel="noopener noreferrer">Grabbitz - Better With Time</a></li>
<li><a href="https://youtu.be/AJh1o0wvqKI" target="_blank" rel="noopener noreferrer">Pierce Fulton & Puppet - Boy and the Beast</a></li>
<li><a href="https://youtu.be/YaHw1lYbE7I" target="_blank" rel="noopener noreferrer">Savoy - Love Is Killing Me (feat. Chali 2na)</a></li>
<li><a href="https://youtu.be/4DgyAO1cB8Q" target="_blank" rel="noopener noreferrer">Varien & Mr FijiWiji - We Are The Lights</a></li>
<li><a href="https://youtu.be/78JXdi7IGNo" target="_blank" rel="noopener noreferrer">F.O.O.L - Need You</a></li>
</ul>

<p>I like this album. Very much actually. 024 really gave me the scare, and so did the album cover of 025. The album covers were always somewhat meaningless, but with 025 - 030, Monstercat introduced this evil cat and something of a little story. This scared me, because before listening to 025 - 030, I thought the evil cat represented Brostep. Fortunately, this is not the case, ahem 028 ahem, and I really liked what 025 ended up being. Grabbitz again is absolutely phenomenal with <a href="https://youtu.be/eAro3t2ABCA" target="_blank" rel="noopener noreferrer">Better With Time</a>. If I wasn't already, now I really started to love Grabbitz and his music. Also I want to mention <a href="https://youtu.be/dlgqTJb406Y" target="_blank" rel="noopener noreferrer">Karma Fields</a>, which I was very familiar with already, and hold to high regard. His and MORTENs song <a href="https://youtu.be/ysNolli7iGg" target="_blank" rel="noopener noreferrer">Stickup (feat. Juliette Lewis)</a> doesn't hit me as odd. It's that experimental unique style that he puts on the table.</p>

<p>All in all, 025 is a very great album, and I am really giving it S-tier. I fully expected to write off all albums after 021 as trash, especially after the 024 scare, but I am delightfully surprised.</p>

<h2>026 Resistance</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/026_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Defiance Album Mix: <a href="https://youtu.be/4vqyzUCeLgw" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Submission Album Mix: <a href="https://youtu.be/khy1MXllimg" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/E66v5GOPgkU" target="_blank" rel="noopener noreferrer">Karma Fields - Edge of the World</a></li>
<li><a href="https://youtu.be/PJZRvE4xHPM" target="_blank" rel="noopener noreferrer">Karma Fields - Greatness (feat. Talib Kweli)</a></li>
<li><a href="https://youtu.be/EF0b22w-tIM" target="_blank" rel="noopener noreferrer">Puppet - Vagabond</a></li>
<li><a href="https://youtu.be/YQbjisWixoU" target="_blank" rel="noopener noreferrer">San Holo - They Just Haven't Seen It (feat. The Nicholas)</a></li>
<li><a href="https://youtu.be/MSvVuGT1XrQ" target="_blank" rel="noopener noreferrer">PYLOT - A Race Against Time</a></li>
</ul>

<p>Too much like pop, simmelar to 024. 026 is the better album of the two, but not by much. It's annoying, bland and simply forgettable. I don't recommend it. Since I chewed 024 out already, there is not much more to say about 026.</p>

<p>Karma Fields is amazing and definitely the best thing about this album. The others just don't hit as hard. I also want to touch on San Holo for a moment. His music is also very different from anything that came before, and his song <a href="https://youtu.be/iw48xKL5N6o" target="_blank" rel="noopener noreferrer">Victory</a> is simply amazing. Victory is on 022, but didn't make the cut in the highlights, because the other artists were simply better. Quite a shame. In 026 San Holo easily made the list, because 026 provided absolutely no competition.</p>

<h2>027 Cataclysm</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/027_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Trials Album Mix: <a href="https://youtu.be/1bHojkVYqPg" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Tribulations Album Mix: <a href="https://youtu.be/hytQsJg7H04" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/mpQeKHrZGWU" target="_blank" rel="noopener noreferrer">Melano - Traveller</a></li>
<li><a href="https://youtu.be/YnwsMEabmSo" target="_blank" rel="noopener noreferrer">Marshmello - Alone</a></li>
<li><a href="https://youtu.be/yappQQtfk8Q" target="_blank" rel="noopener noreferrer">Ramases B - Neon Rainbow</a></li>
<li><a href="https://youtu.be/gqbEDgGvnwM" target="_blank" rel="noopener noreferrer">Trivecta - Into the Limelight</a></li>
<li><a href="https://youtu.be/8c0M7p49Acs" target="_blank" rel="noopener noreferrer">Notaker - Infinite</a></li>
</ul>

<p>Oha. This is the album with Marshmello on it. Honestly, I don't know much about the guy, <a href="https://youtu.be/YnwsMEabmSo" target="_blank" rel="noopener noreferrer">Alone</a> is literally the only song I know from him. Probably because it was on Monstercat lol. And despite my vitriol against pop, I don't dismiss this song. Honestly, I am even giving it a pass, and somehow, it fits very well inside the entire album. Even though it's somewhat cringe, It's decent as a standalone song.</p>

<p>So while Marshmello stole the show, 027 in it's entirety is nothing that I hate. As such, it gets solid B-Tier. Not above 017 though, as even though there is nothing bad on it, there is not much good on it either. And my 0 nostalgia towards 027 is really dragging it down.</p>

<h2>028 Uproar</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/028_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Tyranny Album Mix: <a href="https://youtu.be/TI8K5rYVYVw" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Supremacy Album Mix: <a href="https://youtu.be/KAWLbDvedYQ" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlight</h3>

<ul>
<li><a href="https://youtu.be/6-hRrKFkAQE" target="_blank" rel="noopener noreferrer">WRLD - By Design</a></li>
</ul>

<p>The bottom of the barrel. We have reached it. I absolutely despise this album. Even more than the atrocious 010 continuous mix. Where to even begin?</p>

<p>I vividly remember EDM going into a very crazy direction, aka Brostep. But as I said already, <a href="https://youtu.be/-hLlVVKRwk0" target="_blank" rel="noopener noreferrer">all my homies hate Skrillex</a>. So, first things first, 028 doesn't start well with the absolute worst drop I have ever heard in my entire life. It isn't fun, rhythmically interesting, or enjoyable in any way. It's just some batshit crazy drop and that's it. The album has more songs like this, and the other half is more pop shit. One questionable song after the other, and it just doesn't stop. Out of all the albums on this blog post, this one I <b>really</b> don't want to listen to.</p>

<p>And the ironic part is, that 028 doesn't want to live me alone. It's in my recommendations to this day. It pops up every day. It probably does this, because I am still flirting with the idea to just listen to it 100 times, so that the <a href="https://youtu.be/oGN4juGQ-0A" target="_blank" rel="noopener noreferrer">repetition-legitimization</a> kicks in. And it does have probably the coolest cover out of all the Monstercat albums, even to this day, with their newer stuff. It's glorious and evil. The red tint really makes it look menacingly.</p>

<p>I noted in 025 how I was scared about the evil cat subplot, because I thought it represented this awful kind of Brostep. 028 is probably the main reason for that fear. The first song just doesn't go down well. I did check on Monstercat a few times, even after 021. But 028 was the last thing before my nostalgia trip. I really thought this is the end of Monstercat, and Brostep took over.</p>

<h2>029 Havoc</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/029_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Fury Album Mix: <a href="https://youtu.be/jtJh1A7s6X8" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Retribution Album Mix: <a href="https://youtu.be/6Vqku6ZZOFA" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/k1JmWQMvEsQ" target="_blank" rel="noopener noreferrer">DROELOE - Bon Voyage</a></li>
<li><a href="https://youtu.be/OT9tqddn9PY" target="_blank" rel="noopener noreferrer">Koven - Silence</a></li>
<li><a href="https://youtu.be/wB2k5urAOS4" target="_blank" rel="noopener noreferrer">Aero Chord x Fractal - Until The End (feat. Q'AILA)</a></li>
<li><a href="https://youtu.be/P56X91KrH_s" target="_blank" rel="noopener noreferrer">Varien - TEVA833</a></li>
<li><a href="https://youtu.be/kwRGhAjwp7o" target="_blank" rel="noopener noreferrer">Stonebank - The Only One (feat. Ben Clark)</a></li>
</ul>

<p>Okay, things took a rather sad turn with 028. But there is light at the end of the tunnel: With my interest into Monstercat completely dead after 028, I was able to hear 029 and 030 completely blind. Literally the only song I knew was <a href="https://youtu.be/F3CG8CM22BQ" target="_blank" rel="noopener noreferrer">Karma Fields - Sweat</a>, because as should be clear by now, I really like the music from this dude. But if you've never heard Sweat before, it really does not help the image of Monstercat going into a weird and bad direction.</p>

<p>However, to my utter surprise, 029 is actually very cool. Instead continuing with Brostep, it pivoted hard into Growlstep. <a href="https://youtu.be/ysK77V2_qW0" target="_blank" rel="noopener noreferrer">And Growlstep is fucking amazing</a>. Instead of just doing stupid ridiculous drops, it's relishing in the filthy and disgusting basslines and reshapes them into nice harmonics and very catchy rhythms. So while 029 is probably the weirdest Monstercat album between 001 and 030 (maybe even all time, honestly I have no fucking clue about anything after 030), it's definitely one of the better albums. Similar to 013, I now routinely come back to it and I think I've found a new favorite.</p>

<p>But as much as I like 029, it has proven itself to be strange enough. When shared with friends, they demand me to stop and request something else. Funny how that turned out.</p>

<p>Solid A-Tier. Very good album.</p>

<h2>030 Finale</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/030_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Overture Album Mix: <a href="https://youtu.be/jh18hFFvzjo" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Epilogue Album Mix: <a href="https://youtu.be/pXiN6-Fh3-I" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/1UTYlATnHhI" target="_blank" rel="noopener noreferrer">Gareth Emery & Standerwick - Saving Light (feat. HALIENE)</a></li>
<li><a href="https://youtu.be/E-0fzEPA7nU" target="_blank" rel="noopener noreferrer">Darren Styles & Gammer - Feel Like This</a></li>
<li><a href="https://youtu.be/8j5bRbdUMf0" target="_blank" rel="noopener noreferrer">Ramases B - Virtuality</a></li>
<li><a href="https://youtu.be/vw4DzslUw7Y" target="_blank" rel="noopener noreferrer">Unlike Pluto - Someone New (feat. Desi Valentine)</a></li>
<li><a href="https://youtu.be/UT6d6RC2gS8" target="_blank" rel="noopener noreferrer">PYLOT - Shadowtask</a></li>
</ul>

<p>And thus we have reached the end. And it isn't a bad ending at all. 030 is quite a stellar album! In retrospect, the evil cat subplot does make sense. Monstercat has gotten somewhat weird and poppy between 025 and 029. But 030 completely escapes that. This album really feels like old Monstercat, but with modern high-quality mixing. So even though I knew literally no songs on it, it did feel somewhat nostalgic.</p>

<p>I want to mention the squeaking chair in <a href="https://youtu.be/LIdeAkFdCII" target="_blank" rel="noopener noreferrer">Hush - Pilvorm</a>, which I find absolutely hilarious. I don't know, something about originally irritating, but looping sounds, which blend into the music, are just very fun. <a href="https://youtu.be/oGN4juGQ-0A" target="_blank" rel="noopener noreferrer">Repetition legitimizes</a> after all. Reminds me a lot of <a href="https://youtu.be/ssmYUDYtrKA" target="_blank" rel="noopener noreferrer">Cowboy Bebop OST 1 - Piano Black</a>.</p>

<p>The absolute highlight here is the last song, <a href="https://youtu.be/1UTYlATnHhI" target="_blank" rel="noopener noreferrer">Gareth Emery & Standerwick - Saving Light (feat. HALIENE)</a>. It's so triumphant and confident, tying the story together and showcasing the last victory over the evil cat. But it also marks a change, as this song definitely sounds more mainstream than anything else on the label. Also it's absolutely bathed in reverb. What is this? <a href="https://youtu.be/KJoLGNu5BFY" target="_blank" rel="noopener noreferrer">SLIFT</a>?</p>

<h2 style="text-align: center;">Bonus &lt;3</h2>

<h2>Uncaged Vol. 1</h2>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/vol_1_small.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h3>Album Mix: <a href="https://youtu.be/ujOArEV3yuA" target="_blank" rel="noopener noreferrer">LINK</a></h3>

<h3>Highlights</h3>

<ul>
<li><a href="https://youtu.be/OFqeoXFSlms" target="_blank" rel="noopener noreferrer">Unlike Pluto - Everything Black (feat. Mike Taylor)</a></li>
<li><a href="https://youtu.be/ikIXmUUumjg" target="_blank" rel="noopener noreferrer">Darren Styles - Us Against the World</a></li>
<li><a href="https://youtu.be/y5SmBKDT98c" target="_blank" rel="noopener noreferrer">Stonebank - Ripped To Pieces (feat. EMEL)</a></li>
<li><a href="https://youtu.be/lj0HRdX5cg4" target="_blank" rel="noopener noreferrer">Duumu - Illuminate (feat. Styleaf)</a></li>
</ul>

<p>After 030, Monstercat rebranded. This was probably for the better. As 025 - 030 demonstrated, Monstercat wanted to bring in many new people and styles, and multiple channels allowed them to specialize. Monstercat also got rid of the 2 mixes and combined them into one. I was always listening to both mixes anyway. Highlights were pretty difficult to find for this album, because Monstercat has perfected their mixing to such a level, that it's very difficult to tell songs apart. Where does one song end and where does another start? As someone who doesn't know any of the songs, the whole mix really does feel like some continuum, and I condone that.</p>

<p>However, even though I did give some albums after Uncaged Vol. 1 a fair shot, I decided that Monstercat simply isn't for me anymore. I have my nostalgia, and will go back to 007, 018, 016 and 025 many times, but everything after Uncaged Vol. 1 doesn't interest me in the slightest, regardless how good the music may be.</p>

<p>Before I leave, I want to mention <a href="https://youtu.be/OFqeoXFSlms" target="_blank" rel="noopener noreferrer">Unlike Pluto - Everything Black (feat. Mike Taylor)</a>. When Mike sings "black diamonds" in the buildup before the drop, I mishear "black garbage". I can't be the only one, no? Doesn't change that the song is an absolute banger though. But I find it it still hilarious.</p>

<h2>Conclusion</h2>

<p>And with this, my thoughts are concluded. Below is a tier list, combining every of my thoughts into an easy to reference image. Tracks to the left in the same tier are considered to be higher. I.e. 007 is better than 018.</p>

<img src="https://www.rismosch.com/articles/my-thoughts-on-monstercat-001-030/tierlist.webp" style="display: block; margin: auto; max-width: 100%;" />
]]></content:encoded></item><item><title>Why I make my own Game Engine</title><link>https://www.rismosch.com/article?id=why-i-make-my-own-game-engine</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Other]]</category><guid isPermaLink="false">why-i-make-my-own-game-engine</guid><pubDate>Thu, 30 May 2024 12:02:35 +0200</pubDate><description>Reflecting on the GameDev community as a whole, and comming to terms on the size of the project.</description><content:encoded><![CDATA[<blockquote style="background-color:var(--pico-8-white); border: 5px solid var(--pico-8-cyan); padding: 20px;">
    <p>The real treasure was the friends we made along the way.</p>
    <cite>Every cheesy ass children's TV show</cite>
</blockquote>

<p>Since I can remember, I was fascinated by video games and how they work. I want to make my own. A few years back, it was only natural for me to get sucked into the game dev rabbit hole. I did what the internet told me. I participated in game jams, engaged in subreddits, watched other people talk about game design on YouTube. But over time, my views drastically changed. So much so, that I started to write my own game engine, something that no one recommends. But with how my views changed, this is the only path that I want to take.</p>

<p>Many beginners are not aware that making a game is a huge endeavor. How difficult can it be to draw a triangle on the screen? The community is aware of this issue. To counteract, their advice is tailored to keep the expectations low and the workload manageable. This directly leads to many corners being cut.

<p>For example, People recommend to build your game with preexisting, all-purpose game engines. Don't focus on project or code architecture and just get things running. Don't reinvent the wheel, use the first library or asset you can find that does what you want. Fail fast, i.e. don't learn upfront, don't try to understand how things work and only investigate when things fail. Burn yourself out in game jams, to gain experience. And the best of all: Don't work on what you want. Work on smaller things that neither you, nor anyone else cares about.</p>

<p>I presented these a bit mean spirited, but I can't help but feel that this advice is harmful. First, it generates terrible code, that is neither maintainable nor performant. You'll struggle a lot to get things running and you will bite your teeth out when you hit awful bugs. Second, you will learn slower, as per this advice you are not actually trying to understand what you are doing. And third, it does not make you happy, because you will be spending more time on focusing on finishing a project, instead of enjoying the process itself.</p>

<p>Let's play devil's advocate. Assume the worst-case position for my argument, that I've constructed a strawman. Assume I misrepresented what everyone is saying. And assume I did not address the actual advice, which still floats around in the community. In this case I want to ask the question: Why is there so much failure in this community? Every day in different parts of the web, people share their post mortems, about how they are burnt out, how much work all of this is, how it is not fun or that their end product was not as successful as they anticipated. At one point, one should stop and ask themselves: Surely, the failure rate would be much smaller, if this advice actually works, right? However, if there is a reason why people fail, why then is the advice not tailored to this reason?</p>

<p>The answer is, as I've lined out, that the advice is essentially harmful in itself. I don't assume bad faith. People are not evil, and I think what they are trying to say is well meant. But because of how communication on the internet works, well meant advice got distorted. It morphed into unhelpful buzzwords and short, snappy phrases, which misguide the beginner.</p>

<p>For example, take the advice to not work on what you want, but on many small things. Most big successes are from people who already have years of experience. Usually, they worked a long time in the field already, or boast a portfolio of smaller projects. The wrong way to connect the dots is to assume more games equal more success. The reality is however, that people did not gather all this experience to have one single success, but rather because it is their passion. The huge work they put into it is because they can and want to. When they do eventually have a breakaway game, usually it's because of that exact experience, which allowed them to put all their strengths into one unfathomable good product.</p>

<p>Or take for example the advice to not reinvent the wheel. People recommend this, because programming is a wide and deep field. You can pick a single subject and spend your entire life only studying this one thing. So, when you are doing a project, and you need a solution for something you don't fully understand, you can build on top of existing knowledge. You can save a lot of time and energy, by using other people's work. But this advice gets distorted to never try to build things on your own. It leads to people not wanting to do stuff, and them assuming everything is solved nowadays. In the worst case, people really don't understand what they are doing, and they burn out on the fact that there might not be a solution to their problem.</p>

<p>Knowledge is like a drawer. Whenever you learn something, you put something into it. When you forget, you don't really lose anything. Forgetting is more like losing the note on one of its doors, such that it's difficult to tell what's behind it. However, a circumstance or event can trigger you to look into it, allowing you to access the knowledge. It goes without saying, the more knowledge you have, the larger your drawer becomes. Over time, you will burn stuff inside it. Mostly details, for example mathematical formulas or syntax of a programming language. But that's not necessarily a bad thing. You may forget details, but you retain the concepts. Making room for different knowledge allows you to use the space more efficiently. You can always look up details later.</p>

<p>Students often ask, why should we study, when everything can be looked up? The simple and unsatisfying answer is that you don't know what you don't know. It can feel like a real waste of time, when you don't see how a given knowledge can be useful. But putting more stuff into your drawer is always useful, because you look inside it every single day. It affects how you think. Let me ask you this: How exactly are you looking up a mathematical formula, when you are not even aware of its existence? How exactly are you solving a problem, when you can't even pinpoint what the exact problem is? Sure, you can ask people online for help, or one of the hot new text generators. But when your problem is too niche, even they will struggle to help you.</p>

<p>And this is why I take great dismay with "don't reinvent the wheel". I am not reinventing anything. I am learning how things work. I look up what other people have done and then give my own spin on it. I am putting things into my drawer, growing it in the process. When you lose yourself in the mindset to never solve problems and always use preexisting solutions, you will struggle. Period. A related issue is what the community calls "tutorial hell". People who are in tutorial hell follow too many tutorials too closely, never deviating from them. People in this situation really struggle to get the ball rolling on their own, because they miss the concepts to do so.</p>

<p>So, what about me then? I am talking out of my ass and I have yet to say a single thing about my game engine. Well, after 2 years of work my engine is far from being in a presentable state. It looks primitive. And what it can do is easily achieved by a few clicks with every other engine on the market. At this point, I am imagining that this whole project will take an even greater portion of my life. But God damn, it's the single coolest thing I've ever worked on, by a long shot. I take great pride in saying "yeah, I did that", and I can't do that for the things I've done in Unity. I understand and have full control over my code. I actually do own my code, which isn't given in today's copyright hellscape. Literally the only downside to writing your own thing is the huge amount of time and effort required to do so. But I am planning big (maybe too big), so I am going to spent a lot of time and work on this anyway. By writing my own game engine, I am just front loading this work, experiencing it now instead of later.</p>

<p>Of course, I have this one great amazing innovative never seen before best of all time game in my head. I hope it will succeed, like everyone else does for theirs. But it's not my primary incentive anymore. I am having fun. And I amassed so much underlying knowledge and experience, that I feel I can work on anything now. I don't think I could've said that 2 years ago. Ultimately, you'll only learn by going out of your comfort zone. And by doing something as difficult as this, I am practically always outside my comfort zone.</p>

<p>I am not really trying to convince you of writing your own game engine. What I am trying to say is exactly the cheesy quote at the very top of this post: The real fun is the things you learn along the way, not the end product. You should enjoy what you are doing, using the end product as a justification to do so. And in my case, this is writing a game engine. For you, the end product may not be some giant undertaking, but at least it should be something you care about. And you have to learn. Always learn. At least try to understand why your copied solution works the way it does.</p>

<p>If you understand what you are doing, and have fun doing it, then you will have a much better time. You will regret nothing.</p>
]]></content:encoded></item><item><title>I found a Bug in my JobSystem</title><link>https://www.rismosch.com/article?id=i-found-a-bug-in-my-job-system</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">i-found-a-bug-in-my-job-system</guid><pubDate>Sun, 17 Mar 2024 07:40:00 +0100</pubDate><description>I've found a rather sever, but interesting bug in my JobSystem.</description><content:encoded><![CDATA[<p>As a little joke, in my <a href="https://www.rismosch.com/article?id=building-a-job-system" target="_blank" rel="noopener noreferrer">post about how I built my JobSystem</a>, I included a little PHP script that counts the days since it was posted.</p>

<img src="https://www.rismosch.com/articles/i-found-a-bug-in-my-job-system/screenshot.webp" style="display: block; margin: auto; max-width: 100%;">

<p>Unfortunately, I did run into a very severe bug, which is able to deadlock the entire system. Considering I made my JobSystem a big deal, I feel obligated to share you this rather interesting bug &#128522;</p>

<h2>The Bug</h2>

<p>Without going into the nitty gritty, here's a basic rundown of what the JobSystem does and how it works:</p>

<p>The JobSystem allows "Jobs" (function pointers, closures, lambdas, anonymous methods, or whatever your language of choice calls them) to be submitted to a buffer. Worker threads dequeue Jobs and execute them. With one worker per CPU core, this system is able to utilize all cores of your CPU, without the user ever needing to spawn additional threads for concurrency.</p>

<p>The submit function is global, and thus easily accessible. The pseudocode looks something like this:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">submit</span><span style="color:var(--pico-8-cyan)">(</span>job: <span style="color:var(--pico-8-washed-grey)">Job</span><span style="color:var(--pico-8-cyan)">)</span> -> <span style="color:var(--pico-8-washed-grey)">JobFuture</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> future = <span style="color:var(--pico-8-washed-grey)">JobFuture</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">()</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> wrapped_job = <span style="color:var(--pico-8-washed-grey)">Job</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-brown)">()</span> => <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> result = <span style="color:var(--pico-8-brown)">job</span><span style="color:var(--pico-8-cyan)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;future.<span style="color:var(--pico-8-brown)">set</span><span style="color:var(--pico-8-cyan)">(</span>result<span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><span style="color:var(--pico-8-green)">)</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> success = <span style="color:var(--pico-8-brown)">enqueue_job</span><span style="color:var(--pico-8-green)">(</span>wrapped_job<span style="color:var(--pico-8-green)">)</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <span style="color:var(--pico-8-green)">(</span>!success<span style="color:var(--pico-8-green)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">wrapped_job()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">return</span> future;<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
</code>

<p>First, a future is created. A future is a utility, that allows client code to wait and retrieve a Jobs return value, once it's done. The job is wrapped into another job, such that the future can be set. Then the wrapped job is enqueued. If the enqueue failed, the Job is simply invoked. Finally, the future is returned.</p>

<p>Unfortunately, this code is based on a flawed assumption: If a Job failed to be enqueued, then calling it immediately may lead to a deadlock.</p>

<p>Let me elaborate: Enqueuing can fail for 2 reasons: Either because the buffer is full, or because another thread holds a lock inside the buffer. These failures are by design. They enable a lock free behaviour and allow predictable performance. However, this comes with the consequence, that we may have a Job which was not enqueued. And now we need to decide what to do with that Job. When I wrote this code, I naively assumed I can just execute the Job. Afterall, as long as the system is making progress somehow, everything is fine. The client code should not care whether the Job is executed now or later.</p>

<p>But the following code breaks: </p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">let</span> future = <span style="color:var(--pico-8-washed-grey)">JobFuture</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-cyan)">()</span>;<br>
<br>
<span style="color:var(--pico-8-brown)">submit</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-green)">()</span> => <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;future.<span style="color:var(--pico-8-brown)">wait()</span>;<br>
<span style="color:var(--pico-8-green)">}</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
<br>
future.<span style="color:var(--pico-8-brown)">set</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-green)">42</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
</code>

<p>If an enqueue fails, this leads to the Job being executed directly. It's as if the call to submit isn't even there. The thread responsible for setting the future, the thread itself, will never set the future, because it's waiting on the future being set. Deadlock.</p>

<h2>The Fix</h2>

<p>Unfortunately, this has no satisfying solution. My engine is written in Rust, and to say it mildly, I am really struggling to get safe global state working. My latest prototype produces client code like this. It could be argued that the client code is unsound, and it shouldn't be legal in the first place, but because my latest prototype is somewhat promising, compromises have to be taken.</p>

<p>My current fix looks like this:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">submit</span><span style="color:var(--pico-8-cyan)">(</span>job: <span style="color:var(--pico-8-washed-grey)">Job</span><span style="color:var(--pico-8-cyan)">)</span> -> <span style="color:var(--pico-8-washed-grey)">JobFuture</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> future = <span style="color:var(--pico-8-washed-grey)">JobFuture</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">()</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> wrapped_job = <span style="color:var(--pico-8-washed-grey)">Job</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-brown)">()</span> => <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> result = <span style="color:var(--pico-8-brown)">job</span><span style="color:var(--pico-8-cyan)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;future.<span style="color:var(--pico-8-brown)">set</span><span style="color:var(--pico-8-cyan)">(</span>result<span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><span style="color:var(--pico-8-green)">)</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">while</span> <span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-cyan)">true</span><span style="color:var(--pico-8-green)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> success = <span style="color:var(--pico-8-brown)">enqueue_job(</span>wrapped_job<span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <span style="color:var(--pico-8-brown)">(</span>success<span style="color:var(--pico-8-brown)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">break</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">else</span> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">run_pending_job</span><span style="color:var(--pico-8-cyan)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">return</span> future;<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
</code>

<p>It's very similar to the original code. Basically, submit the wrapped job until it succeeds. When the enqueue fails, call <code class="code">run_pending_job()</code>. This function is a utility, allowing client code to run an enqueued Job. This is helpful, because if the current thread cannot make progress, the entire system can still make progress by working on something different. If no enqueued job exists, this function yields, freeing up the core for another thread.</p>

<p>This solution is not ideal, because this can still deadlock. It is still invoking Jobs, which may block the calling thread. There is always the possibility to simply <i>not</i> invoke a pending Job. But that would lead to a busy spinlock, using CPU resources without making progress. Admittedly, it would be safe, but there is the potential for a performance hit. Considering that my flawed clientcode only exists in debug builds of my engine, I am preferring the risk of a potential deadlock over a potential performance hit.</p>

<p>An more sophisticated solution would be to have a dedicated dispatcher. It would assign each Job an ID, telling them on what threads a Job is allowed to run on. But this requires more time and effort. And at the moment this bug is not justification enough for a dispatcher to exist. So I am sticking with the less likely, potential deadlock.</p>

<h2>Conclusion</h2>

<p>I am kind of amazed that it took this long until I found a major bug in my job system. In <a href="https://www.rismosch.com/article?id=building-a-job-system" target="_blank" rel="noopener noreferrer">my previous post about the JobSystem</a>, I emphasized how important it is to stress test something as critical and central as this. It only goes to show, how much good and extensive tests prevent bugs. Since then, I've also integrated <a href="https://github.com/rust-lang/miri" target="_blank" rel="noopener noreferrer">miri</a> in my testing, which gives me even more confidence in the stability of my system.</p>

<p>It also highlights once again how reliable Rust is. When I am working with C#, implementing something similar, I can't tell you how many times my code breaks just a few weeks or days after implementation. But nevertheless, my Rust code did in fact produce a bug. And unfortunately, that means I must take down my little PHP script on my original post &#129394;</p>]]></content:encoded></item><item><title>An even better Error Type</title><link>https://www.rismosch.com/article?id=an-even-better-error-type</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">an-even-better-error-type</guid><pubDate>Sun, 11 Feb 2024 03:13:05 +0100</pubDate><description>Utilizing Rusts Backtrace functionality, it's possible to make even better errors types.</description><content:encoded><![CDATA[<p>My last post caused quite a stir in the Rust subreddit lol. Luckily, it's not a hill I am willing to die on. The post was more about having fun, poking holes on some annoyance I face while programming in Rust every day, than truly throwing hate to something or someone. I mean, who would plaster memes on a subject they are 100% serious about, right?</p>

<img src="https://www.rismosch.com/articles/an-even-better-error-type/wojak.webp" style="display: block; margin: auto; max-width: 100%;">

<p>Nonetheless, I did get some value out of it. A single commenter pointed out that actually, Rust does have a utility to capture the stack trace. Well, it isn't built into <code class="code">Result</code>, and you still need to call the function manually, but it exists. And poof. My biggest argument against <code class="code">Result</code> just evaporated.</p>

<p>Capturing the stack trace allows for some beautiful ergonomics: Calling <code class="code">file!()</code> and <code class="code">line!()</code> isn't as important anymore, as all information is on the stack trace anyway. This means, no macro for conversion between errors is necessary, and now it actually makes sense to implement a generic <code class="code">From</code>, that converts <i>every</i> <code class="code">std::error::Error</code> into a <code class="code">RisError</code>. Sure, it adds one more frame to the stack, but who cares? The entire thing is captured anyway <span style="display: inline-block">&#175;&#92;&#95;&#40;&#12484;&#41;&#95;&#47;&#175;</span></p>

<p>I find it quite silly that so many people recommended to just use some crate. Especially since the entire implementation, plus some utility, fits into a little over 100 lines of code. Again, it was just a single person who realized the actual problem. I am really getting <a href="https://www.npmjs.com/package/is-odd" target="_blank" rel="noopener noreferrer">is-odd</a> vibes from this situation.</p>

<p>Enough condescending talk about redditors. Here's the new, better <code class="code">RisError</code>:</p>

<p><a href="https://github.com/Rismosch/ris_engine/blob/7829aada888eae6a11378605824f1d6cae40dd6e/crates/ris_error/src/error.rs" target="_blank" rel="noopener noreferrer">GitHub permalink</a></p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">use</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">backtrace</span>::<span style="color:var(--pico-8-washed-grey)">Backtrace</span>;<br>
<span style="color:var(--pico-8-cyan)">use</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">error</span>::<span style="color:var(--pico-8-washed-grey)">Error</span>;<br>
<span style="color:var(--pico-8-cyan)">use</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">sync</span>::<span style="color:var(--pico-8-washed-grey)">Arc</span>;<br>
<br>
<span style="color:var(--pico-8-cyan)">pub type</span> <span style="color:var(--pico-8-washed-grey)">SourceError</span> = <span style="color:var(--pico-8-washed-grey)">Option</span>&lt;<span style="color:var(--pico-8-washed-grey)">Arc</span>&lt;<span style="color:var(--pico-8-cyan)">dyn</span> <span style="color:var(--pico-8-washed-grey)">Error</span> + <span style="color:var(--pico-8-cyan)">'static</span>&gt;&gt;;<br>
<span style="color:var(--pico-8-cyan)">pub type</span> <span style="color:var(--pico-8-washed-grey)">RisResult</span>&lt;<span style="color:var(--pico-8-washed-grey)">T</span>&gt; = <span style="color:var(--pico-8-washed-grey)">Result</span>&lt;<span style="color:var(--pico-8-washed-grey)">T</span>, <span style="color:var(--pico-8-washed-grey)">RisError</span>&gt;;<br>
<br>
#<span style="color:var(--pico-8-cyan)">[</span><span style="color:var(--pico-8-brown)">derive</span><span style="color:var(--pico-8-washed-grey)"><span style="color:var(--pico-8-green)">(</span>Clone<span style="color:var(--pico-8-green)">)</span></span><span style="color:var(--pico-8-cyan)">]</span><br>
<span style="color:var(--pico-8-cyan)">pub struct</span> <span style="color:var(--pico-8-washed-grey)">RisError</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub</span> source: <span style="color:var(--pico-8-washed-grey)">SourceError</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub</span> message: <span style="color:var(--pico-8-washed-grey)">Option</span>&lt;<span style="color:var(--pico-8-washed-grey)">String</span>&gt;,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub</span> file: <span style="color:var(--pico-8-washed-grey)">String</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub</span> line: <span style="color:var(--pico-8-washed-grey)">u32</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub</span> backtrace: <span style="color:var(--pico-8-washed-grey)">Arc</span>&lt;<span style="color:var(--pico-8-washed-grey)">Backtrace</span>&gt;,<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Display</span> <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">RisError</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">fmt</span>(&<span style="color:var(--pico-8-cyan)">self</span>, <u>f</u>: &<span style="color:var(--pico-8-cyan)">mut</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Formatter</span>&lt;<span style="color:var(--pico-8-cyan)">'_</span>&gt;<span style="color:var(--pico-8-green)">)</span> -&gt; <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Result</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-brown)">(</span>source<span style="color:var(--pico-8-brown)">)</span> = &<span style="color:var(--pico-8-cyan)">self</span>.source <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">write!(</span><u>f</u>, <span style="color:var(--pico-8-brown)">"<span style="color:var(--pico-8-cyan)">{}</span>"</span>, source<span style="color:var(--pico-8-cyan)">)</span>?;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-brown)">(</span>message<span style="color:var(--pico-8-brown)">)</span> = &<span style="color:var(--pico-8-cyan)">self</span>.message <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">write!(</span><u>f</u>, <span style="color:var(--pico-8-brown)">"</span><span style="color:var(--pico-8-red)">\n</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">message:</span> <span style="color:var(--pico-8-red)">\"</span><span style="color:var(--pico-8-cyan)">{}</span><span style="color:var(--pico-8-red)">\"</span><span style="color:var(--pico-8-brown)">"</span>, message<span style="color:var(--pico-8-cyan)">)</span>?;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">write!</span><span style="color:var(--pico-8-brown)">(</span><u>f</u>, <span style="color:var(--pico-8-brown)">"</span><span style="color:var(--pico-8-red)">\n</span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">at</span> <span style="color:var(--pico-8-cyan)">{}</span>:<span style="color:var(--pico-8-cyan)">{}</span><span style="color:var(--pico-8-brown)">"</span>, <span style="color:var(--pico-8-cyan)">self</span>.file, <span style="color:var(--pico-8-cyan)">self</span>.line<span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Debug</span> <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">RisError</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">fmt</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span>, <u>f</u>: &<span style="color:var(--pico-8-washed-grey)">mut</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Formatter</span>&lt;<span style="color:var(--pico-8-cyan)">'_</span>&gt<span style="color:var(--pico-8-green)">)</span> -&gt; <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Result</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">write!</span><span style="color:var(--pico-8-brown)">(</span><u>f</u>, <span style="color:var(--pico-8-brown)">"</span><span style="color:var(--pico-8-cyan)">{}</span><span style="color:var(--pico-8-red)">\n</span><span style="color:var(--pico-8-brown)">backtrace:</span><span style="color:var(--pico-8-red)">\n</span><span style="color:var(--pico-8-cyan)">{}</span><span style="color:var(--pico-8-brown)">"</span>, <span style="color:var(--pico-8-cyan)">self</span>, <span style="color:var(--pico-8-cyan)">self</span>.backtrace<span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
#<span style="color:var(--pico-8-cyan)">[</span><span style="color:var(--pico-8-brown)">derive</span><span style="color:var(--pico-8-washed-grey)">(Debug)</span><span style="color:var(--pico-8-cyan)">]</span><br>
<span style="color:var(--pico-8-cyan)">pub struct</span> <span style="color:var(--pico-8-washed-grey)">OptionError</span>;<br>
<br>
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">Error</span> <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">OptionError</span> <span style="color:var(--pico-8-cyan)">{}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Display</span> <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">OptionError</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">fmt</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-washed-grey)">self</span>, <u>f</u>: &<span style="color:var(--pico-8-cyan)">mut</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Formatter</span>&lt;<span style="color:var(--pico-8-cyan)">'_</span>&gt<span style="color:var(--pico-8-green)">)</span> -&gt; <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Result</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">write!</span><span style="color:var(--pico-8-brown)">(</span><u>f</u>, <span style="color:var(--pico-8-brown)">"Option was None")</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">impl</span>&lt;<span style="color:var(--pico-8-washed-grey)">E</span>: <span style="color:var(--pico-8-washed-grey)">Error</span> + <span style="color:var(--pico-8-cyan)">'static</span>&gt <span style="color:var(--pico-8-washed-grey)">From</span>&lt;<span style="color:var(--pico-8-washed-grey)">E</span>&gt; <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">RisError</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">from</span><span style="color:var(--pico-8-green)">(</span>value: <span style="color:var(--pico-8-washed-grey)">E</span><span style="color:var(--pico-8-green)">)</span> -&gt; <span style="color:var(--pico-8-cyan)">Self</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">Self</span> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;source: <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">Arc</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span>value<span style="color:var(--pico-8-green)">)</span><span style="color:var(--pico-8-cyan)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message: <span style="color:var(--pico-8-washed-grey)">None</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file: <span style="color:var(--pico-8-washed-grey)">String</span>::<span style="color:var(--pico-8-brown)">from</span><span style="color:var(--pico-8-cyan)">(file!</span><span style="color:var(--pico-8-green)">()</span><span style="color:var(--pico-8-cyan)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line: <span style="color:var(--pico-8-cyan)">line!()</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;backtrace: <span style="color:var(--pico-8-cyan)">crate</span>::<span style="color:var(--pico-8-cyan)">get_backtrace!()</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">pub trait</span> <span style="color:var(--pico-8-washed-grey)">Extensions</span>&lt;<span style="color:var(--pico-8-washed-grey)">T</span>&gt; <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">unroll</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-green)">)</span> -&gt; <span style="color:var(--pico-8-washed-grey)">Result</span>&lt;<span style="color:var(--pico-8-washed-grey)">T</span>, <span style="color:var(--pico-8-washed-grey)">RisError</span>&gt;;<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">impl</span>&lt;<span style="color:var(--pico-8-washed-grey)">T</span>&gt; <span style="color:var(--pico-8-washed-grey)">Extensions</span>&lt;<span style="color:var(--pico-8-washed-grey)">T</span>&gt; <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">Option</span>&lt;<span style="color:var(--pico-8-washed-grey)">T</span>&gt; <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">unroll</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-green)">)</span> -&gt; <span style="color:var(--pico-8-washed-grey)">Result</span>&lt;<span style="color:var(--pico-8-washed-grey)">T</span>, <span style="color:var(--pico-8-washed-grey)">RisError</span>&gt; <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> <span style="color:var(--pico-8-cyan)">self</span> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span>value<span style="color:var(--pico-8-cyan)">)</span> =&gt; <span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-cyan)">(</span>value<span style="color:var(--pico-8-cyan)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">None</span> =&gt; <span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">RisError</span>::<span style="color:var(--pico-8-brown)">from</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">OptionError</span><span style="color:var(--pico-8-green)">)</span><span style="color:var(--pico-8-cyan)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
#<span style="color:var(--pico-8-cyan)">[</span>macro_export<span style="color:var(--pico-8-cyan)">]</span><br>
<span style="color:var(--pico-8-cyan)">macro_rules! new {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">(</span>$<span style="color:var(--pico-8-brown)">(</span>$arg:tt<span style="color:var(--pico-8-brown)">)</span>*<span style="color:var(--pico-8-green)">)</span> =&gt; <span style="color:var(--pico-8-green)">{</span><span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">use</span> $<span style="color:var(--pico-8-cyan)">crate</span>::<span style="color:var(--pico-8-washed-grey)">error</span>::<span style="color:var(--pico-8-washed-grey)">RisError</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> source = <span style="color:var(--pico-8-washed-grey)">None</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> message = <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-brown)">format!</span><span style="color:var(--pico-8-green)">(</span>$<span style="color:var(--pico-8-brown)">(</span>$arg<span style="color:var(--pico-8-brown)">)</span>*<span style="color:var(--pico-8-green)">)</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> file = <span style="color:var(--pico-8-washed-grey)">String</span>::<span style="color:var(--pico-8-brown)">from</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-brown)">file!</span><span style="color:var(--pico-8-green)">()</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> line = <span style="color:var(--pico-8-brown)">line!</span><span style="color:var(--pico-8-cyan)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> backtrace = $<span style="color:var(--pico-8-cyan)">crate</span>::<span style="color:var(--pico-8-brown)">get_backtrace!</span><span style="color:var(--pico-8-cyan)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">RisError</span><span style="color:var(--pico-8-cyan)">{</span>source, message, file, line, backtrace<span style="color:var(--pico-8-cyan)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><span style="color:var(--pico-8-green)">}</span>;<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
#<span style="color:var(--pico-8-cyan)">[</span>macro_export<span style="color:var(--pico-8-cyan)">]</span><br>
<span style="color:var(--pico-8-cyan)">macro_rules! new_result {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">(</span>$<span style="color:var(--pico-8-brown)">(</span>$arg:tt<span style="color:var(--pico-8-brown)">)</span>*<span style="color:var(--pico-8-green)">)</span> =&gt; <span style="color:var(--pico-8-green)">{</span><span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> result = $<span style="color:var(--pico-8-cyan)">crate</span>::<span style="color:var(--pico-8-brown)">new!</span><span style="color:var(--pico-8-cyan)">(</span>$<span style="color:var(--pico-8-green)">(</span>$arg<span style="color:var(--pico-8-green)">)</span>*<span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-cyan)">(</span>result<span style="color:var(--pico-8-cyan)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><span style="color:var(--pico-8-green)">}</span>;<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
#<span style="color:var(--pico-8-cyan)">[</span>macro_export<span style="color:var(--pico-8-cyan)">]</span><br>
<span style="color:var(--pico-8-cyan)">macro_rules! get_backtrace {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">()</span> =&gt; <span style="color:var(--pico-8-green)">{</span><span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">use</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">backtrace</span>::<span style="color:var(--pico-8-washed-grey)">Backtrace</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">use</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">sync</span>::<span style="color:var(--pico-8-washed-grey)">Arc</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> backtrace = <span style="color:var(--pico-8-washed-grey)">Arc</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">Backtrace</span>::<span style="color:var(--pico-8-brown)">force_capture</span><span style="color:var(--pico-8-green)">()</span><span style="color:var(--pico-8-cyan)">)</span></span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">eprintln!</span><span style="color:var(--pico-8-cyan)">(</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">"<span style="color:var(--pico-8-red)">\u{001B}</span>[93mWARNING<span style="color:var(--pico-8-red)">\u{001B}</span>[0m: created backtrace. this operation is expensive. excessive use may cost performance.<span style="color:var(--pico-8-red)">\n</span>&nbsp;&nbsp;&nbsp;&nbsp;in {}:{}<span style="color:var(--pico-8-red)">\n</span><span style="color:var(--pico-8-brown)">"</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">file!</span><span style="color:var(--pico-8-green)">()</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">line!</span><span style="color:var(--pico-8-green)">()</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;backtrace<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
</code>
]]></content:encoded></item><item><title>My most hated feature in Rust</title><link>https://www.rismosch.com/article?id=my-most-hated-feature-in-rust</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">my-most-hated-feature-in-rust</guid><pubDate>Sun, 03 Dec 2023 13:57:57 +0100</pubDate><description>Result is a quite powerful concept. But because it's so general, it's quite clunky and aweful to use.</description><content:encoded><![CDATA[<blockquote style="background-color:var(--pico-8-white); border: 5px solid var(--pico-8-cyan); padding: 20px;"><p>There are only two kinds of languages: the ones people complain about and the ones nobody uses.</p><cite>Bjarne Stoustroup</cite></blockquote>

<p>I use Rust and I plan to continue, so I've earned the right to complain about Rust. But this won't be your average Rust vs Go blogpost. (Why are there so many of those? What the hell?) I won't be complaining about the borrow checker. Neither about traits, lifetimes, macros or compile times. These are fine. No, I will be complaining about <code class="code">Result</code>. That is right. I will be complaining about one of Rusts most beloved features.</p> 

<p>Rust prides itself on its robust and strong type system. If a function returns an object, you can be 99.99998...% sure that this object actually exists. (I am not saying 100%, because unsafe Rust exists. And who knows if some dependency you are using is doing some funky C++ shit under the hood.) If this object may not exist, it will be wrapped in an <code class="code">Option</code>. Before you can access it however, you must first check, whether this <code class="code">Option</code> actually holds your object. And if it doesn't, your object really doesn't exist and you cannot access it.</p>

<p><code class="code">Result</code> is quite similar, but a notch above <code class="code">Option</code>. Like in <code class="code">Option</code>, your object may or may not exist, but if it doesn't, it holds an error. This error (hopefully&#8482;) describes why the function couldn't return your object. And just like <code class="code">Option</code>, before you can access your object, you must first check whether it actually exists or not.</p>

<p>Everything is safe and sound.</p>

<p>But then you start to use <code class="code">Result</code>, and it turns out it's pretty clunky to use and just plain annoying.</p>

<h2>The problems emerge</h2>

<p>First of all, a lot of things can fail. Let me repeat: A LOT OF THINGS CAN FAIL. And you need to handle each and every Result you encounter. This means, everyone gets a match-statement, and bloated boilerplate ensues.</p>

<img src='https://www.rismosch.com/articles/my-most-hated-feature-in-rust/opera.webp' style='display: block; margin: auto; max-width: 100%;'/>

<p><i>"Aha!"</i> says the Rust evangelist, <i>"Simply use the <code class="code">?</code> operator!"</i> Ah yes. That removes the <code class="code">match</code>. But it introduces more complexity somewhere else: Now the client function must also return a <code class="code">Result</code>, and its error type must be the same as the calling function. This introduces problems the moment you call functions that return different errors. Now you'll have to convert errors to other errors, otherwise the compiler won't be happy.</p>

<p><i>"Well, just use <code class="code">From</code>!"</i> says the evangelist. Sure, let's hide the boiler plate code somewhere else, because this obviously fixes the issue. Also, do you really want to implement <code class="code">From</code> between all the hundreds of error states, that your program can find itself in? I don't think so.</p>

<p><i>"I hear you, I hear you. What about <code class="code">map_err()</code> then?"</i> I mean yes, that works. It's obvious, straightforward and understandable. But it becomes quite annoying when you have to type it hundreds of times.</p>

<p><i>"Ehh, <code class="code">unwrap</code>?"</i> Cool. Why even use Rust in the first place?</p>

<p>Ultimately there is no silver bullet, and you will most likely use a combination of these solutions.</p>

<h2>It keeps on giving...</h2>

<p>Okay, usability aside, what else is there to hate about <code class="code">Result</code>? Here's something: They give little information about what actually went wrong. Ideally, you want the error to implement <code class="code">std::error::Error</code>, such that you can log it or something. You probably also want it to be an <code class="code">enum</code>, such that it gives you a human readable and computer friendly way to tell what went wrong. Boilerplate over boilerplate.</p>

<p>Look, for the API of your library, it makes sense to cover all possible failure states. But from my perspective, building a game engine, an executable, I only care whether the given operation succeeded or not. And when it fails, it should tell me where and why. <code class="code">Result</code> simply doesn't provide that information. The uncool thing about <code class="code">Result</code> is, that <i>anything</i> can be an error. The error may not implement <code class="code">std::error::Error</code>, and it may not be an <code class="code">enum</code>. The <a href="https://docs.rs/sdl2/latest/sdl2/" target="_blank" rel="noopener noreferrer">SDL2</a> crate for example made the amazingly annoying decision, to only return <code class="code">String</code>s as errors.</p>

<p>Compare that to exceptions in C#, which I am very familiar with. When an exception is thrown, you get an entire stack trace. You know which function called which, and it's usually fairly easy to pinpoint where and why an exception was thrown. Not so with Rust errors. When a "stream read failed" error bubbles up to my entry function, my first reaction is annoyance, because I have no idea where it occurred. It's not like I don't read streams in like 100 different places, no?</p>

<img src='https://www.rismosch.com/articles/my-most-hated-feature-in-rust/do_you_have_the_slightest_idea.webp' style='display: block; margin: auto; max-width: 100%;'/>

<p>In Rusts defense however, when building C# as Release, most debug symbols are stripped away, and you get error messages that are undecipherable and less useful than C++ linker errors. Because you know, the linker at least <i>tries</i> to tell you what went wrong. Exceptions in C# Release builds just spit digital vomit at you.</p>

<h2>The antidote?</h2>

<p>Nonetheless, all problems I've described thus far, drove me to the point where I attempted to solve them by my own custom error type: <code class="code">RisError</code>. It stores a message, it's file and line where it was created, and the <code class="code">std::error::Error</code> that caused it. The file and line are not as useful as an entire stack trace, but it's better than nothing. I also created a few macros, that make creating and converting errors into it easier. Now, everything that fails returns an <code class="code">RisResult&lt;T&gt;</code>, which essentially is just a <code class="code">Result&lt;T, RisError&gt;</code>. Thus I can use <code class="code">?</code> everywhere, and use macros whenever something is not an <code class="code">RisError</code>.</p>

<code>
<p class="code code_block">
<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">foo</span><span style="color:var(--pico-8-cyan)">(</span>i: <span style="color:var(--pico-8-washed-grey)">usize</span><span style="color:var(--pico-8-cyan)">)</span> -&gt; <span style="color:var(--pico-8-washed-grey)">RisResult</span>&lt;<span style="color:var(--pico-8-washed-grey)">Bar</span>&gt; <span style="color:var(--pico-8-cyan)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">ris_util</span>::<span style="color:var(--pico-8-brown)">unroll!</span><span style="color:var(--pico-8-green)">(</span> <span style="color:var(--pico-8-green)">// this right here is the golden goose</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">im_a_dangerous_function(</span>i<span style="color:var(--pico-8-brown)">)</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">"failed to call function with {}"</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">)</span>?;<br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;...<br/>
<span style="color:var(--pico-8-cyan)">}</span><br/>
<br/>
<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">im_a_dangerous_function</span><span style="color:var(--pico-8-cyan)">(</span>i: <span style="color:var(--pico-8-washed-grey)">usize</span><span style="color:var(--pico-8-cyan)">)</span> -&gt; <span style="color:var(--pico-8-washed-grey)">Result</span>&lt;<span style="color:var(--pico-8-cyan)">()</span>, <span style="color:var(--pico-8-washed-grey)">SomeError</span>&gt; <span style="color:var(--pico-8-cyan)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;...<br/>
<span style="color:var(--pico-8-cyan)">}</span><br/>
</p>
</code>

<p>At this point, you may notice that this looks awfully like exceptions. Abort execution at anytime... Possibly (hopefully&#8482;) catch it somewhere up the call stack... Pretty much a <code class="code">goto</code>, but god knows where it will end up... And you may ask, why even go through the trouble and not just use exceptions in the first place? To that I say: RAII still holds. And RAII is very useful.</p>

<p>With this system, if an error occurs, I can still execute code. This allows me to gather system information, properly log failure states and ensure that the current state of the game is saved, such that no progress is lost. A <code class="code">try-catch</code> (or <code class="code">std::panic::catch_unwind</code> as the Rust people call it) doesn't work: Building as Release, exceptions are disabled and they are turned into aborts.</p>

<p>Even if I enable exceptions in Release, or are somehow able to catch aborts, working with exceptions in memory managed languages is infamously difficult. It's so difficult in fact, that people coined the term <a href="https://en.wikipedia.org/wiki/Exception_safety" target="_blank" rel="noopener noreferrer">exception safety</a>. If I keep avoiding exceptions, everything that implements <code class="code">Drop</code> will be cleaned up properly.</p>

<p>And it is now, where I have to mention, that I am absolutely annoyed by the fact that the Rust people decided to rename exceptions to "panics". When talking to non Rust people, I always have to preface: "Ackchyually, Rust has exceptions, they just call it something different".</p>

<img src='https://www.rismosch.com/articles/my-most-hated-feature-in-rust/actually.webp' style='display: block; margin: auto; max-width: 100%;'/>

<p>I understand why the Rust people decided to rename them. Because exceptions are rarely exceptional. If you are anticipating an error with <code class="code">try-catch</code>, is it really an "exception"? But the irony is, in my case, exceptions now really represent exceptional state! It's state that I did not account for. State that allows the engine to crash without properly shutting down. It's so backwards, and I hate it. I hate it so much.</p>

<h2>Conclusion</h2>

<p>If there will be a successor of Rust, I'd wish for an error system in between of <code class="code">Result</code> and exceptions, which goes alongside the other two. Something that generates a stack trace and unrolls like an exception, but allows RAII to properly free all held resources.</p>

<p>The compiler is smart. Couldn't the compiler generate a stack trace at compile time? I mean like generics, it could just figure out all the functions that call an error, and just place that function path as a compile constant string into the error, no? But I guess recursion must then be forbidden, because that damn halting problem exist. God fucking dammit. I curse you, halting problem!</p>

<img src="https://www.rismosch.com/articles/my-most-hated-feature-in-rust/turing.webp" style="display: block; margin: auto; max-width: 100%;"/>

<p>Nevertheless. As much as I hate my current solution, it is usable. And that is all I need for now....</p>

<p>Because people will be asking, below is the implementation of <code class="code">RisError</code>. I called the conversion macro <code class="code">unroll</code>, to differentiate it from <code class="code">unwrap</code>, and because <code class="code">RisError</code>s can be chained, like exceptions unrolling a stack.</p>

<p><a href="https://github.com/Rismosch/ris_engine/blob/2c94f080fe45bf0f7d3fbd4da0fbc439e76a8717/crates/ris_util/src/error.rs" target="_blank" rel="noopener noreferrer">GitHub permalink</a></p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">use</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">error</span>::<span style="color:var(--pico-8-washed-grey)">Error</span>;<br/>
<br/>
<span style="color:var(--pico-8-cyan)">pub type</span> <span style="color:var(--pico-8-washed-grey)">RisResult</span>&lt;<span style="color:var(--pico-8-washed-grey)">T</span>&gt; = <span style="color:var(--pico-8-washed-grey)">Result</span>&lt;<span style="color:var(--pico-8-washed-grey)">T</span>, <span style="color:var(--pico-8-washed-grey)">RisError</span>&gt;;<br/>
<br/>
<span style="color:var(--pico-8-cyan)">pub type</span> <span style="color:var(--pico-8-washed-grey)">SourceError</span> = <span style="color:var(--pico-8-washed-grey)">Option</span>&lt;std::sync::<span style="color:var(--pico-8-washed-grey)">Arc</span>&lt;<span style="color:var(--pico-8-cyan)">dyn</span> <span style="color:var(--pico-8-washed-grey)">Error</span> + '<span style="color:var(--pico-8-washed-grey)">static</span>&gt;&gt;;<br/>
<br/>
#<span style="color:var(--pico-8-cyan)">[</span>derive<span style="color:var(--pico-8-green)">(<span style="color:var(--pico-8-washed-grey)">Clone</span>)</span><span style="color:var(--pico-8-cyan)">]</span><br/>
<span style="color:var(--pico-8-cyan)">pub struct <span style="color:var(--pico-8-washed-grey)">RisError</span> {</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;source: <span style="color:var(--pico-8-washed-grey)">SourceError</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;message: <span style="color:var(--pico-8-washed-grey)">String</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;file: <span style="color:var(--pico-8-washed-grey)">String</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;line: <span style="color:var(--pico-8-washed-grey)">u32</span>,<br/>
<span style="color:var(--pico-8-cyan)">}</span><br/>
<br/>
<span style="color:var(--pico-8-cyan)">impl <span style="color:var(--pico-8-washed-grey)">RisError</span> {</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span>source: <span style="color:var(--pico-8-washed-grey)">SourceError</span>, message: <span style="color:var(--pico-8-washed-grey)">String</span>, file: <span style="color:var(--pico-8-washed-grey)">String</span>, line: <span style="color:var(--pico-8-washed-grey)">u32</span><span style="color:var(--pico-8-green)">)</span> -&gt; <span style="color:var(--pico-8-cyan)">Self</span> <span style="color:var(--pico-8-green)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">Self</span> <span style="color:var(--pico-8-brown)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;source,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">message</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-green)">)</span> -&gt; &<span style="color:var(--pico-8-washed-grey)">String</span> <span style="color:var(--pico-8-green)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&<span style="color:var(--pico-8-cyan)">self</span>.message<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">file</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-green)">)</span> -&gt; &<span style="color:var(--pico-8-washed-grey)">String</span> <span style="color:var(--pico-8-green)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&<span style="color:var(--pico-8-cyan)">self</span>.file<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">line</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-green)">)</span> -&gt; &<span style="color:var(--pico-8-washed-grey)">u32</span> <span style="color:var(--pico-8-green)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&<span style="color:var(--pico-8-cyan)">self</span>.line<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br/>
<span style="color:var(--pico-8-cyan)">}</span><br/>
<br/>
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">Error</span> <span style="color:var(--pico-8-pink)">for</span> <span style="color:var(--pico-8-washed-grey)">RisError</span> <span style="color:var(--pico-8-cyan)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">source</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-green)">)</span> -&gt; <span style="color:var(--pico-8-washed-grey)">Option</span>&lt;&<span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-cyan)">dyn</span> <span style="color:var(--pico-8-washed-grey)">Error</span> + '<span style="color:var(--pico-8-washed-grey)">static</span><span style="color:var(--pico-8-green)">)</span>&gt; <span style="color:var(--pico-8-green)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">self</span>.source.<span style="color:var(--pico-8-brown)">as_ref()</span>.<span style="color:var(--pico-8-brown)">map(</span>|e| e.<span style="color:var(--pico-8-brown)">as_ref</span><span style="color:var(--pico-8-cyan)">()</span><span style="color:var(--pico-8-brown)">)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br/>
<span style="color:var(--pico-8-cyan)">}</span><br/>
<br/>
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Display</span> <span style="color:var(--pico-8-pink)">for</span> <span style="color:var(--pico-8-washed-grey)">RisError</span> <span style="color:var(--pico-8-cyan)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">fmt</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span>, <u>f</u>: &<span style="color:var(--pico-8-cyan)">mut</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Formatter</span>&lt;'<span style="color:var(--pico-8-green)">_</span>&gt;<span style="color:var(--pico-8-green)">)</span> -&gt; <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Result</span> <span style="color:var(--pico-8-green)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-brown)">(</span>source<span style="color:var(--pico-8-brown)">)</span> = <span style="color:var(--pico-8-cyan)">self</span>.<span style="color:var(--pico-8-brown)">source() {</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">write!</span><span style="color:var(--pico-8-cyan)">(</span><u>f</u>, <span style="color:var(--pico-8-brown)">"{}<span style="color:var(--pico-8-red)">\n</span>&nbsp;&nbsp;&nbsp;&nbsp;"</span>, source<span style="color:var(--pico-8-cyan)">)</span>?;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">write!(</span><u>f</u>, <span style="color:var(--pico-8-brown)">"<span style="color:var(--pico-8-red)">\"</span>{}<span style="color:var(--pico-8-red)">\"</span>, {}:{}"</span>, <span style="color:var(--pico-8-cyan)">self</span>.message, <span style="color:var(--pico-8-cyan)">self</span>.file, <span style="color:var(--pico-8-cyan)">self</span>.line<span style="color:var(--pico-8-brown)">)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br/>
<span style="color:var(--pico-8-cyan)">}</span><br/>
<br/>
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Debug</span> <span style="color:var(--pico-8-pink)">for</span> <span style="color:var(--pico-8-washed-grey)">RisError</span> <span style="color:var(--pico-8-cyan)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">fmt</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span>, <u>f</u>: &<span style="color:var(--pico-8-cyan)">mut</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Formatter</span>&lt;'<span style="color:var(--pico-8-green)">_</span>&gt;<span style="color:var(--pico-8-green)">)</span> -&gt; <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Result</span> <span style="color:var(--pico-8-green)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> source_string = <span style="color:var(--pico-8-pink)">match</span> &<span style="color:var(--pico-8-cyan)">self</span>.source <span style="color:var(--pico-8-brown)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span>source<span style="color:var(--pico-8-cyan)">)</span> =&gt; <span style="color:var(--pico-8-brown)">format!</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-brown)">"Some ({:?})"</span>, source<span style="color:var(--pico-8-cyan)">)</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">None</span> =&gt; <span style="color:var(--pico-8-washed-grey)">String</span>::<span style="color:var(--pico-8-brown)">from</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-brown)">"None"</span><span style="color:var(--pico-8-cyan)">)</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span>;<br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">write!(</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>f</u>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">"RisError {{inner: {}, message: {}, file: {}, line: {}}}"</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;source_string, <span style="color:var(--pico-8-cyan)">self</span>.message, <span style="color:var(--pico-8-cyan)">self</span>.file, <span style="color:var(--pico-8-cyan)">self</span>.line<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br/>
<span style="color:var(--pico-8-cyan)">}</span><br/>
<br/>
#<span style="color:var(--pico-8-cyan)">[</span>derive<span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">Debug</span><span style="color:var(--pico-8-green)">)</span><span style="color:var(--pico-8-cyan)">]</span><br/>
<span style="color:var(--pico-8-cyan)">pub struct</span> <span style="color:var(--pico-8-washed-grey)">OptionError</span>;<br/>
<br/>
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">Error</span> <span style="color:var(--pico-8-pink)">for</span> <span style="color:var(--pico-8-washed-grey)">OptionError</span> <span style="color:var(--pico-8-cyan)">{}</span><br/>
<br/>
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Display</span> <span style="color:var(--pico-8-pink)">for</span> <span style="color:var(--pico-8-washed-grey)">OptionError</span> <span style="color:var(--pico-8-cyan)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">fmt</span>(&<span style="color:var(--pico-8-cyan)">self</span>, <u>f</u>: &<span style="color:var(--pico-8-cyan)">mut</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Formatter</span>&lt;'<span style="color:var(--pico-8-green)">_</span>&gt;<span style="color:var(--pico-8-green)">)</span> -&gt; <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Result</span> <span style="color:var(--pico-8-green)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">write!(</span><u>f</u>, <span style="color:var(--pico-8-brown)">"Option was None")</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br/>
<span style="color:var(--pico-8-cyan)">}</span><br/>
<br/>
#<span style="color:var(--pico-8-cyan)">[</span>macro_export<span style="color:var(--pico-8-cyan)">]</span><br/>
<span style="color:var(--pico-8-brown)">macro_rules! unroll</span> <span style="color:var(--pico-8-cyan)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">(</span>$result:expr, $<span style="color:var(--pico-8-brown)">(</span>$arg:tt<span style="color:var(--pico-8-brown)">)</span>*<span style="color:var(--pico-8-green)">)</span> =&gt; <span style="color:var(--pico-8-green)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> $result <span style="color:var(--pico-8-brown)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-cyan)">(</span>value<span style="color:var(--pico-8-cyan)">)</span> =&gt; <span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-cyan)">(</span>value<span style="color:var(--pico-8-cyan)">)</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-cyan)">(</span>error<span style="color:var(--pico-8-cyan)">)</span> =&gt; <span style="color:var(--pico-8-cyan)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> source: <span style="color:var(--pico-8-washed-grey)">ris_util<span style="color:var(--pico-8-black)">::</span>error<span style="color:var(--pico-8-black)">::</span>SourceError <span style="color:var(--pico-8-black)">=</span> Some<span style="color:var(--pico-8-green)">(</span>std<span style="color:var(--pico-8-black)">::</span>sync<span style="color:var(--pico-8-black)">::</span>Arc</span>::<span style="color:var(--pico-8-brown)">new(<span style="color:var(--pico-8-black)">error</span>)</span><span style="color:var(--pico-8-green)">)</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> message = <span style="color:var(--pico-8-brown)">format!</span><span style="color:var(--pico-8-green)">(</span>$<span style="color:var(--pico-8-brown)">(</span>$arg<span style="color:var(--pico-8-brown)">)</span>*<span style="color:var(--pico-8-green)">)</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> file = <span style="color:var(--pico-8-washed-grey)">String</span>::<span style="color:var(--pico-8-brown)">from</span><span style="color:var(--pico-8-green)">(<span style="color:var(--pico-8-brown)">file!()</span>)</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> line = <span style="color:var(--pico-8-brown)">line!</span><span style="color:var(--pico-8-green)">()</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> result = <span style="color:var(--pico-8-washed-grey)">ris_util</span>::<span style="color:var(--pico-8-washed-grey)">error</span>::<span style="color:var(--pico-8-washed-grey)">RisError</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span>source, message, file, line<span style="color:var(--pico-8-green)">)</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-green)">(</span>result<span style="color:var(--pico-8-green)">)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span>;<br/>
<span style="color:var(--pico-8-cyan)">}</span><br/>
<br/>
#<span style="color:var(--pico-8-cyan)">[</span>macro_export<span style="color:var(--pico-8-cyan)">]</span><br/>
<span style="color:var(--pico-8-brown)">macro_rules! unroll_option</span> <span style="color:var(--pico-8-cyan)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">(</span>$result:expr, $<span style="color:var(--pico-8-brown)">(</span>$arg:tt<span style="color:var(--pico-8-brown)">)</span>*<span style="color:var(--pico-8-green)">)</span> =&gt; <span style="color:var(--pico-8-green)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> $result <span style="color:var(--pico-8-brown)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span>value<span style="color:var(--pico-8-cyan)">)</span> =&gt; <span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-cyan)">(</span>value<span style="color:var(--pico-8-cyan)">)</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">None</span> =&gt; <span style="color:var(--pico-8-cyan)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> source: <span style="color:var(--pico-8-washed-grey)">ris_util</span>::<span style="color:var(--pico-8-washed-grey)">error</span>::<span style="color:var(--pico-8-washed-grey)">SourceError</span> = <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">sync</span>::<span style="color:var(--pico-8-washed-grey)">Arc</span>::<span style="color:var(--pico-8-brown)">new(</span><span style="color:var(--pico-8-washed-grey)">ris_util</span>::<span style="color:var(--pico-8-washed-grey)">error</span>::<span style="color:var(--pico-8-washed-grey)">OptionError</span><span style="color:var(--pico-8-brown)">)</span><span style="color:var(--pico-8-green)">)</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> message = <span style="color:var(--pico-8-brown)">format!</span><span style="color:var(--pico-8-green)">(</span>$<span style="color:var(--pico-8-brown)">(</span>$arg<span style="color:var(--pico-8-brown)">)</span>*<span style="color:var(--pico-8-green)">)</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> file = <span style="color:var(--pico-8-washed-grey)">String</span>::<span style="color:var(--pico-8-brown)">from</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-brown)">file!()</span><span style="color:var(--pico-8-green)">)</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> line = <span style="color:var(--pico-8-brown)">line!</span><span style="color:var(--pico-8-green)">()</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> result = <span style="color:var(--pico-8-washed-grey)">ris_util</span>::<span style="color:var(--pico-8-washed-grey)">error</span>::<span style="color:var(--pico-8-washed-grey)">RisError</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span>source, message, file, line<span style="color:var(--pico-8-green)">)</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-green)">(</span>result<span style="color:var(--pico-8-green)">)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span>;<br/>
<span style="color:var(--pico-8-cyan)">}</span><br/>
<br/>
#<span style="color:var(--pico-8-cyan)">[</span>macro_export<span style="color:var(--pico-8-cyan)">]</span><br/>
<span style="color:var(--pico-8-brown)">macro_rules! new_err</span> <span style="color:var(--pico-8-cyan)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">(</span>$<span style="color:var(--pico-8-brown)">(</span>$arg:tt<span style="color:var(--pico-8-brown)">)</span>*<span style="color:var(--pico-8-green)">)</span> =&gt; <span style="color:var(--pico-8-green)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> source: <span style="color:var(--pico-8-washed-grey)">ris_util</span>::<span style="color:var(--pico-8-washed-grey)">error</span>::<span style="color:var(--pico-8-washed-grey)">SourceError</span> = <span style="color:var(--pico-8-washed-grey)">None</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> message = <span style="color:var(--pico-8-brown)">format!</span><span style="color:var(--pico-8-cyan)">(</span>$<span style="color:var(--pico-8-green)">(</span>$arg<span style="color:var(--pico-8-green)">)</span>*<span style="color:var(--pico-8-cyan)">)</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> file = <span style="color:var(--pico-8-washed-grey)">String</span>::<span style="color:var(--pico-8-brown)">from</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-brown)">file!</span><span style="color:var(--pico-8-green)">()</span><span style="color:var(--pico-8-cyan)">)</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> line = <span style="color:var(--pico-8-brown)">line!</span><span style="color:var(--pico-8-cyan)">()</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">ris_util</span>::<span style="color:var(--pico-8-washed-grey)">error</span>::<span style="color:var(--pico-8-washed-grey)">RisError</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-cyan)">(</span>source, message, file, line<span style="color:var(--pico-8-cyan)">)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span>;<br/>
<span style="color:var(--pico-8-cyan)">}</span><br/>
<br/>
#<span style="color:var(--pico-8-cyan)">[</span>macro_export<span style="color:var(--pico-8-cyan)">]</span><br/>
<span style="color:var(--pico-8-brown)">macro_rules! result_err</span> <span style="color:var(--pico-8-cyan)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">(</span>$<span style="color:var(--pico-8-brown)">(</span>$arg:tt<span style="color:var(--pico-8-brown)">)</span>*<span style="color:var(--pico-8-green)">)</span> =&gt; <span style="color:var(--pico-8-green)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">{</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> result = <span style="color:var(--pico-8-washed-grey)">ris_util</span>::<span style="color:var(--pico-8-brown)">new_err!</span><span style="color:var(--pico-8-cyan)">(</span>$<span style="color:var(--pico-8-green)">(</span>$arg<span style="color:var(--pico-8-green)">)</span>*<span style="color:var(--pico-8-cyan)">)</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-cyan)">(</span>result<span style="color:var(--pico-8-cyan)">)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span>;<br/>
<span style="color:var(--pico-8-cyan)">}</span><br/>

</code>]]></content:encoded></item><item><title>Making videos is hard</title><link>https://www.rismosch.com/article?id=making-videos-is-hard</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Other]]</category><guid isPermaLink="false">making-videos-is-hard</guid><pubDate>Mon, 31 Jul 2023 23:44:16 +0200</pubDate><description>I was planning to make a beginner friendly video to explain quaternions. Unfortunately, that took a lot longer than expected.</description><content:encoded><![CDATA[<p>Quaternions are easy. I am not saying this to flex my intelligence. I am saying this because I genuinely believe that they are easy. The problem is just that there aren't many beginner friendly resources out there. I mean there is <a href="https://eater.net/quaternions" target="_blank" rel="noopener noreferrer">this</a>, by Grant Sanderson and Ben Eater, but Grant is a mathematician, not a programmer. So while the videos are <i>theoretically</i> correct, they aren't particularly helpful in your 3d programming day to day life.</p>

<p>I was trying to change this, by actually doing a beginner friendly intro to Quaternions, but it turned out to be much more work than anticipated. I made <a href="https://www.rismosch.com/article?id=quaternion-playground" target="_blank" rel="noopener noreferrer">this visualization tool</a>, which is something. It's inspired by the book "Visualizing Quaternions" by Andrew J. Hanson and it's in my opinion better than any other visualization that I've found online.</p>

<img src='https://www.rismosch.com/articles/making-videos-is-hard/obama.webp' style='display: block; margin: auto; max-width: 100%;' />

<p>Unfortunately, the tool is rather worthless if you don't have a mentor that explains it to you. So the idea was that I also make a video to specifically explain the tool and give a good, simple explanation of quaternions. An explanation that isn't riddled with formulas, doesn't require an understanding of the 4th dimension, and doesn't ask of a deep understanding of mathematics. Such an explanation is indeed possible: I've held a presentation at my job to do exactly that. But the slides are rather low quality, and use many questionable pictures which violate copyright. (On that note, fuck copyright.)</p>

<p>If I wanted to make something that would go on YouTube, instead I had to make custom pictures and diagrams, write a proper script, record and edit a video. Problem is, the visualization tool already took a month of work, and this video will take probably another. Also also, I advocate to use <a href="https://docs.unity3d.com/ScriptReference/Quaternion.AngleAxis.html" target="_blank" rel="noopener noreferrer">Quaternion.AngleAxis</a> and <a href="https://docs.unity3d.com/ScriptReference/Quaternion.LookRotation.html" target="_blank" rel="noopener noreferrer">Quaternion.LookRotation</a> and I discourage everyone to use Euler Angles ever again. But I want to keep things as general as possible. I don't want to say <i>"just use the provided functions by Unity"</i>. Instead I want to provide proper formulas, because 1: Not everyone is using Unity. And 2: People may want to write their own quaternion library, and this just doesn't fly.</p>

<p>This is all a lot of work.</p>

<img src='https://www.rismosch.com/articles/making-videos-is-hard/screenshot.webp' style='display: block; margin: auto; max-width: 100%;' />

<p>It is at this moment, where I truly realized the difference between people who make, and people who talk. On YouTube you find a lot of people who talk about how to program, how to make a game the "proper way". But often the advice these people preach is shallow and meaningless. The worst kind of these people are video essayists and critics, who talk about what makes a game good, but never made or even considered making one. On this note, huge respect for Mark Brown from Game Maker's Toolkit, who actually tried to put his knowledge to the test and tried making one.</p>

<p>This whole makers vs talkers thing reminds me about the book "Clean Code" by Robert Martin, which is full of questionable advice, which the author himself doesn't actually follow. It also reminds me about No Man's Sky, how it was ruined by the fact that they talked about it too much, but then fixed it by shutting up and actually fixing it: <a href="https://youtu.be/O5BJVO3PDeQ" target="_blank" rel="noopener noreferrer">https://youtu.be/O5BJVO3PDeQ</a></p>

<p>I decided that I want to be a maker, not a talker. As such I scrapped the idea of a video, and instead focus more on my engine. So here's what I've been up to: I implemented a basic Vulkan based 3d renderer into my engine :)</p>

<video style="max-width:100%; display: block; margin: auto;" loading='lazy' controls>
<source src="https://www.rismosch.com/articles/making-videos-is-hard/backface_culling_compressed.mp4" type="video/mp4">
</video>

<p>Because of this, my brain is now full of transformation matrices instead of quaternions. Next steps would be build on top of it more. At the time of writing, I am missing index buffers and depth testing. Then I would also want to start with my resource system, such that I can actually import 3d files. Then I would also want to put my shaders into files, such that I can recompile and hotswap them at runtime. Nice stuff.</p>

<img src='https://www.rismosch.com/articles/making-videos-is-hard/thumbnail.webp' style='display: block; margin: auto; max-width: 100%;' />

<p>Until then, radio silence &#128586;</p>
]]></content:encoded></item><item><title>Oops, I deleted my Newsletter</title><link>https://www.rismosch.com/article?id=oops-i-deleted-my-newsletter</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">oops-i-deleted-my-newsletter</guid><pubDate>Sun, 07 May 2023 07:33:56 +0200</pubDate><description>Storing user data is hard. In this blogpost I describe my issues with my Newsletter and why it caused much problems</description><content:encoded><![CDATA[<p>Tracking data is bullshit. I hate when websites track me. And I hate it that technically I am collecting data about you too. Think about it: If I want to have a newsletter, I need to store your email somehow. And this provided me a great deal of headaches, ever since I got my newsletter system working.</p>

<p>First off, I can't make backups. I have yet to experience an SQL Injection Attack, but eventually someone or something will drop all my tables. This is no big deal for my blog, since I store according files separately. In the worst case, I have to fill in the database by hand. But with emails, I can't do that. Assume for a second my tables are dropped, and in that exact time you want to unsubscribe from my newsletter. If I had a backup and restore it, and send the newsletter for a new blogpost, suddenly you receive an email from me, even though you unsubscribed. This is an opportunity for you to sue me, and I don't want to be sued.</p>

<p>Also, people who want to steal the data are free to attack me. I am no IT security professional. I do have basic knowledge, and I did put some safety measures in place, but I am not arrogant enough to say that my system is failsafe. The systems I had were good enough to an extent, such that to my current knowledge, I haven't leaked a single email. But if I do manage to leak an email anyhow, I am the one who is responsible. Again, you could sue me if that happens, and I really really don't want to be sued.</p>

<p style="text-align:center">&#128531;</p>

<p>All this is pain. And it has led me to delete my newsletter. At the time of writing this post, all emails stored on my database are already eradicated. Maybe, if the development of <a href="https://github.com/Rismosch/ris_engine" target="_blank" rel="noopener noreferrer">my game engine</a> is far enough, such that I can release a working product, I may introduce a newsletter again. But then I am probably in a position where I would pay a professional service for that. There is no way I am ever touching something sensitive like storing user data ever again.</p>

<img src="https://www.rismosch.com/articles/oops-i-deleted-my-newsletter/image_0.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>While cleaning up my legal mess, I used the opportunity to get rid of Disqus as well. I am proud to say that I don't use trackers or cookies. I think that's honorable, considering that tracking people has become the norm. And this non-tracking also allowed me to not show you an annoying popup whenever you visit my website. For Disqus however, I displayed a warning that they will track your data. I feel also very proud about this solution, as this thing doesn't even load Disqus, when you don't press the button.</p>

<p>Unfortunately, no one uses the comments. Probably because I have no reach, but probably also because that warning deters that lone wanderer that found me. If this is an indicator for anything, then that people simply don't want to be tracked. Therefore, Disqus serves zero purpose, and I deleted it as well.</p>

<img src="https://www.rismosch.com/articles/oops-i-deleted-my-newsletter/image_1.webp" style="display: block; margin: auto; max-width: 100%; border: 5px solid var(--pico-8-dark-grey);" />

<p>I also updated my <a href="https://www.rismosch.com/privacy" target="_blank" rel="noopener noreferrer">privacy policy</a>, to reflect these changes. And to make it more user friendly, I added a section at the top for non-lawyers. A less dry and quick summary of the whole document.</p>

<p>After these adjustments, I am very happy about the state of my website. A major headache gone. Now literally the only thing that collects data is my contact form. But since this sends an email, it should be pretty obvious that this is data that is stored somehow somewhere, and I think there is nothing controversial about that.</p>

<p>Now my website is exactly how I always described it: A blog and project-collection.</p>
]]></content:encoded></item><item><title>How I made The World Between My Mind And Reality</title><link>https://www.rismosch.com/article?id=how-i-made-the-world-between-my-mind-and-reality</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Music]]</category><guid isPermaLink="false">how-i-made-the-world-between-my-mind-and-reality</guid><pubDate>Fri, 10 Mar 2023 13:37:48 +0100</pubDate><description>I describe how I made my latest album. Which instruments I used, how I went about recording vocals and how I made the cover art.</description><content:encoded><![CDATA[<p>So I've done it. Since announcing it <a href="https://www.rismosch.com/article?id=post-crisis" target="_blank" rel="noopener noreferrer">8 months ago</a>, in October last year I've finally managed to take a break from my engine and compose an album. It's just short of half an hour. I am simply not cut to make hour long masterpieces. So this has to suffice.</p>

<p>I had a lot of doubt in the beginning. During my time studying, I was making music on and off, it was never a big deal. But then I had a job, and suddenly the free time was gone. The game engine is definitely a life goal, so I am definitely going to pursue that. Though, whenever I was working on the engine, there was always this nagging thought at the back of my mind: <i>"Bro? What's up with music? You haven't opened FL Studio in 2 years!"</i> It drove me crazy. Purchasing gear and feeding the <a href="https://de.wikipedia.org/wiki/Gear_Acquisition_Syndrome" target="_blank" rel="noopener noreferrer">GAS</a> didn't help, and it made the doubt so much worse.</p>

<p>In October I finished my <a href="https://www.rismosch.com/article?id=building-a-job-system" target="_blank" rel="noopener noreferrer">JobSystem</a>. While crude and fundamental, it works. But I still had to write the blogpost, which was just. So. Much. This JobSystem and its accompanying blogpost are possibly a master thesis on their own, but fuck it. A degree is nothing but a piece of paper. Once the post was finally done, the literal next step of my engine would be the 3d renderer. I really hit a milestone, and it was the perfect moment to take a break.</p>

<p>And now, after the album is composed, mixed, mastered and uploaded, I want to document, how I made the album.</p>

<h2>The Polybrute</h2>

<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/polybrute.webp" style="display: block; margin: auto; width: 100%;" />

<p>Let's start with this baby, the work horse. It's responsible for the vast majority of sounds in the album. But god damn it, it is such a diva. If you are new to synths, there's this preconception that analog synths are "warmer", "better". I mean, sure the thing is much more fun than a VST on your computer, and the Polybrute definitely sounds different from anything out there, but this god damn thing just didn't want to stay in tune.</p>

<p>I have the Polybrute for almost 2 years now, and one year ago it started to be funny. It went out of tune so badly, that every sixth voice wasn't played in the right ear. I haven't turned it on for months, but then I fired it up in October. And would you know it? No tuning issues whatsoever! The thing acted like it never had any problem. I felt like I was being gaslighted by a friggin synthesizer. But then winter hit, and suddenly the tuning issues returned. This was such a big problem, that I had to plan my entire day around it.</p>

<p>First, I never turned the Polybrute off. Second, I heat my studio to 24,5&#176;C (32&#176;F). I know I know, this is ridiculously warm. And if you still believe in the carbon footprint, this temperature is ludicrous, but it was necessary to keep the Polybrute in tune. Also, I always kept the door of my room shut, to get a more consistent temperature. Once these preconditions are met, my average day looked like this:</p>

<ol>
<li>Wake up.</li>
<li>Ventilate my flat (now everything is cold and the Polybrute is unusable for the next 1-2 hours.)</li>
<li>Go to work after closing the windows.</li>
<li>Back home, tune the Polybrute.</li>
<li>Make music.</li>
<li>Ventilate the room (everything is cold <i>again</i>).</li>
<li>Go to sleep.</li>
</ol>

<p>Most weekends I would only ventilate on Sunday evening, because waiting for the synth to warm up and then tuning it took just way too long and was always such a hustle. The Polybrute has an automatic tune function, which would've been awesome, if it would work... I had better luck disabling the tuning and just stick with the calibration. Remarkably, the VCOs never went out of tune. You know, the thing that people praise about analog synths, that their pitch is <i>slightly</i> off and thus produces these warm and lush tones. Yeah, the VCOs were always perfectly in tune, but the Steiner Filter and the VCAs refused to stay in line.</p>

<p>So, afte all these inconviniences, does it sound good? Well, pretty much every sound on this album, with notable exceptions, is made the Polybrute. It's the fat farting bass synth, and the screaming, grainy pad in "02 Insecurities". It's literally every sound in "03 Chasm Pt1", even the organ! It's the tremolo bass in "04 Chasm Pt2". And "05 Nightmare" pretty much reuses most of these patches, only with the addition of an arpeggio and a solo lead sound. The Polybrute sounds amazing and perfectly fits my taste, it makes all the tuning issues absolutely worth it :)</p>

<p>Note to self: Always make music during summer.</p>

<h2>The other instruments</h2>

<p>While the Polybrute was the bread and butter, I made use of a handful of other instruments. Most notably:</p>

<ul>
<li>909 samples for the drums,</li>
<li>Instance of 3xOsc, only used for risers,</li>
<li>Pianoteq, for the Piano (duh) and</li>
<li>A sample-based choir (it's the default one in FL Studio 20).</li>
</ul>

<p>I pretend to be someone who listens to all genres. Even though I try to listen too as many different styles of music as possible, if I had to pick a favorite, it's probably DnB by a longshot. And my favorite subgenre therein is <a href="https://youtu.be/BNVg9nO2R0o" target="_blank" rel="noopener noreferrer">Intelligent DnB</a>. While I love the sampled, shuffled break beats in the music I listen to, I somehow don't want to use that in the stuff that I make. I really prefer programming my drums, no matter how fake or MIDI they sound.</p>

<p>Up until this album, I've always used samples of acoustic drums. But this time I wanted to try using electric drums. I chose the 909, which I think sounds the best (heresy to the 808, I know). But only after I was done with the first track, "02 Insecurities", did I notice that I really don't like the sound after all, and that I still prefer my drums to be acoustic. But now I had a dilemma to face. I could go back, replace the 909 with acoustic samples and mix the drums again from the ground up. Or I could simply use the finished mixed drums for everything thereafter. I chose to not re-mix my drums. Though I am a little bit bothered by it, I don't really hate it. So it's fine.</p>

<p>While keeping the same project file for multiple songs reduced much mixing work, organization pretty much flew out the window. In the end, instruments weren't in the tracks they were supposed to go, and I had patterns named "solo #24" or something, or like 100 separate vocal recordings. It was insane. Nonetheless, with everything being mixed already, every new melody only had to be programmed, which saved a lot of time :)</p>

<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/nightmare_flp_screenshot.webp" style="display: block; margin: auto; width: 100%;" />

<p>Let's talk about the other instruments. The instance of 3xOsc isn't remarkable. I used it for risers, because risers are trivially easy to make with sliding notes. But only internal FL Studio synths support sliding notes. Maybe if I would've been less lazy, I could've made some really sick risers with the Polybrute.</p>

<p>Pianoteq isn't remarkable either. It's a good sounding piano, with the benefit that it doesn't clog up my computer with piano samples. I don't care much about 100% authenticity. It sounds like a piano, as such the small size is a big plus. In case you are interested in specifics, I used Pianoteq 7 with the Grand C. Bechtstein DG piano.</p>

<p>The choir isn't remarkable either. It literally is the "Choir Ahh" preset of DirectWave. It doesn't sound good, but it doesn't sound particularly bad either. Again, I don't care about 100% authenticity. It sounds like a choir, and as such it is sufficient.</p>

<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/choir.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>But you know what also isn't remarkable?</p>

<h2>My terrible singing</h2>

<p>In the middle of January, I bought some acoustic material! To kill the awful awful reverberation in my studio. I don't own much furniture, that you would find in the typical home. No couch, no cupboards, no bookshelves. Just a desk, a computer and audio equipment. As such, the acoustics in my room were absolutely terrible. The reverb was around 5 seconds long, which is quite amazing, when you consider how small my room actually is &#128584;</p>

<p>But I did my homework, and I know that gluing things on my walls is more damaging in the long run. So instead, I bought (stupidly expensive) general absorbers that can be mounted on microphone stands. If you were to permanently install acoustics, you can get much more and better stuff for a couple of bucks. If you are a DIY person, you can also build absorbers yourself, which apparently is very easy. Building them yourself is even cheaper than the cheapest stuff you can buy. But I'd cut myself even just thinking about using power tools.</p>

<p>But the garbage I bought has the obvious benefit that I can move them around. A recording booth on the go. Even though the acoustics in my studio are now much better, I still have my PC in my studio, which my microphone picks up. So, instead I simply moved the absorbers into my bedroom and recorded my vocals there :D</p>

<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/vocal_booth.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<p>During the making of the first song "02 Insecurities", I didn't have these absorbers yet. Instead, I sang into my closet. If you pay attention, you can actually hear it. It sounds like I am singing into a wooden box :P</p>

<p>But thanks to the absorbers, in "04 Chasm Pt2" and "05 Nightmare", the acoustics are much more clean. As clean as the recordings are though, I still hate how my singing voice sounds. I never practiced singing, so that's probably the biggest problem here. Nevertheless, to "fix" it in the last part of "05 Nightmare", I've put heavy EQ and a bit crusher on top, so now it sounds like I am singing through a telephone. In retrospect, going to all the effort to get squeaky clean recordings, just to ruin them with effects after, was a big waste of money. Oh well, at least with these absorbers randomly standing around in my studio makes me feel like a professional now &#175;&#92;&#95;&#40;&#12484;&#41;&#95;&#47;&#175;</p>

<p>With the acoustics taken care of, now I only had to actual sing. I simply programmed a piano to play the melody I wanted to sing. As a metronome, I used the 909 hi-hats, and that's it. Something like this:</p>

<audio controls style="display: block; margin: auto;">
  <source src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/nightmare_solo_2.mp3" type="audio/mpeg">
  Your browser does not support mp3 &#128546;
</audio>

<p>You can hear how crude it is. I even have the metronome lasting for much longer than was actually needed &#128584;, but it does its job. I had one of these tracks for every part I wanted to sing. I downloaded them to my mobile phone, and listened to them with headphones.</p>

<p>For the last solo, where I actually wanted to sing lyrics, I had to plan out the words and how they fit with the melody. I did a lot of experimenting, writing down the lyrics in a word document and programming a piano parallel to it. I needed like 2 weeks to get the lyrics done. Once I was happy with them, I printed them out for quick reference. That's the sheet of paper lying on the drying rack, in the photo above.</p>

<p>Finally, I had to mix them, which wasn't that hard honestly. EQ, compression, reverb, the telephone effects. I don't want to pretend that I am a good singer, so be rest assured that I used autotune. (In the industry, we actually call it "pitch correction", and FL Studio calls it Newtone.)</p>

<h2>Sampled quotes</h2>

<p>In "02 Insecurities" and "04 Chasm Pt2" I definitely sampled what other people were saying. Did I breach copyright? Possibly. Do I care? No. I have little respect for copyright, much less of big companies abusing it. I won't write an essay about abolishing copyright law, but if you are interested from where I am coming from, <a href="https://youtu.be/MAFUdIZnI5o" target="_blank" rel="noopener noreferrer">here</a> is a detailed take.</p>

<p>Okay, opinions about copyright aside, I am actually going to credit where I got the samples from. The first quote is from John Carmack, on an Interview with Lex Friedman. Carmack is a legendary programmer. He is the founder of id Software and he is probably most famous for being the programmer behind Doom, the original from 1993.</p>

<p>The second quote is from Brian Karis. He is the lead developer behind Nanite, the feature in Unreal Engine 5, which generates LODs at runtime. I actually only learned of his existence because of Nanite. But considering how stupidly impressive Nanite is, this dude got brains.</p>

<p>The third quote is by a man which I honestly don't know. I've come across this clip of his on Reddit some time ago. I kinda vibed with it, with the insanity and determinedness behind the voice. Though I had to alter the audio quite a lot, removing the censored bleeps and rearranging it into something more coherent.</p>

<p>Also also, I really want to credit all the ideas I stole. I am mentioning it, because there is a high chance you missed it, but the melody in "04 Chasm Pt2", which is played at the same time as the enraged man rants, is not mine. It's from Undertale by Toby Fox. More specifically the song "But the Earth Refused to Die".</p>

<p>All other references and similarities are pure coincidence, or simply because I included them unconsciously. Pure originality doesn't exist anyway.</p>

<ul>
<li>John Carmack: <a href="https://youtu.be/I845O57ZSy4?t=18426" target="_blank" rel="noopener noreferrer">https://youtu.be/I845O57ZSy4?t=18426</a></li>
<li>Brian Karis: <a href="https://youtu.be/NRnj_lnpORU?t=2933" target="_blank" rel="noopener noreferrer">https://youtu.be/NRnj_lnpORU?t=2933</a></li>
<li>Enraged man: <a href="https://redd.it/sj210o" target="_blank" rel="noopener noreferrer">https://redd.it/sj210o</a></li>
<li>Toby Fox – But the Earth Refused to Die: <a href="https://youtu.be/ML6OV8fG74w" target="_blank" rel="noopener noreferrer">https://youtu.be/ML6OV8fG74w</a></li>
</ul>

<h2>Thumbnail</h2>

<p>To say it bluntly, the cover art was generated by AI. Specifically: I used DALL·E for the job. Unlike previous albums, I had absolutely no ideas for a cover. So I threw some keywords at DALL·E and watched it go.</p>

<p>First I tried "drum and bass album cover, black noise", but I really hated that DALL·E tried to put text on the cover. Even specifically adding "without text" to the prompt, DALL·E just couldn't help itself to add text.</p>

<p>Then I tried "black digital noise" and later specified it to "corrupt noise, gloomy athmosphere, without color, abstract, cartoonish". While generating super cool textures, it didn't scratch my itch and thus I threw the idea out of the window.</p>

<p>My third attempt was "speaker of a subwoofer, distorted, high contrast perlin noise, cell shaded 3d graphics", but I didn't like these, because they were too basic.</p>

<p>But then I hit gold, once I used the prompt "the world through the eyes of a schizophrenic person, in black and white", and beside the two creepy looking people, the other two pictures really hit the nail on its head. It was a really close call between the dude with the missing head and that distorted forest, but ultimately ended choosing the forest, because the missing head was a little to depressing for me.</p>

<p>Below is a selection of the thumbnails I generated. I left some out, due to them being very similar to the ones you already see here.</p>

<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.57.30 - drum and bass album cover, black noise.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.58.03 - drum and bass album cover, black noise.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.58.21 - drum and bass album cover, black noise, without text.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.58.25 - drum and bass album cover, black noise, without text.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.58.32 - black digital noise.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.58.42 - black digital noise.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.58.45 - black digital noise.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.58.47 - black digital noise.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.58.59 - corrupt noise, gloomy athmosphere, without color, abstract, cartoonish.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.59.02 - corrupt noise, gloomy athmosphere, without color, abstract, cartoonish.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.59.04 - corrupt noise, gloomy athmosphere, without color, abstract, cartoonish.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.59.12 - corrupt noise, gloomy athmosphere, without color, abstract, cartoonish.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.59.28 - speaker of a subwoofer, distorted, high contrast perlin noise, cell shaded 3d graphics.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.59.31 - speaker of a subwoofer, distorted, high contrast perlin noise, cell shaded 3d graphics.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.59.33 - speaker of a subwoofer, distorted, high contrast perlin noise, cell shaded 3d graphics.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.59.36 - speaker of a subwoofer, distorted, high contrast perlin noise, cell shaded 3d graphics.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.59.41 - the world through the eyes of a schizophrenic person, in black and white.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.59.45 - the world through the eyes of a schizophrenic person, in black and white.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.59.48 - the world through the eyes of a schizophrenic person, in black and white.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />
<img src="https://www.rismosch.com/articles/how-i-made-the-world-between-my-mind-and-reality/DALL·E 2023-03-10 19.59.52 - the world through the eyes of a schizophrenic person, in black and white.webp" style="display: inline-block; margin: auto; width: 190px; max-width: 100%;" />

<p>I was quite lucky actually, getting very good results on my 4th attempt or so. For example, the thumbnail for <a href="https://www.rismosch.com/assets/thumbnails/ris_engine.webp" target="_blank" rel="noopener noreferrer">my engine</a> required lots and lots of trial and error. I spent like 3/4 of my credits for colorful engine pictures, but only like 5 for my album :P</p>

<p>Up until this point, the album also didn't have a name yet. After seeing the headless dude and the forest, I stumbled onto "The World Between My Mind And Reality". I think it fits :)</p>

<h2>Miscellaneous</h2>

<p>Finally, let's talk about some miscellaneous stuff. Things that I want to mention, but for one reason or another could not or simply didn't want to put in any category above. So let's go:</p>

<p>The big swell in the beginning is a simple Piano key stroke, but with many many effects on top of it. So many in fact, that it generates these interesting noisy artifacts.</p>

<p>The organ sound in Chasm Pt1 and 2. That is 100% the Polybrute. I used modulated noise to generate the wind sound effect. With the longest possible release on the VCA envelope, such that the noise can ring out. But to stop the VCO when a key isn't pressed anymore, I used the MOD envelope to modulate the VCO mixer.</p>

<p>That sound after John Carmack and Brian Karis, is the Polybrutes delay effect. If you don't play any sound, and put the feedback of the delay up to 100%, the noise floor eventually gets so loud that you can hear it. Once it's at maximum loudness, turn down the delay time to get that pitch shift. Once I recorded it, I only had to correct its pitch, such that it is in tune with the rest of the song.</p>

<p>The first song "02 Insecurities" is never silent. I recorded the ambient noise of my PC and placed it into the song. In the later songs I didn't do that, because first, the organ sound is noisy enough already. And second, the last song "05 Nightmare" has so much sound stacked on top each other, that it was practically meaningless.  I wanted the silent parts in it to really be silent.</p>

<h2>Conclusion</h2>

<p>And there we have it. Now obviously, I didn't go into much detail, like how I mixed and the exact plugins I used, because quite frankly, I find that boring. And honestly, at the end of the day, mixing is more decision making. If you want to learn mixing, you probably should watch <a href="https://www.youtube.com/c/DanWorrall" target="_blank" rel="noopener noreferrer">Dan Worrall</a> instead.</p>

<p>As for what the album means and what I want to say with it, eh. It is what it is. <a href="https://en.wikipedia.org/wiki/The_Death_of_the_Author" target="_blank" rel="noopener noreferrer">Death of the Author</a> or what have you. I let the art speak for itself.</p>

]]></content:encoded></item><item><title>Building a JobSystem</title><link>https://www.rismosch.com/article?id=building-a-job-system</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">building-a-job-system</guid><pubDate>Thu, 06 Oct 2022 09:46:08 +0200</pubDate><description>The latest feature of my gameengine is thread pool, which uses all CPU resources all of the time. In this blogpost I go into the deisgn of this first working prototype.</description><content:encoded><![CDATA[<p>If the hero were the phrase <i>"premature optimization is the root of all evil"</i>, then I'd be its villain. I might be an uninteresting and boring villain, but its villain nonetheless.</p>

<p>Anyway, there is one idea that really caught me on fire, ever since I first came across it. Pretty much most game engines that you will come across, as well as any tutorials that may claim to teach you how to program one, they all hinge on the same basic, single threaded main loop.</p>

<img src="https://www.rismosch.com/articles/building-a-job-system/single_threaded_gameloop.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>This is fine, until you realize that today's machines have multiple processors. If the entire engine runs only on one thread, then no matter how many cores your processor has, only the speed of one actually determines how fast your game is running.</p>

<video loop="true" autoplay="autoplay" muted="true" style="max-width:100%; display: block; margin: auto;" loading='lazy'>
<source src="https://www.rismosch.com/articles/building-a-job-system/multithreading_meme.mp4" type="video/mp4">
</video>

<p>Na&#239;ve me, and multiple people that I've seen online, all seem to come to the same idea eventually: Simply divide the engine into different threads! For example, have one thread that runs the input and logic, and have another thread that runs the output. But this is not an ideal solution. One job will be more expensive than the other. Either the logic, or the output (most definitely the rendering) will take a larger amount of time to compute. So to have things synced up properly, one must wait for the other, wasting CPU cycles. To solve this, maybe you think you simply have to divide the engine into even more threads. But this becomes very complicated very quickly, with diminishing returns.</p>

<p>No. What I want is what Jason Gregory proposes in his book "Game Engine Architecture": A Job System.</p>

<p>The idea doesn't sound so difficult at the first glance: You spawn a thread for every available core. You have a queue where you can push jobs to. The worker threads then constantly try to dequeue jobs from it, and run them. A job is simply a piece of code, usually a pointer to a function. The potential of this idea is huge: In the best case, it gives you access to 100% of the CPU 100% of the time. Sure, we need additional job system logic, which overall is more work. But since we can do multiple things at once, this overhead is definitely worth the effort, and reduces the computation time in total.</p>

<h2>Thread Pool Theory</h2>

<p>One of the best books about programming I've ever read, is "C++ Concurrency in Action" by Anthony Williams. Even though I made the <a href="https://www.rismosch.com/article?id=crisis" target="_blank" rel="noopener noreferrer">switch to Rust a few months ago</a>, the book was still immensely helpful for understanding and designing multithreaded stuff. And the job system that I've implemented is inspired by the thread pool that Anthony proposed in his book. So before we dig into my spaghetti code, it's probably a good idea to first understand how a thread pool works. By that I mean, we'll go and look at Anthony's thread pool.</p>

<h3>Na&#239;ve Thread Pool</h3>

<p>In the most na&#239;ve way possible, a thread pool is fairly easy to implement: Have one concurrent queue and share it among every worker thread.</p>

<img src="https://www.rismosch.com/articles/building-a-job-system/naive_system.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>This is primitive, but it should work. Nonetheless, this design has a huge problem: Congestion. This na&#239;ve solution has multiple threads that are all constantly trying to dequeue jobs from the job queue. This means that the queue must be absolutely thread safe. This begs the question, how does something become thread safe? Simply put, it prevents simultaneous accesses from different threads. There are various techniques to accomplish this. There exist blocking and non-blocking methods, but ultimately, a thread safe object turns multithreaded accesses into "single threaded" ones. (My explanation isn't quite correct, concurrent accesses on a thread safe object still happen on different threads. But since all accesses happen in order and never at the same time, they may as well be single threaded. You get my point.) This is a huge huge problem, because we wanted a system that could run things in parallel, and now this queue alone is preventing that entirely.</p>

<p>To fix this, we somehow need to avoid threads attempting to access the same data. Luckily, I don't have to be smart to figure this one out, and Anthony proposes a better solution.</p>

<h3>Local Job Buffers</h3>

<p>The key thing to realize, is that jobs can submit other jobs. Jobception. If we enqueue these to the shared job queue, we have an even bigger congestion problem. No. Instead, each worker thread has its own job queue, where it can submit and dequeue jobs.</p>

<img src="https://www.rismosch.com/articles/building-a-job-system/local_buffers.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>Now, a worker thread only attempts to dequeue from the global job queue, if its own local queue is empty. Also notice that only the worker thread has access to its queue, so the queue doesn't even need to be thread safe!</p>

<p>This is a much better solution, but it is still prone to problems. Imagine again that we have a logic job and an output job, that are both submitted to this job system. One worker may receive the logic job, and another receives the output job. Since jobs can push other jobs, and these are enqueued to the local buffer, logic jobs will always stay on thread A, while render jobs will always stay on thread B. But just like before, one job is much more expensive than the other one. And even though we have enough jobs for everyone, because they never leave their worker thread, we get this situation again:</p>

<video loop="true" autoplay="autoplay" muted="true" style="max-width:100%; display: block; margin: auto;" loading='lazy'>
<source src="https://www.rismosch.com/articles/building-a-job-system/multithreading_meme.mp4" type="video/mp4">
</video>

<p>Anthony comes to the rescue one more time!</p>

<h3>Stealing Jobs</h3>

<p>The final design proposes that every worker thread actually has a reference to the local queues of the other threads, such that workers may <i>steal</i> jobs from each other.</p>

<img src="https://www.rismosch.com/articles/building-a-job-system/steal_buffers.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>This implies that the local job queues must be thread safe again. Also, we stop talking about queues, and more about buffers. More precisely, a deque. If the container that holds the jobs where a simple queue, we would run into the congestion problem again. But to allow for maximum parallel work, jobs are pushed and popped from the same end of the buffer, while stealing is done from the opposite end. This ensures that even though multiple threads access the same buffer, they happen at different locations on the buffer, so stealing and popping can happen simultaneously. The only way we could run into congestion, is if the buffer were empty. But in this edge case we simply don't care, because what is a worker thread going to do if it is empty? Wait? Since there isn't anything to do anyway, we can absolutely afford to congest.</p>

<img src="https://www.rismosch.com/articles/building-a-job-system/deque.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>While a bit more complicated, this solution is much more sophisticated. Full credit to Anthony. And it is this thread pool, which I decided to build upon.</p>

<h2>My Job System</h2>

<p>Now that we have a basic understanding of how a sophisticated job system looks like, let me present you my altered version. In total, my system is built from 5 parts, which we will tackle in order:</p>

<ol>
<li><b>Job.</b>&nbsp;&nbsp;Simple wrapper around a function pointer. Until I figure out how to store function pointers in a collection, a wrapper is required.</li>

<li><b>JobBuffer.</b>&nbsp;&nbsp;Buffer that holds Jobs. It isn't really a queue, neither is it really a deque, it's more akin to a weird stack, but at the same time it isn't. It's specially designed for this job system, and isn't even thread safe if used incorrectly, but we'll talk about it later.</li>

<li><b>JobSystem.</b>&nbsp;&nbsp;Collection of globally available functions, to setup worker threads, submit jobs and run pending jobs.</li>

<li><b>JobFuture.</b>&nbsp;&nbsp;Utility to wait and return values from jobs.</li>

<li><b>JobCell.</b>&nbsp;&nbsp;Utility, to pass references into a job. Rusts ownership rules made this absolutely necessary and a real headache to design.</li>
</ol>

<p>Without further ado, let's jump into some Rust code &#128522;</p>

<h2>Job</h2>

<p>As stated above, I honestly don't know how to store function pointers in a container elegantly. In Rust, every function is unique. Even if two functions were to have the same signature, they are still considered different from each other. Thus, such two similar functions cannot be stored in the same collection, unless you put them into some sort of wrapper. To make my life easier, I simply created a wrapper that stores a single function pointer. Since every <code class="code">Job</code> is syntactically the same, they can be effortlessly stored in a container.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">pub struct <span style="color:var(--pico-8-washed-grey)">Job</span> {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;to_invoke: <span style="color:var(--pico-8-washed-grey)">Option</span><<span style="color:var(--pico-8-washed-grey)">Box</span><<span style="color:var(--pico-8-cyan)">dyn</span> <span style="color:var(--pico-8-washed-grey)">FnOnce()</span>>>,<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">impl <span style="color:var(--pico-8-washed-grey)">Job</span> {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">new</span><<span style="color:var(--pico-8-washed-grey)">F</span>: <span style="color:var(--pico-8-washed-grey)">FnOnce</span><span style="color:var(--pico-8-green)">()</span> + <span style="color:var(--pico-8-cyan)">'static</span>><span style="color:var(--pico-8-green)">(</span>to_invoke: <span style="color:var(--pico-8-washed-grey)">F</span><span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-cyan)">Self</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> to_invoke: <span style="color:var(--pico-8-washed-grey)">Option</span><<span style="color:var(--pico-8-washed-grey)">Box</span><<span style="color:var(--pico-8-cyan)">dyn</span> <span style="color:var(--pico-8-washed-grey)">FnOnce</span><span style="color:var(--pico-8-brown)">()</span>>> = <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-brown)">(</span><span style="color:var(--pico-8-washed-grey)">Box</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-cyan)">(</span>to_invoke<span style="color:var(--pico-8-cyan)">)</span><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">Self</span> <span style="color:var(--pico-8-brown)">{</span> to_invoke <span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)"><u>invoke</u></span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">mut <u>self</u></span><span style="color:var(--pico-8-green)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-brown)">(</span>to_invoke<span style="color:var(--pico-8-brown)">)</span> = <span style="color:var(--pico-8-cyan)"><u>self</u></span>.to_invoke.<span style="color:var(--pico-8-brown)"><u>take</u>() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to_invoke<span style="color:var(--pico-8-cyan)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Debug</span> <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">Job</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">fmt</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span>, <u>f</u>: &<span style="color:var(--pico-8-cyan)">mut</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Formatter</span><span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">fmt</span>::<span style="color:var(--pico-8-washed-grey)">Result</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> result = <span style="color:var(--pico-8-pink)">match</span> <span style="color:var(--pico-8-cyan)">self</span>.to_invoke <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span>_<span style="color:var(--pico-8-cyan)">)</span> => <span style="color:var(--pico-8-brown)">"Some"</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">None</span> => <span style="color:var(--pico-8-brown)">"None"</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">write!</span><span style="color:var(--pico-8-brown)">(</span><u>f</u>, <span style="color:var(--pico-8-brown)">"{{ to_invoke: <span style="color:var(--pico-8-cyan)">{}</span> }}"</span>, result<span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
</code>

<p>To be able to invoke the function pointer, it is stored in an <code class="code">Option</code>, such that when calling it, we can take ownership of it. It should go without saying, that this <code class="code">Job</code> can only be invoked once, because once we moved the function pointer out of <code class="code">Option</code>, there is no function pointer left.</p>

<h2>JobBuffer</h2>

<p>There is one thing that you must know, when designing interfaces for thread safe constructs: The more flexible the public interface, the more race conditions you introduce. While impractical, assume the following example: A worker thread only wants to pop jobs of the buffer, if they are for example render jobs. To program something like this, you would have a peak method, that checks the next job without popping it off the buffer. The caller then can check the job. If it's the right kind, pop it. Client code would look something like this:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">let</span> job = <span style="color:var(--pico-8-cyan)">job_system</span>::<span style="color:var(--pico-8-brown)">peak()</span>;<br>
<span style="color:var(--pico-8-pink)">if</span> job.kind == <span style="color:var(--pico-8-washed-grey)">JobKind</span>::Render <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> render_job = <span style="color:var(--pico-8-cyan)">job_system</span>::<span style="color:var(--pico-8-brown)">pop()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;render_job.<span style="color:var(--pico-8-brown)">invoke()</span>;<br>
<span style="color:var(--pico-8-green)">}</span>
</code>

<p>This code would be fine in a single threaded context, but this introduces a race condition. Between <code class="code">job_system::peak()</code> and <code class="code">job_system::pop()</code>, another thread may pop off a job. Thus, even though the if-statement may be <code class="code">true</code>, a different job is popped off than what was peaked at. This means, <code class="code">render_job</code> may actually not be a render job.</p>

<p>The simple solution is to keep your interface to an absolute minimum. Besides its constructor, my job buffer only exposes 3 methods: Push, pop and steal. Peaking and indexing are not implemented, because they cause race conditions and aren't used by my system.</p>

<p>An iterator may be helpful, but iterators are notoriously difficult to make thread safe. Whatever mechanism you use to prevent other threads to access your collection, it somehow must live at least as long as the iterator. This introduces many difficult questions, like who owns the locking mechanism, or how to sync it with the iterator? It's probably best to just not implement it.</p>

<p><code class="code">is_empty()</code> may be useful, and I even have the use case for it, but ultimately it's redundant. Because <code class="code">steal()</code> and <code class="code">pop()</code> can simply return <code class="code">None</code> when no job exists, <code class="code">is_empty()</code> provides truly redundant information.</p>

<p><code class="code">count</code> or <code class="code">length</code> are also useless: Either there are jobs in the buffer that can be popped off, or there are none. There will never be a case, where I would want to know how many jobs are currently stored in the buffer.</p>

<br><br>

<p>It should become a bit clearer now, why I am calling it a buffer, and not queue, deque or stack. It is lacking seriously in features. Also, it isn't technically a queue, nor stack, because jobs can be popped from both sides. It isn't a deque either, because it can push only from one side.</p>

<p>Okay, that were a lot of preambles, but how to actually build such a thing? Hang in there, we gotta talk collections first. We will see code soon enough.</p>

<br><br>

<p>I was quite surprised how many different designs there are. I went through at least 10 different prototypes before I landed on the buffer that I am currently using. Initially, I wanted to write a doubly linked list. Those come with a hefty number of drawbacks and they are stupidly difficult to write in Rust. But I wanted one, because it can hold infinite items in theory. When a buffer is full, and a job is pushed, what should happen? For a long time, I didn't want to answer this question, hence I was only considering a buffer with theoretical infinite size.</p>

<p>But eventually, while going for a walk, I realized something: When a buffer is full, I can simply invoke the job. The caller shouldn't care whether the submit function blocks or not. All that matters is that the job system is making progress <i>somehow</i>. If the caller needs to be interrupted to invoke another job, then this is totally fine. Even though the caller may not make progress, another job will be, therefore no resources are wasted.</p>

<img src="https://www.rismosch.com/articles/building-a-job-system/friendship_ended.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>My choice to implement the <code class="code">JobBuffer</code> fell onto the ring buffer. A ring buffer is just an array or vector, with one or two cursors, keeping track where the current head and tail are. It's called a ring buffer, because the cursors wrap around the array, thus it effectively has no start and end, like a ring. Once allocated, no further allocations are necessary to use it. Also, no nasty pointer issues arise. And to top it all off, a ring buffer can be entirely coded in safe Rust, which is always a big bonus.</p>

<p>To familiarize yourself with it, here's a simple playground I've built in JavaScript, where you can familiarize yourself with the concept:</p>

<noscript>&#129299; <i>actually, you have to enable JavaScript, if you want to play on the playground</i> &#129299;</noscript>

<div id="ring_buffer_playground" style="display:none; width:300px; margin:auto; border: 5px solid var(--pico-8-cyan); background-color: var(--pico-8-white);">

<div style="display:block; padding: 5px;">
    <input id="ring_buffer_playground_input" type="text" value="input" style="margin-bottom: 1.3em;font-family: Arial, sans-serif;font-size: 1em;background-color: var(--pico-8-white); width: 200px;">
    <button onclick="playground_push()">push</button>
</div>

<table id="ring_buffer_playground_table">
    <tr>
        <td id="ring_buffer_playground_head_0" class="ring_buffer_playground_head">head</td>
        <td id="ring_buffer_playground_cell_0" class="ring_buffer_playground_cell"></td>
        <td id="ring_buffer_playground_tail_0" class="ring_buffer_playground_tail">tail</td>
    </tr>
    <tr>
        <td id="ring_buffer_playground_head_1" class="ring_buffer_playground_head ring_buffer_invisible">head</td>
        <td id="ring_buffer_playground_cell_1" class="ring_buffer_playground_cell"></td>
        <td id="ring_buffer_playground_tail_1" class="ring_buffer_playground_tail ring_buffer_invisible">tail</td>
    </tr>
    <tr>
        <td id="ring_buffer_playground_head_2" class="ring_buffer_playground_head ring_buffer_invisible">head</td>
        <td id="ring_buffer_playground_cell_2" class="ring_buffer_playground_cell"></td>
        <td id="ring_buffer_playground_tail_2" class="ring_buffer_playground_tail ring_buffer_invisible">tail</td>
    </tr>
    <tr>
        <td id="ring_buffer_playground_head_3" class="ring_buffer_playground_head ring_buffer_invisible">head</td>
        <td id="ring_buffer_playground_cell_3" class="ring_buffer_playground_cell"></td>
        <td id="ring_buffer_playground_tail_3" class="ring_buffer_playground_tail ring_buffer_invisible">tail</td>
    </tr>
    <tr>
        <td id="ring_buffer_playground_head_4" class="ring_buffer_playground_head ring_buffer_invisible">head</td>
        <td id="ring_buffer_playground_cell_4" class="ring_buffer_playground_cell"></td>
        <td id="ring_buffer_playground_tail_4" class="ring_buffer_playground_tail ring_buffer_invisible">tail</td>
    </tr>
</table>

<div style="display:block; padding: 5px; width: 128px; margin:auto;">
    <button onclick="playground_pop()">pop</button>
    <button onclick="playground_steal()">steal</button>
</div>

<span style="background-color: var(--pico-8-white); border: 5px solid var(--pico-8-red); padding: 5px; width: 280px; display: block; overflow: hidden;" id="ring_buffer_playground_output">output</span>

</div>

<script>
let playground = document.getElementById("ring_buffer_playground");
let playground_input = document.getElementById("ring_buffer_playground_input");
let playground_output = document.getElementById("ring_buffer_playground_output");

playground.style.display="block";

let head = 0;
let tail = 0;

function playground_push() {
    let node = document.getElementById(`ring_buffer_playground_cell_${head}`);

    if (node.textContent.length === 0) {
        let to_push = playground_input.value;
        if (to_push.length === 0) {
            playground_output.textContent = "cannot push empty";
        } else {
            node.textContent = to_push;

            let old_head_cursor = document.getElementById(`ring_buffer_playground_head_${head}`);
            head = (head + 1) % 5;
            let new_head_cursor = document.getElementById(`ring_buffer_playground_head_${head}`);

            old_head_cursor.classList.add("ring_buffer_invisible");
            new_head_cursor.classList.remove("ring_buffer_invisible");

            playground_output.textContent = `pushed \"${to_push}\"`;
        }
    } else {
        playground_output.textContent = "buffer full";
    }
}

function playground_pop() {
    let new_head;
    if (head <= 0) {
        new_head = 4;
    } else {
        new_head = head - 1;
    }

    let node = document.getElementById(`ring_buffer_playground_cell_${new_head}`);

    if (node.textContent.length === 0) {
        playground_output.textContent = "buffer empty";
    } else {
        let popped = node.textContent;
        node.textContent = "";

        let old_head_cursor = document.getElementById(`ring_buffer_playground_head_${head}`);
        head = new_head;
        let new_head_cursor = document.getElementById(`ring_buffer_playground_head_${head}`);

        old_head_cursor.classList.add("ring_buffer_invisible");
        new_head_cursor.classList.remove("ring_buffer_invisible");

        playground_output.textContent = `popped \"${popped}\"`;
    }
}

function playground_steal() {
    let old_tail = tail;

    let node = document.getElementById(`ring_buffer_playground_cell_${old_tail}`);

    if (node.textContent.length === 0) {
        playground_output.textContent = "buffer empty";
    } else {
        let stole = node.textContent;
        node.textContent = "";

        let old_tail_cursor = document.getElementById(`ring_buffer_playground_tail_${tail}`);
        tail = (tail + 1) % 5;
        let new_tail_cursor = document.getElementById(`ring_buffer_playground_tail_${tail}`);

        old_tail_cursor.classList.add("ring_buffer_invisible");
        new_tail_cursor.classList.remove("ring_buffer_invisible");

        playground_output.textContent = `stole \"${stole}\"`;
    }
}
</script>



<p>We're finally done with the preamble, let's jump into code:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">pub struct <span style="color:var(--pico-8-washed-grey)">JobBuffer</span> {</span></br>
&nbsp;&nbsp;&nbsp;&nbsp;head: <span style="color:var(--pico-8-washed-grey)">UnsafeCell</span><<span style="color:var(--pico-8-washed-grey)">usize</span>>,</br>
&nbsp;&nbsp;&nbsp;&nbsp;tail: <span style="color:var(--pico-8-washed-grey)">Mutex</span><<span style="color:var(--pico-8-washed-grey)">usize</span>>,</br>
&nbsp;&nbsp;&nbsp;&nbsp;jobs: <span style="color:var(--pico-8-washed-grey)">Vec</span><<span style="color:var(--pico-8-washed-grey)">Mutex</span><<span style="color:var(--pico-8-washed-grey)">Option</span><<span style="color:var(--pico-8-washed-grey)">Job</span>>>,</br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>This is the entire struct. it stores the current head and tail, as well as a vector of jobs.</p>

<p>This definition may confuse you. Why is the head an <code class="code">UnsafeCell&lt;usize&gt;</code>? Why not a <code class="code">Mutex&ltusize&gt;</code>, like the tail? Why does the job vector also store mutexes? Isn't locking the head and tail safe enough?</p>

<p>Pushing and popping will happen on the head. Stealing will happen on the tail. I hope it should be fairly obvious why the tail needs to be a mutex. Multiple worker threads may steal from the same buffer. As such, the tail needs to be protected. Okay, but doesn't this also apply to the head? Well, no. Notice that only the worker thread that owns the buffer is pushing and popping jobs. Because a <i>single</i> thread is calling push and pop, there will never ever be the case, that <code class="code">push()</code> or <code class="code">pop()</code> will be called simultaneously. This means, as an optimization, we can simply leave the head unprotected. This is what I meant earlier, that this buffer isn't thread-safe, if you use it incorrectly. But since we aren't using it incorrectly, we are perfectly safe and sound.</p>

<p>Okay, but why do the items in the vector need to be protected? Doesn't that mean that we have to lock 2 mutexes to access a single entry? Yes, and that's one downside of this design. But till now, this didn't cause too much performance issues, so I am not worrying about it <i>yet</i>. While I can't get rid of this extra mutex, you should still understand why it is needed: When the buffer is full or empty, the tail and the head point to the same node, and thus two different threads may access the same node simultaneously. This needs to be prevented. We can't lock both head and tail, because that would mean if one thread were to call <code class="code">steal()</code>, a second thread cannot call <code class="code">pop()</code>. We want that 2 threads can work on the same buffer at the same time. Thus, the node itself must be stored within a mutex.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">JobBuffer</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span>capacity: <span style="color:var(--pico-8-washed-grey)">usize</span><span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-washed-grey)">Arc</span><<span style="color:var(--pico-8-cyan)">Self</span>> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>jobs</u> = <span style="color:var(--pico-8-washed-grey)">Vec</span>::<span style="color:var(--pico-8-brown)">with_capacity(</span>capacity<span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">for</span> _ <span style="color:var(--pico-8-pink)">in</span> <span style="color:var(--pico-8-green)">0</span>..capacity <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>jobs</u>.<span style="color:var(--pico-8-brown)"><u>push</u></span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">Mutex</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">None</span><span style="color:var(--pico-8-green)">)</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Arc</span>::<span style="color:var(--pico-8-brown)">new(</span><span style="color:var(--pico-8-cyan)">Self {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;head: <span style="color:var(--pico-8-washed-grey)">UnsafeCell</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(0)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tail: <span style="color:var(--pico-8-washed-grey)">Mutex</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(0)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jobs,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>The constructor should now be very straightforward. We create a vector with a fixed capacity, and insert empty nodes. Notice that we return an <code class="code">Arc&lt;Self&gt;</code>. This makes the client code a bit tidier, because this buffer is never used on its own, it will always be duplicated somehow.

</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">JobBuffer</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">push</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span>, job: <span style="color:var(--pico-8-washed-grey)">Job</span><span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-washed-grey)">Result</span><<span style="color:var(--pico-8-washed-grey)">()</span>, <span style="color:var(--pico-8-washed-grey)">BlockedOrFull</span>> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> <u>head</u> = <span style="color:var(--pico-8-cyan)">unsafe</span> <span style="color:var(--pico-8-brown)">{</span> &<span style="color:var(--pico-8-cyan)">mut</span> *<span style="color:var(--pico-8-cyan)">self</span>.head.<span style="color:var(--pico-8-brown)">get</span><span style="color:var(--pico-8-cyan)">()</span> <span style="color:var(--pico-8-brown)">}</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>node</u> = <span style="color:var(--pico-8-pink)">match</span> <span style="color:var(--pico-8-cyan)">self</span>.jobs<span style="color:var(--pico-8-brown)">[</span>*<u>head</u><span style="color:var(--pico-8-brown)">]</span>.<span style="color:var(--pico-8-brown)">try_lock() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-cyan)">(</span>node<span style="color:var(--pico-8-cyan)">)</span> => node,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">sync</span>::<span style="color:var(--pico-8-washed-grey)">TryLockError</span>::<span style="color:var(--pico-8-washed-grey)">WouldBlock</span><span style="color:var(--pico-8-cyan)">)</span> => <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">return</span> <span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">BlockedOrFull</span> <span style="color:var(--pico-8-brown)">{</span> not_pushed: job <span style="color:var(--pico-8-brown)">}</span><span style="color:var(--pico-8-green)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">sync</span>::<span style="color:var(--pico-8-washed-grey)">TryLockError</span>::<span style="color:var(--pico-8-washed-grey)">Poisoned</span><span style="color:var(--pico-8-green)">(</span>e<span style="color:var(--pico-8-green)">)</span><span style="color:var(--pico-8-cyan)">)</span> => <span style="color:var(--pico-8-cyan)">throw!(</span><span style="color:var(--pico-8-brown)">"mutex is poisoned: <span style="color:var(--pico-8-cyan)">{}</span>"</span>, e<span style="color:var(--pico-8-cyan)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> *<u>node</u> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span>_<span style="color:var(--pico-8-cyan)">)</span> => <span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">BlockedOrFull</span> <span style="color:var(--pico-8-green)">{</span> not_pushed: job <span style="color:var(--pico-8-green)">}</span><span style="color:var(--pico-8-cyan)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">None</span => <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<u>node</u> = <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-green)">(</span>job<span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<u>head</u> = <span style="color:var(--pico-8-green)">(</span>*<u>head</u> + <span style="color:var(--pico-8-green)">1)</span> % <span style="color:var(--pico-8-cyan)">self</span>.jobs.<span style="color:var(--pico-8-brown)">capacity</span><span style="color:var(--pico-8-green)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-green)">(<span style="color:var(--pico-8-brown)">()</span>)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>Push is a bit more complicated. Notice the unsafe block in the first line of this method. As I've explained earlier, this doesn't cause problems, because this will only ever be accessed by a single thread. We then lock the node at the current head. Notice how this is a <code class="code">try_lock</code>, not a <code class="code">lock</code>. This avoids blocking, meaning the job system can progress, even if the push failed. If we managed to lock the node, we can then see if there is a job inside or not. If there is a job already, the buffer is full. If there is no job, then we can overwrite it and update the head.</p>

<p>Note that the <code class="code">BlockedOrFull</code> error takes ownership of the job. This allows the not-pushed job to be returned to the caller, so that they may invoke it.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">JobBuffer</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">wait_and_pop</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-washed-grey)">Result</span><<span style="color:var(--pico-8-washed-grey)">Job</span>, <span style="color:var(--pico-8-washed-grey)">IsEmpty</span>> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> <u>head</u> = <span style="color:var(--pico-8-cyan)">unsafe</span> <span style="color:var(--pico-8-brown)">{</span> &<span style="color:var(--pico-8-cyan)">mut</span> *<span style="color:var(--pico-8-cyan)">self</span>.head.<span style="color:var(--pico-8-brown)">get</span><span style="color:var(--pico-8-cyan)">()</span> <span style="color:var(--pico-8-brown)">}</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> new_head = <span style="color:var(--pico-8-pink)">if</span> *<u>head</u> == <span style="color:var(--pico-8-green)">0</span> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">self</span>.jobs.<span style="color:var(--pico-8-brown)">capacity</span><span style="color:var(--pico-8-cyan)">()</span> - <span style="color:var(--pico-8-green)">1</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span> <span style="color:var(--pico-8-pink)">else</span> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<u>head</u> - <span style="color:var(--pico-8-green)">1</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>node</u> = <span style="color:var(--pico-8-cyan)">unwrap_or_throw!</span><span style="color:var(--pico-8-brown)">(</span><span style="color:var(--pico-8-cyan)">self</span>.jobs<span style="color:var(--pico-8-cyan)">[</span>new_head<span style="color:var(--pico-8-cyan)">]</span>.<span style="color:var(--pico-8-brown)">lock</span><span style="color:var(--pico-8-cyan)">()</span>, <span style="color:var(--pico-8-brown)">"mutex is poisoned")</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> <u>node</u>.<span style="color:var(--pico-8-brown)"><u>take</u>() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">None</span> => <span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">IsEmpty</span><span style="color:var(--pico-8-cyan)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span>job<span style="color:var(--pico-8-cyan)">)</span> => <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<u>head</u> = new_head;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-green)">(</span>job<span style="color:var(--pico-8-green)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>Pop is very similar, but the new head is computed first and then the node is locked. Note that it uses <code class="code">lock</code>, not <code class="code">try_lock</code>. A worker thread attempting to pop a job literally has nothing else to do. So to make progress, the best option is to block until we can access the node. Then, whether or not there is a job, we return the job or an <code class="code">IsEmpty</code> error.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">JobBuffer</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">steal</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-washed-grey)">Result</span><<span style="color:var(--pico-8-washed-grey)">Job</span>, <span style="color:var(--pico-8-washed-grey)">BlockedOrEmpty</span>> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> tail = <span style="color:var(--pico-8-cyan)">self</span>.tail.<span style="color:var(--pico-8-brown)">try_lock()</span>.<span style="color:var(--pico-8-brown)">map_err(to_steal_error)</span>?;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> old_tail = *<u>tail</u>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>node</u> = <span style="color:var(--pico-8-cyan)">self</span>.jobs<span style="color:var(--pico-8-brown)">[</span>old_tail<span style="color:var(--pico-8-brown)">]</span>.<span style="color:var(--pico-8-brown)">try_lock()</span>.<span style="color:var(--pico-8-brown)">map_err(to_steal_error)</span>?;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> <u>node</u>.<span style="color:var(--pico-8-brown)"><u>take</u>() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">None</span> => <span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">BlockedOrEmpty</span><span style="color:var(--pico-8-cyan)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span>job<span style="color:var(--pico-8-cyan)">)</span> => <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<u>tail</u> = <span style="color:var(--pico-8-green)">(</span>old_tail + <span style="color:var(--pico-8-green)">1)</span> % <span style="color:var(--pico-8-cyan)">self</span>.jobs.<span style="color:var(--pico-8-brown)">capacity</span><span style="color:var(--pico-8-green)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-green)">(</span>job<span style="color:var(--pico-8-green)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>Again, steal is very similar. But unlike the head in push and pop, the tail needs to be locked, because it is protected by a mutex. Notice how this one is using a <code class="code">try_lock</code> and not a <code class="code">lock</code>. This is due to there being <code class="code">number of CPUS - 1</code> amount of buffers to steal from. If we can't steal from this buffer, we simply steal from the next one. There is no need to block. After that, we then lock the node. If we were successful, we compute the next tail and return the job, otherwise we return an error.</p>

<p>At last, but not least, we need some utility stuff, so that this buffer compiles and can actually be shared between threads:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">unsafe impl</span> <span style="color:var(--pico-8-washed-grey)">Send</span> <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">JobBuffer</span> <span style="color:var(--pico-8-cyan)">{}</span><br>
<span style="color:var(--pico-8-cyan)">unsafe impl</span> <span style="color:var(--pico-8-washed-grey)">Sync</span> <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">JobBuffer</span> <span style="color:var(--pico-8-cyan)">{}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">to_steal_error</span><<span style="color:var(--pico-8-washed-grey)">T</span>><span style="color:var(--pico-8-green)">(</span>error: <span style="color:var(--pico-8-washed-grey)">TryLockError</span><<span style="color:var(--pico-8-washed-grey)">T</span>><span style="color:var(--pico-8-cyan)">)</span> -> <span style="color:var(--pico-8-washed-grey)">BlockedOrEmpty</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> error <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">sync</span>::<span style="color:var(--pico-8-washed-grey)">TryLockError</span>::<span style="color:var(--pico-8-washed-grey)">WouldBlock</span> => <span style="color:var(--pico-8-washed-grey)">BlockedOrEmpty</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">sync</span>::<span style="color:var(--pico-8-washed-grey)">TryLockError</span>::<span style="color:var(--pico-8-washed-grey)">Poisoned</span><span style="color:var(--pico-8-brown)">(</span>e<span style="color:var(--pico-8-brown)">)</span> => <span style="color:var(--pico-8-cyan)">throw!</span><span style="color:var(--pico-8-brown)">(</span><span style="color:var(--pico-8-brown)">"mutex is poisoned: <span style="color:var(--pico-8-cyan)">{}</span>"</span>, e<span style="color:var(--pico-8-brown)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
</code>

<p>And there we have it. A highly specialized buffer to store jobs.</p>

<p>This <code class="code">JobBuffer</code> is about 100 lines of code, but to test it I wrote 1180 lines! (including whitespaces)</p>

<p>This buffer is the core of my job system, which is the core of my game engine. So it must be <i>water tight</i>. I really can't afford this buffer to blow up, under any circumstance. As such, Anthony Williams recommended himself, to write as much tests as possible, to test every thinkable edge case, no matter how rare. What if one thread is pushing while another is stealing? What if 100 threads are stealing on an empty buffer? What if 1 thread is popping from an empty buffer? What if one thread is pushing and popping on a full buffer, while 100 threads are stealing?</p>

<p>But the painful, repetitive work was absolutely worth it. To this day, I haven't encountered a single issue with the <code class="code">JobBuffer</code>, and it's been 530 days, since its implementation. And I am quite confident that it does its job properly. <i>Maybe</i> I will encounter a bug in the future, but I seriously don't think I will encounter a serious problem, ever.</p>

<p style="color:var(--pico-8-dark-grey)"><i><b>Narrator:</b> The moment the buffer blows up, he will regret to have said this.</i></p>

<p><b>EDIT</b> 17th March, 2024. The system did, in fact, blow up:<br><a href="https://www.rismosch.com/article?id=i-found-a-bug-in-my-job-system" target="_blank" rel="noopener noreferrer">https://www.rismosch.com/article?id=i-found-a-bug-in-my-job-system</a></p>

<h2>JobSystem</h2>

<p>You may or may not have figured out, that the <code class="code">JobBuffer</code> described in the previous section is the local <code class="code">JobBuffer</code>, which is owned by a worker thread. What about the globally shared <code class="code">JobBuffer</code>? For better or for worse, I got rid of it.</p>

<p>Anthony Williams' thread pool seems fine, but I was always asking myself: Who is pushing onto the global buffer? I feel like Anthony's thread pool is designed for a general purpose. It most likely finds use in some enterprise project. Maybe a user is requesting a search or find feature, and then the program would initiate a thread pool to do just that. Maybe there will be additional threads that also push onto the thread-pool. Nonetheless, I really want to do what Naughty Dog did with their engine: Jobify the entire thing. EVERYTHING will run on this job system, with a few significant exceptions: Startup, shutdown, logging and IO. Everything that runs on the job system will push local jobs.</p>

<p>I also thought about who would own the main game loop. This too went through many different design iterations, but I realized soon enough that the main thread can also be a worker thread. The main thread can own a local <code class="code">JobBuffer</code> too, and it would execute a "GodJob", that lives for the entirety of the program. When the god job ends, it waits for all currently enqueued jobs. After all workers have been ended, the engine is allowed to shut down.</p>

<img src="https://www.rismosch.com/articles/building-a-job-system/startup_shutdown.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>Let's start with some structs:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">thread_local! {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">static</span> <span style="color:var(--pico-8-washed-grey)">WORKER_THREAD</span>: <span style="color:var(--pico-8-washed-grey)">RefCell</span><<span style="color:var(--pico-8-washed-grey)">Option</span><<span style="color:var(--pico-8-washed-grey)">WorkerThread</span>>> = <span style="color:var(--pico-8-washed-grey)">RefCell</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(<span style="color:var(--pico-8-washed-grey)">None</span>)</span>;<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">struct <span style="color:var(--pico-8-washed-grey)">WorkerThread</span> {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;local_buffer: <span style="color:var(--pico-8-washed-grey)">Arc</span><<span style="color:var(--pico-8-washed-grey)">JobBuffer</span>>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;steal_buffers: <span style="color:var(--pico-8-washed-grey)">Vec</span><<span style="color:var(--pico-8-washed-grey)">Arc</span><<span style="color:var(--pico-8-washed-grey)">JobBuffer</span>>>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;index: <span style="color:var(--pico-8-washed-grey)">usize</span>,<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">pub struct <span style="color:var(--pico-8-washed-grey)">JobSystemGuard</span> {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;handles: <span style="color:var(--pico-8-washed-grey)">Option</span><<span style="color:var(--pico-8-washed-grey)">Vec</span><<span style="color:var(--pico-8-washed-grey)">JoinHandle</span><<span style="color:var(--pico-8-green)">()</span>>>>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;done: <span style="color:var(--pico-8-washed-grey)">Arc</span><<span style="color:var(--pico-8-washed-grey)">AtomicBool</span>>,<br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>First, we have a thread local variable. It stores an <code class="code">Option</code>, because a thread that wasn't initialized as a worker thread cannot serve as a worker thread.</p>

<p>The <code class="code">WorkerThread</code> currently stores 3 things: The <code class="code">JobBuffer</code> that it owns, the <code class="code">JobBuffer</code>s from the other workers, and an index, that uniquely identifies this thread. The index is mainly used for debug purposes, and it's a utility that directly comes with my job system. As such, the index isn't linked to the platform, the OS, or anything of that nature.</p>

<p><code class="code">JobSystemGuard</code> is the struct that will be returned when the job system is initialized. If this guard is dropped, the job system will be shut down. Due to its singleton-like behavior, it didn't feel right to have a struct that represents the job system, similar of how you would design an OOP singleton. Instead, it gives the caller the opportunity to drop it at a specified time. The <code class="code">JobSystemGuard</code> stores all handles of every spawned worker thread, and an <code class="code">AtomicBool</code> to signal when worker threads should be shut down.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">init</span><span style="color:var(--pico-8-cyan)">(</span>buffer_capacity: <span style="color:var(--pico-8-washed-grey)">usize</span>, threads: <span style="color:var(--pico-8-washed-grey)">usize</span><span style="color:var(--pico-8-cyan)">)</span> -> <span style="color:var(--pico-8-washed-grey)">JobSystemGuard</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">// estimate workthreads and according affinities</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> cpu_count = <span style="color:var(--pico-8-brown)">cpu_info</span><span style="color:var(--pico-8-green)">()</span>.cpu_count <span style="color:var(--pico-8-cyan)">as</span> <span style="color:var(--pico-8-washed-grey)">usize</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> threads = <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">cmp</span>::<span style="color:var(--pico-8-brown)">min</span><span style="color:var(--pico-8-green)">(</span>cpu_count, threads<span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>affinities</u> = <span style="color:var(--pico-8-washed-grey)">Vec</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-pink)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">for</span> _ <span style="color:var(--pico-8-pink)">in</span> <span style="color:var(--pico-8-green)">0</span>..threads <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>affinities</u>.<span style="color:var(--pico-8-brown)"><u>push</u>(</span><span style="color:var(--pico-8-washed-grey)">Vec</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-cyan)">()</span><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">for</span> i <span style="color:var(--pico-8-pink)">in</span> <span style="color:var(--pico-8-green)">0</span>..cpu_count <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>affinities</u><span style="color:var(--pico-8-brown)">[</span>i % threads<span style="color:var(--pico-8-brown)">]</span>.<span style="color:var(--pico-8-brown)">push</u>(<span style="color:var(--pico-8-black)">i</span>)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">// setup job buffers</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>buffers</u> = <span style="color:var(--pico-8-washed-grey)">Vec</span>::<span style="color:var(--pico-8-brown)">with_capacity</span><span style="color:var(--pico-8-green)">(</span>threads<span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">for</span> _ <span style="color:var(--pico-8-pink)">in</span> <span style="color:var(--pico-8-green)">0</span>..threads <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>buffers</u>.<span style="color:var(--pico-8-brown)"><u>push</u>(</span><span style="color:var(--pico-8-washed-grey)">JobBuffer</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-cyan)">(</span>buffer_capacity<span style="color:var(--pico-8-cyan)">)</span><span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> done = <span style="color:var(--pico-8-washed-grey)">Arc</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">AtomicBool</span>::<span style="color:var(--pico-8-brown)">new(<span style="color:var(--pico-8-cyan)">false</span>)</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">// setup worker threads</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>handles</u> = <span style="color:var(--pico-8-washed-grey)">Vec</span>::<span style="color:var(--pico-8-brown)">with_capacity</span><span style="color:var(--pico-8-green)">(</span>threads - <span style="color:var(--pico-8-green)">1)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">for</span> <span style="color:var(--pico-8-green)">(</span>i, core_ids<span style="color:var(--pico-8-green)">)</span> <span style="color:var(--pico-8-pink)">in</span> <u>affinities</u>.<span style="color:var(--pico-8-brown)">iter</span><span style="color:var(--pico-8-green)">()</span>.<span style="color:var(--pico-8-brown)">enumerate</span><span style="color:var(--pico-8-green)">()</span>.<span style="color:var(--pico-8-brown)">take</span><span style="color:var(--pico-8-green)">(</span>threads<span style="color:var(--pico-8-green)">)</span>.<span style="color:var(--pico-8-brown)">skip</span><span style="color:var(--pico-8-green)">(1) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> core_ids = core_ids.<span style="color:var(--pico-8-brown)">clone()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> buffers = <span style="color:var(--pico-8-brown)">duplicate_buffers(</span>&<u>buffers</u><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> done_copy = done.<span style="color:var(--pico-8-brown)">clone()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>handles</u>.<span style="color:var(--pico-8-brown)"><u>push</u>(</span><span style="color:var(--pico-8-washed-grey)">thread</span>::<span style="color:var(--pico-8-brown)">spawn</span><span style="color:var(--pico-8-cyan)">(move</span> || <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">setup_worker_thread(</span>&core_ids, buffers, i<span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">run_worker_thread(</span>i, done_copy<span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><span style="color:var(--pico-8-cyan)">)</span><span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">ris_log</span>::<span style="color:var(--pico-8-cyan)">debug!</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-brown)">"spawned <span style="color:var(--pico-8-cyan)">{}</span> additional worker threads"</span>, <u>handles</u>.<span style="color:var(--pico-8-brown)">len()</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> handles = <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-green)">(</span><u>handles</u><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">// setup main worker thread (this thread)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> core_ids = <u>affinities</u><span style="color:var(--pico-8-green)">[0]</span>.<span style="color:var(--pico-8-brown)">clone</span><span style="color:var(--pico-8-green)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> buffers = <span style="color:var(--pico-8-brown)">duplicate_buffers</span><span style="color:var(--pico-8-green)">(</span>&<u>buffers</u><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">setup_worker_thread</span><span style="color:var(--pico-8-green)">(</span>&core_ids, buffers, <span style="color:var(--pico-8-green)">0)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">JobSystemGuard</span> <span style="color:var(--pico-8-green)">{</span> handles, done <span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>The <code class="code">init</code> method may look daunting at first, but it's actually very straight forward. It takes 2 values: The size of the <code class="code">JobBuffer</code>s and how many threads should be spawned. First, we clamp the threads to the number of processors that your machine has. This is to prevent spawning more threads than cores.</p>

<p>Then we calculate the affinities. Affinity allows you to lock a thread only to a specific core. For example, if a thread has affinity 0, 1 and 2, then it will run only on core 0, 1 and 2. Every worker thread should run on a different core, otherwise worker threads can interrupt each other, which may result in a performance loss.</p>

<p>Assume your PC has 12 cores. If you were to spawn 5 worker threads, my code would estimate the affinities like so:</p>

<table class="affinity_table">
    <tr>
        <td class="affinity_table_th">Thread</td>
        <td class="affinity_table_th">Affinity</td>
    </tr>
    <tr>
        <td class="affinity_table_td_left">0</td>
        <td class="affinity_table_td_right">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0, 5, 10</td>
    </tr>
    <tr>
        <td class="affinity_table_td_left">1</td>
        <td class="affinity_table_td_right">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1, 6, 11</td>
    </tr>
    <tr>
        <td class="affinity_table_td_left">2</td>
        <td class="affinity_table_td_right">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2, 7</td>
    </tr>
    <tr>
        <td class="affinity_table_td_left">3</td>
        <td class="affinity_table_td_right">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3, 8</td>
    </tr>
    <tr>
        <td class="affinity_table_td_left">4</td>
        <td class="affinity_table_td_right">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4, 9</td>
    </tr>
</table>

<p>After we've calculated the affinities, we simply create one <code class="code">JobBuffer</code> for every worker thread. We also create the <code class="code">done</code> flag.</p>

<p>Since the main thread is also a worker thread, we will be spawning <code class="code">threads - 1</code> number of workers. For each we clone the affinities, the buffers and the <code class="code">done</code> flag. Once spawned, each thread will first set itself up and then run itself.</p>

<p>Just right after that, the main thread is doing the same, but it also collects the handles and puts them into the <code class="code">JobSystemGuard</code>. The job system is now setup and already running!</p>

<p>Now let's see how it's dropped:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">impl <span style="color:var(--pico-8-washed-grey)">Drop</span> for <span style="color:var(--pico-8-washed-grey)">JobSystemGuard</span> {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)"><u>drop</u></span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">mut <u>self</u></span><span style="color:var(--pico-8-green)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">ris_log</span>::<span style="color:var(--pico-8-cyan)">debug!</span><span style="color:var(--pico-8-brown)">("dropping job system...")</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)"><u>self</u></span>.done.<span style="color:var(--pico-8-brown)">store(</span><span style="color:var(--pico-8-cyan)">true</span>, <span style="color:var(--pico-8-washed-grey)">Ordering</span>::<span style="color:var(--pico-8-washed-grey)">SeqCst</span><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">empty_buffer(<span style="color:var(--pico-8-green)">0</span>)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> <span style="color:var(--pico-8-cyan)"><u>self</u></span>.handles.<span style="color:var(--pico-8-brown)"><u>take</u>() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span>handles<span style="color:var(--pico-8-cyan)">)</span> => <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>i</u> = <span style="color:var(--pico-8-green)">0</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">for</span> handle <span style="color:var(--pico-8-pink)">in</span> handles <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>i</u> <u>+=</u> <span style="color:var(--pico-8-green)">1</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> handle.<span style="color:var(--pico-8-brown)">join() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-cyan)">(<span style="color:var(--pico-8-green)">()</span>)</span> => <span style="color:var(--pico-8-washed-grey)">ris_log</span>::<span style="color:var(--pico-8-cyan)">trace!(</span><span style="color:var(--pico-8-brown)">"joined thread <span style="color:var(--pico-8-cyan)">{}</span>"</span>, i<span style="color:var(--pico-8-cyan)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-cyan)">(</span>_<span style="color:var(--pico-8-cyan)">)</span> => <span style="color:var(--pico-8-washed-grey)">ris_log</span>::<span style="color:var(--pico-8-cyan)">fatal!(</span><span style="color:var(--pico-8-brown)">"failed to join thread <span style="color:var(--pico-8-cyan)">{}</span>"</span>, i<span style="color:var(--pico-8-cyan)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">None</span> => <span style="color:var(--pico-8-washed-grey)">ris_log</span>::<span style="color:var(--pico-8-cyan)">debug!(<span style="color:var(--pico-8-brown)">"handles already joined"</span>)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">ris_log</span>::<span style="color:var(--pico-8-cyan)">debug!</span><span style="color:var(--pico-8-brown)">("job system finished")</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>First, we set the <code class="code">done</code> flag to <code class="code">true</code>, so every worker thread knows it's time to stop. The main thread then empties its local buffer, meaning it is popping all jobs left in the buffer and running them. Then we take the <code class="code">handles</code>, and join each worker thread. With some logging thrown in, that's all that <code class="code">drop</code> does.</p>

<p>Let's take a look at all the utility functions, that the previous two code snippets were using:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">duplicate_buffers</span><span style="color:var(--pico-8-cyan)">(</span>buffers: &<span style="color:var(--pico-8-washed-grey)">Vec</span><<span style="color:var(--pico-8-washed-grey)">Arc</span><<span style="color:var(--pico-8-washed-grey)">JobBuffer</span>>>) -> <span style="color:var(--pico-8-washed-grey)">Vec</span><<span style="color:var(--pico-8-washed-grey)">Arc</span><<span style="color:var(--pico-8-washed-grey)">JobBuffer</span>>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>result</u> = <span style="color:var(--pico-8-washed-grey)">Vec</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">for</span> buffer <span style="color:var(--pico-8-pink)">in</span> buffers <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>result</u>.<span style="color:var(--pico-8-brown)"><u>push</u>(</span>buffer.<span style="color:var(--pico-8-brown)">clone<span style="color:var(--pico-8-cyan)">()</span>)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<u>result</u><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
</code>

<p>This method duplicates the array of <code class="code">JobBuffer</code>s, thus every worker thread can have a copy of all available buffers.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">fn <span style="color:var(--pico-8-brown)">setup_worker_thread</span>(</span>core_ids: &<span style="color:var(--pico-8-green)">[</span><span style="color:var(--pico-8-washed-grey)">usize</span><span style="color:var(--pico-8-green)">]</span>, buffers: <span style="color:var(--pico-8-washed-grey)">Vec</span><<span style="color:var(--pico-8-washed-grey)">Arc</span><<span style="color:var(--pico-8-washed-grey)">JobBuffer</span>>>, index: <span style="color:var(--pico-8-washed-grey)">usize</span><span style="color:var(--pico-8-cyan)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> <span style="color:var(--pico-8-washed-grey)">ris_os</span>::<span style="color:var(--pico-8-washed-grey)">affinity</span>::<span style="color:var(--pico-8-brown)">set_affinity</span><span style="color:var(--pico-8-green)">(</span>core_ids<span style="color:var(--pico-8-green)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-brown)">(<span style="color:var(--pico-8-cyan)">()</span>)</span> => <span style="color:var(--pico-8-washed-grey)">ris_log</span>::<span style="color:var(--pico-8-cyan)">trace!</span><span style="color:var(--pico-8-brown)">("set affinity <span style="color:var(--pico-8-cyan)">{:?}</span> for thread <span style="color:var(--pico-8-cyan)">{}</span>"</span>, core_ids, index<span style="color:var(--pico-8-brown)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-brown)">(</span>error<span style="color:var(--pico-8-brown)">)</span> => <span style="color:var(--pico-8-washed-grey)">ris_log</span>::<span style="color:var(--pico-8-cyan)">error!</span><span style="color:var(--pico-8-brown)">("couldn't set affinity for thread <span style="color:var(--pico-8-cyan)">{}</span>: <span style="color:var(--pico-8-cyan)">{}</span>"</span>, index, error<span style="color:var(--pico-8-brown)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> local_buffer = buffers<span style="color:var(--pico-8-green)">[</span>index<span style="color:var(--pico-8-green)">]</span>.<span style="color:var(--pico-8-brown)">clone</span><span style="color:var(--pico-8-green)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>steal_buffers</u> = <span style="color:var(--pico-8-washed-grey)">Vec</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">for</span> buffer <span style="color:var(--pico-8-pink)">in</span> buffers.<span style="color:var(--pico-8-brown)">iter</span><span style="color:var(--pico-8-green)">()</span>.<span style="color:var(--pico-8-brown)">skip</span><span style="color:var(--pico-8-green)">(</span>index + <span style="color:var(--pico-8-green)">1) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>steal_buffers</u>.<span style="color:var(--pico-8-brown)"><u>push</u>(</span>buffer.<span style="color:var(--pico-8-brown)">clone<span style="color:var(--pico-8-cyan)">()</span>)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">for</span> buffer <span style="color:var(--pico-8-pink)">in</span> buffers.<span style="color:var(--pico-8-brown)">iter</span><span style="color:var(--pico-8-green)">()</span>.<span style="color:var(--pico-8-brown)">take</span><span style="color:var(--pico-8-green)">(</span>index<span style="color:var(--pico-8-green)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>steal_buffers</u>.<span style="color:var(--pico-8-brown)"><u>push</u>(</span>buffer.<span style="color:var(--pico-8-brown)">clone<span style="color:var(--pico-8-cyan)">()</span>)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">WORKER_THREAD</span>.<span style="color:var(--pico-8-brown)">with</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-cyan)">move</span> |worker_thread| <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*worker_thread.<span style="color:var(--pico-8-brown)">borrow_mut</span><span style="color:var(--pico-8-cyan)">()</span> = <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">WorkerThread</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local_buffer,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;steal_buffers,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;index,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><span style="color:var(--pico-8-green)">)</span>;<br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>Setting up a worker thread is a bit more involved. First, we set the affinity. This is simply a wrapper around the Windows API, nothing special.</p>

<p>Then, we choose our local buffer. This is simply the buffer at the worker threads index. Meaning, the local buffer of thread 0 will be at index 0. The local buffer of thread 42 will be at index 42.</p>

<p>Using 2 for loops, we then get the buffers from which will be stolen from. We start at <code class="code">index + 1</code> and then wrap around. This diagram illustrates how the buffers will be arranged, for worker thread 2 on a machine with 5 cores:</p>

<img src="https://www.rismosch.com/articles/building-a-job-system/local_steal_buffers.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>After the busy work, we then simply set the thread-local variable with the necessary information.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">run_worker_thread</span> <span style="color:var(--pico-8-cyan)">(</span>index: <span style="color:var(--pico-8-washed-grey)">usize</span>, done: <span style="color:var(--pico-8-washed-grey)">Arc</span><<span style="color:var(--pico-8-washed-grey)">AtomicBool</span>><span style="color:var(--pico-8-cyan)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">while</span> !done.<span style="color:var(--pico-8-brown)">load</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">Ordering</span>::<span style="color:var(--pico-8-washed-grey)">SeqCst</span><span style="color:var(--pico-8-green)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">run_pending_job()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">empty_buffer</span><span style="color:var(--pico-8-green)">(</span>index<span style="color:var(--pico-8-green)">)</span>;<br>
<span style="color:var(--pico-8-washed-grey)">}</span>
</code>

<p>Running the worker thread is very straight forward. While the <code class="code">done</code> flag is <code class="code">false</code>, we are stuck in an endless loop, running jobs that are still waiting to be executed. If the <code class="code">done</code> flag is <code class="code">true</code>, we empty the buffer, like the main thread does when <code class="code">JobSystemGuard</code> is dropped.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">pub fn <span style="color:var(--pico-8-brown)">run_pending_job</span>() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> <span style="color:var(--pico-8-brown)">pop_job</span><span style="color:var(--pico-8-green)">() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-brown)">(</span><span style="color:var(--pico-8-cyan)">mut</span> <u>job</u><span style="color:var(--pico-8-brown)">)</span> => <u>job</u>.<span style="color:var(--pico-8-brown)"><u>invoke</u>()</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-brown)">(</span><span style="color:var(--pico-8-washed-grey)">IsEmpty</span><span style="color:var(--pico-8-brown)">)</span> => <span style="color:var(--pico-8-pink)">match</span> <span style="color:var(--pico-8-brown)">steal_job() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-cyan)">(mut</span> <u>job</u><span style="color:var(--pico-8-cyan)">)</span> => <u>job</u>.<span style="color:var(--pico-8-brown)"><u>invoke</u></span><span style="color:var(--pico-8-cyan)">()</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">BlockedOrEmpty</span><span style="color:var(--pico-8-cyan)">)</span> => <span style="color:var(--pico-8-washed-grey)">thread</span>::<span style="color:var(--pico-8-brown)">yield_now</span><span style="color:var(--pico-8-cyan)">()</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>To run a pending job, we first pop from our local buffer. If it is successful, we invoke it. If our local buffer is empty, we steal from the other buffers instead. If this is successful, we just stole a job and can invoke it. If no job was popped or stolen, we yield, to give room for other threads.</p>

<p><code class="code">run_pending_job()</code> is public, because as you will see in the sections <i>JobFuture</i> and <i>JobCell</i>, it is quite useful to let others run jobs as well.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">empty_buffer</span><span style="color:var(--pico-8-cyan)">(</span>index: <span style="color:var(--pico-8-washed-grey)">usize</span><span style="color:var(--pico-8-cyan)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">loop</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">ris_log</span>::<span style="color:var(--pico-8-cyan)">trace!</span><span style="color:var(--pico-8-brown)">("emptying <span style="color:var(--pico-8-cyan)">{}</span>"</span>, index<span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> <span style="color:var(--pico-8-brown)">pop_job() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-cyan)">(mut</span> <u>job</u><span style="color:var(--pico-8-cyan)">)</span> => <u>job</u>.<span style="color:var(--pico-8-brown)"><u>invoke</u></span><span style="color:var(--pico-8-cyan)">()</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">IsEmpty</span><span style="color:var(--pico-8-cyan)">)</span> => <span style="color:var(--pico-8-pink)">break</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>Emptying the local buffer is also very straight forward. We are stuck in a loop, popping jobs from our local buffer and running them, until it's empty.</p>

<p>Now we've seen several functions that pop and steal jobs. So now it's time to show what these functions are doing in detail:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">pop_job</span><span style="color:var(--pico-8-cyan)">()</span> -> <span style="color:var(--pico-8-washed-grey)">Result</span><<span style="color:var(--pico-8-washed-grey)">Job</span>, <span style="color:var(--pico-8-washed-grey)">IsEmpty</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>result</u> = <span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">IsEmpty</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">WORKER_THREAD</span>.<span style="color:var(--pico-8-brown)">with</span><span style="color:var(--pico-8-green)">(</span>|worker_thread| <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span><u>worker_thread</u><span style="color:var(--pico-8-cyan)">)</span> = worker_thread.<span style="color:var(--pico-8-brown)">borrow_mut</span><span style="color:var(--pico-8-cyan)">()</span>.<span style="color:var(--pico-8-brown)"><u>as_mut</u></span><span style="color:var(--pico-8-cyan)">() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>result</u> = <u>worker_thread</u>.local_buffer.<span style="color:var(--pico-8-brown)">wait_and_pop</span><span style="color:var(--pico-8-green)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">} <span style="color:var(--pico-8-pink)">else</span> {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">ris_log</span>::<span style="color:var(--pico-8-cyan)">error!</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-brown)">"couldn't pop job, calling thread isn't a worker thread"</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<u>result</u><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>Popping literally does nothing except calling <code class="code">wait_and_pop()</code> of its local buffer. If for whatever reason this method is called from a non-worker thread, then this method returns nothing and prints an error instead.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">steal_job</span><span style="color:var(--pico-8-cyan)">()</span> -> <span style="color:var(--pico-8-washed-grey)">Result</span><<span style="color:var(--pico-8-washed-grey)">Job</span>, <span style="color:var(--pico-8-washed-grey)">BlockedOrEmpty</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>result</u> = <span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">BlockedOrEmpty</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">WORKER_THREAD</span>.<span style="color:var(--pico-8-brown)">with</span><span style="color:var(--pico-8-green)">(</span>|worker_thread| <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span><u>worker_thread</u><span style="color:var(--pico-8-cyan)">)</span> = worker_thread.<span style="color:var(--pico-8-brown)">borrow_mut</span><span style="color:var(--pico-8-brown)">()</span>.<span style="color:var(--pico-8-brown)"><u>as_mut</u></span><span style="color:var(--pico-8-cyan)">() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">for</span> buffer <span style="color:var(--pico-8-pink)">in</span> &<u>worker_thread</u>.steal_buffers<> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>result</u> = buffer.<span style="color:var(--pico-8-brown)">steal()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <u>result</u>.<span style="color:var(--pico-8-brown)">is_ok() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">break</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">} <span style="color:var(--pico-8-pink)">else</span> {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">ris_log</span>::<span style="color:var(--pico-8-cyan)">error!</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-brown)">"couldn't steal job, calling thread isn't a worker thread"</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<u>result</u><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>Stealing is pretty much the same, except that because we have a vector of buffers, we iterate through them. The first steal that succeeds breaks the iteration. Just like <code class="code">pop_job()</code>, if this is called from a non-worker thread somehow, this method will print an error.</p>

<p>With all the setting up, tearing down and dequeuing taken care of, let's look at the thread index:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">pub fn <span style="color:var(--pico-8-brown)">thread_index</span>()</span> -> <span style="color:var(--pico-8-washed-grey)">i32</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>result</u> = <span style="color:var(--pico-8-green)">-1</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">WORKER_THREAD</span>.<span style="color:var(--pico-8-brown)">with</span><span style="color:var(--pico-8-green)">(</span>|worker_thread| <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span>worker_thread<span style="color:var(--pico-8-cyan)">)</span> = worker_thread.<span style="color:var(--pico-8-brown)">borrow</span><span style="color:var(--pico-8-cyan)">()</span>.<span style="color:var(--pico-8-brown)">as_ref</span><span style="color:var(--pico-8-cyan)">() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>result</u> = worker_thread.index <span style="color:var(--pico-8-cyan)">as</span> <span style="color:var(--pico-8-washed-grey)">i32</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">} <span style="color:var(--pico-8-pink)">else</span> {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">ris_log</span>::<span style="color:var(--pico-8-cyan)">error!</span><span style="color:var(--pico-8-green)">(<span style="color:var(--pico-8-brown)">"calling thread isn't a worker thread"</span>)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<u>result</u><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>This simply returns the thread-local index. If the calling thread is not a worker thread, <code class="code">-1</code> is returned and an error is printed.</p>

<p>I reserved the submit function for last, because it uses <code class="code">JobFuture</code>s, which I'll explain in the next section. But here it finally is:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">submit</span><<span style="color:var(--pico-8-washed-grey)">ReturnType</span>: <span style="color:var(--pico-8-cyan)">'static</span>, <span style="color:var(--pico-8-washed-grey)">F</span>: <span style="color:var(--pico-8-washed-grey)">FnOnce</span><span style="color:var(--pico-8-cyan)">()</span> -> <span style="color:var(--pico-8-washed-grey)">ReturnType</span> + <span style="color:var(--pico-8-cyan)">'static</span>><span style="color:var(--pico-8-cyan)">(</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;job: <span style="color:var(--pico-8-washed-grey)">F</span>,<br>
<span style="color:var(--pico-8-cyan)">)</span> -> <span style="color:var(--pico-8-washed-grey)">JobFuture</span><<span style="color:var(--pico-8-washed-grey)">ReturnType</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>not_pushed</u> = <span style="color:var(--pico-8-washed-grey)">None</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-green)">(</span>settable_future, future<span style="color:var(--pico-8-green)">)</span> = <span style="color:var(--pico-8-washed-grey)">SettableJobFuture</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> job = <span style="color:var(--pico-8-washed-grey)">Job</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-cyan)">move</span> || <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> result = job<span style="color:var(--pico-8-cyan)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;settable_future.<span style="color:var(--pico-8-brown)">set</span><span style="color:var(--pico-8-cyan)">(</span>result<span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">WORKER_THREAD</span>.<span style="color:var(--pico-8-brown)">with</span><span style="color:var(--pico-8-green)">(</span>|worker_thread| <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span><u>worker_thread</u><span style="color:var(--pico-8-cyan)">)</span> = worker_thread.<span style="color:var(--pico-8-brown)">borrow_mut</span><span style="color:var(--pico-8-cyan)">()</span>.<span style="color:var(--pico-8-brown)"><u>as_mut</u></span><span style="color:var(--pico-8-cyan)">() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> <u>worker_thread</u>.local_buffer.<span style="color:var(--pico-8-brown)">push</span><span style="color:var(--pico-8-green)">(</span>job<span style="color:var(--pico-8-green)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-brown)">(<span style="color:var(--pico-8-cyan)">()</span>) <span style="color:var(--pico-8-black)">=></span> ()</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-brown)">(</span>blocked_or_full<span style="color:var(--pico-8-brown)">)</span> => <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>not_pushed</u> = <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span>blocked_or_full.not_pushed<span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">} <span style="color:var(--pico-8-pink)">else</span> {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">ris_log</span>::<span style="color:var(--pico-8-cyan)">error!</span><span style="color:var(--pico-8-green)">(<span style="color:var(--pico-8-brown)">"couldn't submit job, calling thread isn't a worker thread"</span>)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-cyan)">mut</span> <u>to_invoke</u><span style="color:var(--pico-8-green)">)</span> = <u>not_pushed</u> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>to_invoke</u>.<span style="color:var(--pico-8-brown)"><u>invoke</u>()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;future<br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>This function takes a closure, that can return a value. This is the job to be run. And it returns a <code class="code">JobFuture</code>, which can return the jobs returned value. You may remember, that <code class="code">Job</code> was a very very simple wrapper around a function pointer, <b>which doesn't even return anything</b>. That is intentional, to make my life easier. Instead of handing the closure directly into the job, and thus forcing me to somehow accommodate for its return value, it's much easier to simply wrap the closure into another closure, that doesn't return anything.</p>

<p><code class="code">submit()</code> first creates the future. This includes a <code class="code">SettableJobFuture</code> and a <code class="code">JobFuture</code>. Soon you will see, that they share a mutex, but the split between "settable" and "non-settable" prevents client code to set the future themselves.</p>

<p>Then it creates said closure, which sets the future with its return value. After that, we simply call <code class="code">push()</code> from our thread-local local buffer. Recall that pushing returns the job, when the buffer is full. In that case, we store it in <code class="code">not_pushed</code> and invoke it later. At the very end, we return the non-settable <code class="code">JobFuture</code>, so that the client may wait on the job that was just submitted.</p>

<p>If you read this far, and understood everything, I have to commemorate you. To come to this point, I've read several books already. Even though this blogpost is already incredibly long, it still condenses a lot of information, and I seriously applaud you if you could follow along with everything. But we aren't done yet, there are still 2 things that we need to talk about.</p>

<h2>JobFuture</h2>

<p>Submitting a job is an asynchronous operation. Submitting takes O(1) time, but the job itself will be executed on any core in some arbitrary point in the future. But what if you need to wait for the job to continue? For example, my Input system runs mouse, keyboard and gamepad in parallel, but my remapping system requires that these 3 systems are already computed. So before any remapping can take place, the input job needs to wait for the 3 children.</p>

<p>This is what the <code class="code">JobFuture</code> is for. It gives client code a handle, which can be awaited. As you've already seen, it is split into a <code class="code">SettableJobFuture</code> and a non-settable <code class="code">JobFuture</code>. Let's just jump straight into it!</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">struct</span> <span style="color:var(--pico-8-washed-grey)">Inner</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;is_ready: <span style="color:var(--pico-8-washed-grey)">bool</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;data: <span style="color:var(--pico-8-washed-grey)">Option</span><<span style="color:var(--pico-8-washed-grey)">T</span>>,<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">type</span> <span style="color:var(--pico-8-washed-grey)">InnerPtr</span><<span style="color:var(--pico-8-washed-grey)">T</span>> = <span style="color:var(--pico-8-washed-grey)">Arc</span><<span style="color:var(--pico-8-washed-grey)">Mutex</span><<span style="color:var(--pico-8-washed-grey)">Inner</span><<span style="color:var(--pico-8-washed-grey)">T</span>>>>;<br>
<br>
<span style="color:var(--pico-8-cyan)">pub struct</span> <span style="color:var(--pico-8-washed-grey)">SettableJobFuture</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;inner: <span style="color:var(--pico-8-washed-grey)">InnerPtr</span><<span style="color:var(--pico-8-washed-grey)">T</span>>,<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">pub struct</span> <span style="color:var(--pico-8-washed-grey)">JobFuture</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;inner: <span style="color:var(--pico-8-washed-grey)">InnerPtr</span><<span style="color:var(--pico-8-washed-grey)">T</span>>,<br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p><code class="code">Inner</code> is simply the data to be stored. It stores a bool <code class="code">is_ready</code>, which indicates whether the job is finished or not. <code class="code">data</code> is the value, which was returned by the job. It is stored inside an <code class="code">Option</code>, because sooner or later we need to move the data out. The Future can be in these 4 states:</p>

<table class="future_table">
    <tr>
        <td class="future_table_th">is_ready</td>
        <td class="future_table_th">data</td>
        <td class="future_table_th">state</td>
    </tr>
    <tr>
        <td class="future_table_td">false</td>
        <td class="future_table_td">None</td>
        <td class="future_table_td">Job is not done</td>
    </tr>
    <tr>
        <td class="future_table_td">true</td>
        <td class="future_table_td">Some</td>
        <td class="future_table_td">Job is done</td>
    </tr>
    <tr>
        <td class="future_table_td">true</td>
        <td class="future_table_td">None</td>
        <td class="future_table_td">Job is done, and data was moved out</td>
    </tr>
    <tr>
        <td class="future_table_td">false</td>
        <td class="future_table_td">Some</td>
        <td class="future_table_td">close eyes, cover ears and run screaming in circles</td>
    </tr>
</table>

<p><code class="code">SettableJobFuture</code> and <code class="code">JobFuture</code> literally store the same: An <code class="code">Arc&lt;Mutex&lt;Inner&lt;T&gt;&gt;&gt;</code>. Thus, they are virtually identical. Because they are different structs however, they can implement different methods. For example, only <code class="code">SettableJobFuture</code> has a constructor, and it returns both a <code class="code">SettableJobFuture</code> and a <code class="code">JobFuture</code>. Also, only <code class="code">SettableJobFuture</code> can set its value. <code class="code">JobFuture</code> can wait on a value, but <code class="code">SettableJobFuture</code> cannot. Let's see:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">impl</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-washed-grey)">SettableJobFuture</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">()</span> -> <span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">SettableJobFuture</span><<span style="color:var(--pico-8-washed-grey)">T</span>>, <span style="color:var(--pico-8-washed-grey)">JobFuture</span><<span style="color:var(--pico-8-washed-grey)">T</span>><span style="color:var(--pico-8-green)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> inner = <span style="color:var(--pico-8-washed-grey)">Arc</span>::<span style="color:var(--pico-8-brown)">new(</span><span style="color:var(--pico-8-washed-grey)">Mutex</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">Inner</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is_ready: <span style="color:var(--pico-8-cyan)">false</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data: <span style="color:var(--pico-8-washed-grey)">None</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><span style="color:var(--pico-8-cyan)">)</span><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> settable_job_future = <span style="color:var(--pico-8-washed-grey)">SettableJobFuture</span> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inner: inner.<span style="color:var(--pico-8-brown)">clone</span><span style="color:var(--pico-8-cyan)">()</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> job_future = <span style="color:var(--pico-8-washed-grey)">JobFuture</span> <span style="color:var(--pico-8-brown)">{</span> inner <span style="color:var(--pico-8-brown)">}</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">(</span>settable_job_future, job_future<span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">set</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-cyan)">self</span>, result: <span style="color:var(--pico-8-washed-grey)">T</span><span style="color:var(--pico-8-green)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>inner</u> = <span style="color:var(--pico-8-cyan)">unwrap_or_throw!</span>(<span style="color:var(--pico-8-cyan)">self</span>.inner.<span style="color:var(--pico-8-brown)">lock</span><span style="color:var(--pico-8-cyan)">()</span>, <span style="color:var(--pico-8-brown)">"couldn't set job future")</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>inner</u>.is_ready = <span style="color:var(--pico-8-cyan)">true</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>inner</u>.data = <span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-brown)">(</span>result<span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p><code class="code">SettableJobFuture</code> is very straight forward. It initializes the <code class="code">Arc&lt;Mutex&lt;Inner&lt;T&gt;&gt;&gt;</code> which will be shared between the two structs. It then creates each struct and returns them. <code class="code">set()</code> simply locks the mutex, sets <code class="code">is_ready</code> to <code class="code">true</code>, and overwrites <code class="code">data</code>. Notice how <code class="code">set()</code> consumes <code class="code">self</code>. This directly means that once <code class="code">SettableJobFuture</code> is changed, it might as well be dead.</p>

<p>Let's look at the await-able <code class="code">JobFuture</code> next:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">impl</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-washed-grey)">JobFuture</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">wait</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-cyan)">mut <u>self</u></span><span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-washed-grey)">T</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> <span style="color:var(--pico-8-cyan)"><u>self</u></span>.<span style="color:var(--pico-8-brown)"><u>wait_and_take</u>() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Some</span><span style="color:var(--pico-8-cyan)">(</span>value<span style="color:var(--pico-8-cyan)">)</span> => value,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">None</span> => <span style="color:var(--pico-8-cyan)">unreachable!()</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)"><u>wait_and_take</u></span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">mut <u>self</u></span><span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-washed-grey)">Option</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">loop</span> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">match</span> <span style="color:var(--pico-8-cyan)"><u>self</u></span>.inner.<span style="color:var(--pico-8-brown)">try_lock</span><span style="color:var(--pico-8-cyan)">() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Ok</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-cyan)">mut</span> <u>inner</u><span style="color:var(--pico-8-green)">)</span> => <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <u>inner</u>.is_ready <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">return</span> <u>inner</u>.data.<span style="color:var(--pico-8-brown)"><u>take</u></span><span style="color:var(--pico-8-cyan)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Err</span><span style="color:var(--pico-8-green)">(</span>e<span style="color:var(--pico-8-green)">)</span> => <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">if</span> <span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-washed-grey)">TryLockError</span>::<span style="color:var(--pico-8-washed-grey)">Poisoned</span><span style="color:var(--pico-8-brown)">(</span>e<span style="color:var(--pico-8-brown)">)</span> = e <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">throw!(</span><span style="color:var(--pico-8-brown)">"couldn't take job future: <span style="color:var(--pico-8-cyan)">{}</span>"</span>, e<span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">job_system</span>::<span style="color:var(--pico-8-brown)">run_pending_job</span><span style="color:var(--pico-8-cyan)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>Just like <code class="code">set()</code> in <code class="code">SettableJobFuture</code>, <code class="code">wait()</code> also consumes self. This results in the fact, that taking <code class="code">data</code> will always succeed. We can't <code class="code">wait()</code> a second time, when it was awaited already. This is why the <code class="code">None</code> branch of <code class="code">wait()</code> includes an <code class="code">unreachable!()</code> and why <code class="code">wait()</code> can afford to return the value directly, instead of returning an <code class="code">Option</code>.</p>

<p><code class="code">wait()</code> calls <code class="code">wait_and_take()</code>, which spinlocks until <code class="code">data</code> is set. Considering the reactions I got from a <a href="https://www.rismosch.com/article?id=running-test-in-series" target="_blank" rel="noopener noreferrer">previous blogpost</a>, people somehow seem to hate spinlocks and immediately consider them unsafe. But let me assure you, that without a spinlock, this future wouldn't work.</p>

<p>Assume for a second, that <code class="code">wait()</code> uses a locking mechanism, like a condition variable or a mutex. In that case, <b>waiting for the future would block the entire thread</b>. This is problematic, because a blocked worker thread cannot run jobs. Ideally, the worker thread would do other things while the calling job is waiting. As such, a spinlock-like construct is the best choice for implementing such behavior.</p>

<p>This is what <code class="code">wait_and_take()</code> does: It first calls <code class="code">try_lock()</code> on the mutex, which isn't a blocking operation. If the lock was successful and the future was set, we can take the <code class="code">data</code> inside. If the lock was not successful, because it was poisoned, then this is unrecoverable and we throw an error. If the future was not set, or the lock resulted in a <code class="code">TryLockError::WouldBlock</code> error, then we run a pending job and attempt the whole procedure again.</p>

<p>In a nutshell, <code class="code">wait()</code> will be stuck in a loop, running pending jobs, as long as the job is not completed, thus effectively blocking the calling job and progressing the entire job system. With this taken care of, what else might be missing from this job system? Well...</p>

<h2>JobCell</h2>

<p>At this point, I thought I was done with the job system. I seriously didn't expect that Rusts borrow checker would be a major killjoy. I've spent already a lot of time and effort to get to this point. But then I tried using it in my main loop, and the compiler simply said no.</p>

<img src="https://www.rismosch.com/articles/building-a-job-system/borrow_checker_meme.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>The entire purpose of jobs is that they can take stuff, like objects or references, and then do work on them. A job will probably mutate data, or simply just immutably reference it to generate new state. But here's the last obstacle: Because the entire job system stores everything statically, thanks to its singleton-like nature, everything that is moved into a job must be statically borrowed. Something that is locally owned or referenced cannot be borrowed for a static lifetime. As much as the compiler is concerned, if a reference is moved into a job, it enters the nirvana, never to return. And the compiler simply doesn't allow that.</p>

<p>A workaround must be found.</p>

<p>To overcome this problem, I really had to scrape the bottom of the barrel. I have tested numerous solutions, all of which weren't satisfactory. Either I'd took a major performance hit, or the solution would panic randomly, or I'd introduce undefined behavior. Nothing worked, and prototype after prototype failed.</p>

<p>Before you say it, no, <code class="code">Arc&lt;Mutex&lt;T&gt;&gt;</code> does <b>NOT</b> work. Remember what I've written in the previous section <i>JobFuture</i>: If a mutex were to block, then the entire worker thread blocks, meaning no progress will be made. I could write a spinlock around <code class="code">try_lock()</code>, but this really isn't practical. Even if I were to create an elegant interface to spinlock a mutex, a spinlock still adds major overhead, which simply isn't worth it for just passing a single value into a job. This is especially true when I plan to spawn numerous jobs, all of which may reference their outside in one way or another.</p>

<p>What I want is an easy way to pass things into a job, with no overhead at all. Eventually, this led me to <code class="code">UnsafeCell</code>, and a much much deeper understanding of how Rusts ownership rules work.</p>

<p>First, let's tackle mutable references, because as you will see shortly, these are actually quite easy to work around. I was expecting that these are the difficult ones, but with a little hack they were pretty trivial to solve. Instead of passing a mutable reference into a job, you can simply pass <i>ownership</i> into the job.</p>

<p>Test your knowledge! Does the following code compile?</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">struct <span style="color:var(--pico-8-washed-grey)">MyInt</span> {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;value: <span style="color:var(--pico-8-washed-grey)">i32</span>,<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">struct</span> <span style="color:var(--pico-8-washed-grey)">Wrapper</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">MyInt</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
<br>
<span style="color:var(--pico-8-cyan)">fn <span style="color:var(--pico-8-brown)">consume</span>(</span>_: <span style="color:var(--pico-8-washed-grey)">MyInt</span><span style="color:var(--pico-8-cyan)">) {}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">fn <span style="color:var(--pico-8-brown)">main</span>() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> wrapper = <span style="color:var(--pico-8-washed-grey)">Wrapper</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">MyInt</span> <span style="color:var(--pico-8-brown)">{</span> value: <span style="color:var(--pico-8-washed-grey)">42 <span style="color:var(--pico-8-brown)">}</span>)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">consume</span><span style="color:var(--pico-8-green)">(</span>wrapper.0<span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">println!</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-brown)">"my current value is: <span style="color:var(--pico-8-cyan)">{}</span>"</span>, wrapper.0.value<span style="color:var(--pico-8-green)">)</span>;<br>
<span style="color:var(--pico-8-washed-grey)">}</span>
</code>

<p>Hover to reveal the answer:</p>

<p class="spoiler">No, this doesn't compile. That should come as no surprise. We are moving a value out of <code class="code">wrapper</code>! If you are accustomed to Rust, this should stick out like a sore thumb, and you would immediately realize that passing a <code class="code">&mut</code> into <code class="code">consume()</code> is probably what you wanted in the first place.</p>

<p>But what about this one? Does this compile?</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">struct <span style="color:var(--pico-8-washed-grey)">MyInt</span> {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;value: <span style="color:var(--pico-8-washed-grey)">i32</span>,<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">struct</span> <span style="color:var(--pico-8-washed-grey)">Wrapper</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">MyInt</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
<br>
<span style="color:var(--pico-8-cyan)">fn <span style="color:var(--pico-8-brown)">consume</span>(</span>_: <span style="color:var(--pico-8-washed-grey)">MyInt</span><span style="color:var(--pico-8-cyan)">) {}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">fn <span style="color:var(--pico-8-brown)">main</span>() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> wrapper = <span style="color:var(--pico-8-washed-grey)">Wrapper</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">MyInt</span> <span style="color:var(--pico-8-brown)">{</span> value: <span style="color:var(--pico-8-washed-grey)">42 <span style="color:var(--pico-8-brown)">}</span>)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">consume</span><span style="color:var(--pico-8-green)">(</span>wrapper.0<span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;wrapper.0 = <span style="color:var(--pico-8-washed-grey)">MyInt</span> <span style="color:var(--pico-8-green)">{</span> value: <span style="color:var(--pico-8-green)">-13 }</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">println!</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-brown)">"my current value is: <span style="color:var(--pico-8-cyan)">{}</span>"</span>, wrapper.0.value<span style="color:var(--pico-8-green)">)</span>;<br>
<span style="color:var(--pico-8-washed-grey)">}</span>
</code>

<p>Hover to reveal the answer:</p>

<p class="spoiler">Yes, this does actually compile. This surprised me when I first saw this. We are still moving a value out of <code class="code">wrapper</code>, just like the first code snippet, so why does it compile? The reason why the first one didn't compile is not really because we moved something out. Rather, we tried to <i>use</i> a value which was already moved. If you remove the <code class="code">println!()</code> in the first example, we are not using <code class="code">wrapper</code> after its move and the code compiles just fine. This implies that it's A-okay to move child values out from a parent. We just gotta replace it before we use it again. Instead of replacing it with an arbitrary value, we can replace it with the value we moved out! Remember that the <code class="code">JobFuture</code> allows us to return something from a job. Any ownership that we may pass into a job we can return afterwards.</p>

<p>To illustrate this technique, here's an excerpt of my input logic, showcasing the part of the keyboard job:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)"><u>run</u></span><span style="color:var(--pico-8-green)">(</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&<span style="color:var(--pico-8-cyan)">mut <u>self</u></span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">mut</span> <u>current</u>: <span style="color:var(--pico-8-washed-grey)">InputData</span>, <span style="color:var(--pico-8-green)">//&#127312;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;previous: <span style="color:var(--pico-8-washed-grey)">Ref</span><<span style="color:var(--pico-8-washed-grey)">InputData</span>>, <span style="color:var(--pico-8-green)">//&#127313;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;_frame: <span style="color:var(--pico-8-washed-grey)">Ref</span><<span style="color:var(--pico-8-washed-grey)">FrameData</span>>,<br>
<span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">InputData</span>, <span style="color:var(--pico-8-washed-grey)">GameloopState</span><span style="color:var(--pico-8-green)">) {</span> <span style="color:var(--pico-8-green)">//&#127314;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> current_keyboard = <u>current</u>.keyboard; <span style="color:var(--pico-8-green)">//&#127315;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> keyboard_future = <span style="color:var(--pico-8-washed-grey)">job_system</span>::<span style="color:var(--pico-8-brown)">submit(</span><span style="color:var(--pico-8-cyan)">move</span> || <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>keyboard</u> = current_keyboard; <span style="color:var(--pico-8-green)">//&#127316;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> gameloop_state = <span style="color:var(--pico-8-brown)">update_keyboard</span><span style="color:var(--pico-8-green)">(</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&<span style="color:var(--pico-8-cyan)">mut</span> <u>keyboard</u>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">(<span style="color:var(--pico-8-black)"><u>keyboard</u>, gameloop_state</span>)</span> <span style="color:var(--pico-8-green)">//&#127317;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-brown)">(</span>new_keyboard, new_gameloop_state<span style="color:var(--pico-8-brown)">)</span> = keyboard_future.<span style="color:var(--pico-8-brown)">wait()</span>; <span style="color:var(--pico-8-green)">//&#127318;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<u>current</u>.keyboard = new_keyboard; <span style="color:var(--pico-8-green)">//&#127319;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">(</span><u>current</u>, new_gameloop_state<span style="color:var(--pico-8-brown)">)</span><br>
<span style="color:var(--pico-8-green)">}</span>
</code>

<p>Ignore <code class="code">Ref</code> for a moment &#127313;. It most definitely is not the <code class="code">Ref</code> you are currently thinking about. We will talk about it in a second.</p>

<p>Notice how the <code class="code">run()</code> function takes ownership of an <code class="code">InputData</code> object &#127312;. It also returns an <code class="code">InputData</code> object &#127314;. This method alone is already demonstrating the technique. It takes ownership of <code class="code">InputData</code> and later returns it. The first thing we do is to pass ownership of <code class="code">current.keyboard</code> to a local variable &#127315;. Then we move the local variable and ownership into the job &#127316;. Now the job owns the keyboard and can mutate it however it wants. With an additional <code class="code">gameloop_state</code>, the job also returns the keyboard &#127317;, such that when the job is awaited, the caller once again has the ownership of <code class="code">keyboard</code> in a local variable &#127318;. To satisfy the compiler, we move this local variable <code class="code">new_keyboard</code> back into <code class="code">current.keyboard</code> &#127319;.</p>

<img src="https://www.rismosch.com/articles/building-a-job-system/ownership_diagram.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>No ownership rules have been broken, and yet a job was fully able to mutate the value. Notice how in the diagram above, no green "owns keyboard" blocks overlap on the y axis. At every single point in time, there exists exactly one owner of <code class="code">keyboard</code>, and as such the compiler is happy with this code.</p>

<br><br>

<p>This is cool, but why is this section called <code class="code">JobCell</code>? Apparently, we don't even need a <code class="code">Cell</code>-like structure to move things into a job! Up until this point I've talked about moving mutable values. But immutable references ain't so easy.</p>

<p>Immutable references are implicitly <code class="code">Copy</code>. That means that if a single immutable reference exists, you can make as many immutable references as you like. We may pass a single immutable reference into a job, but returning it is fruitless. The job may create God knows how many references from it. A single return can never accommodate for all references that have been created. To say it bluntly: <code class="code">&</code> is forbidden. No amount of ownership tricks can change this.</p>

<p>So we need a <code class="code">Cell</code>-like struct afterall, that keeps track of all references somehow. Let me introduce my <code class="code">JobCell</code>:</p>

<img src="https://www.rismosch.com/articles/building-a-job-system/jobcell.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>This <code class="code">JobCell</code> can be in two states: Either simply <code class="code">JobCell</code>, which allows you to make as many immutable references as you like. Or <code class="code">MutableJobCell</code>, which allows you to mutate its content. To switch between the two states, some extra logic is required:</p>

<p>To switch from <code class="code">JobCell</code> to <code class="code">MutableJobCell</code>, all immutable references must be dead. To do this, we spinlock and call pending jobs as long as immutable references exist. This already imposes a restriction: Immutable references, created by the <code class="code">JobCell</code>, are only allowed to be passed into a Job. If you were to create an immutable reference in the same thread where you want to mutate data, or attempt to store the reference somewhere indefinitely, then switching to the mutable state will <i>livelock</i>. A livelock is similar to a deadlock, except it is using up resources by spinning, instead of just going to sleep like a deadlock.</p>

<p>But if this restriction is taken care of, the spinlock ends and a <code class="code">MutableJobCell</code> is created. To switch back to <code class="code">JobCell</code>, all you have to do is to drop <code class="code">MutableJobCell</code>. Now here comes a trick: Since <code class="code">MutableJobCell</code> borrows <code class="code">JobCell</code> mutably, the Rust compiler forbids you to use <code class="code">JobCell</code> while <code class="code">MutableJobCell</code> lives. This means as long as the <code class="code">JobCell</code> is in its mutable state, no immutable references can be created. Not via <code class="code">JobCell</code>s interface, nor via Rusts default reference mechanics.</p>

<p>Enough theory, let's look at some code:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">pub struct</span> <span style="color:var(--pico-8-washed-grey)">JobCell</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;value: <span style="color:var(--pico-8-washed-grey)">UnsafeCell</span><<span style="color:var(--pico-8-washed-grey)">T</span>>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;refs: <span style="color:var(--pico-8-washed-grey)">Arc</span><<span style="color:var(--pico-8-washed-grey)">AtomicUsize</span>>,<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">pub struct</span> <span style="color:var(--pico-8-washed-grey)">MutableJobCell</span><<span style="color:var(--pico-8-cyan)">'a</span>, <span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;value: &<span style="color:var(--pico-8-cyan)">'a</span> <span style="color:var(--pico-8-washed-grey)">UnsafeCell</span><<span style="color:var(--pico-8-washed-grey)">T</span>>,<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">pub struct</span> <span style="color:var(--pico-8-washed-grey)">Ref</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;value: <span style="color:var(--pico-8-washed-grey)">NonNull</span><<span style="color:var(--pico-8-washed-grey)">T</span>>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;refs: <span style="color:var(--pico-8-washed-grey)">Arc</span><<span style="color:var(--pico-8-washed-grey)">AtomicUsize</span>>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;_boo: <span style="color:var(--pico-8-washed-grey)">PhantomData</span><<span style="color:var(--pico-8-washed-grey)">T</span>>,<br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>Here we have all structs to make the magic work. <code class="code">JobCell</code> is a simple wrapper around <code class="code">UnsafeCell</code>, but it additionally keeps count of its current references via an <code class="code">AtomicUsize</code>. As mentioned previously, <code class="code">MutableJobCell</code> stores a <i>reference</i> to an <code class="code">UnsafeCell</code>, instead of straight up owning it. This directly leads to the mechanism, that <code class="code">JobCell</code> cannot be used while <code class="code">MutableJobCell</code> lives. Finally, we need to mimic <code class="code">&</code>, by wrapping a pointer into a struct called <code class="code">Ref</code>. Since this wrapper is its own thing, and syntactically independent from <code class="code">JobCell</code>, the compiler thinks that client code owns it. To ensure that <code class="code">Ref</code> mimics an immutable reference, only <code class="code">Deref</code> will be implemented on it. It also doesn't implement any methods that could mutate its state in any way. Additionally, <code class="code">Ref</code> stores a counter of all alive references. This counter is increased when <code class="code">Ref</code> is being cloned, or decreased when <code class="code">Ref</code> is being dropped. And because of some compiler optimization aliasing safety shenanigans tic-tac-toe i-don't-know-what-i-am-talking-about, <code class="code">Ref</code> must also store a <code class="code">PhantomData</code>.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">impl</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-washed-grey)">JobCell</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">/// ⚠️ don't put this in an `Rc<T>` or `Arc<T>` ⚠️</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">///</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">/// this cell is intended to have only one owner, who can mutate it</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span>value: <span style="color:var(--pico-8-washed-grey)">T</span><span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-cyan)">Self</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">Self</span> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value: <span style="color:var(--pico-8-washed-grey)">UnsafeCell</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-cyan)">(</span>value<span style="color:var(--pico-8-cyan)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;refs: <span style="color:var(--pico-8-washed-grey)">Arc</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">AtomicUsize</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(0)</span><span style="color:var(--pico-8-cyan)">)</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">/// ⚠️ this method **WILL** livelock, when not all created `Ref<T>`s are dropped ⚠️</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)"><u>as_mut</u></span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-washed-grey)">mut <u>self</u></span><span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-washed-grey)">MutableJobCell</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-washed-grey)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">while</span> <span style="color:var(--pico-8-washed-grey)"><u>self</u></span>.refs.<span style="color:var(--pico-8-brown)">load(</span><span style="color:var(--pico-8-washed-grey)">Ordering</span>::<span style="color:var(--pico-8-washed-grey)">SeqCst</span><span style="color:var(--pico-8-brown)">)</span> > <span style="color:var(--pico-8-green)">0</span> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">job_system</span>::<span style="color:var(--pico-8-brown)">run_pending_job</span><span style="color:var(--pico-8-cyan)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">MutableJobCell</span> <span style="color:var(--pico-8-brown)">{</span> value: &<span style="color:var(--pico-8-cyan)"><u>self</u></span>.value <span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">borrow</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-washed-grey)">Ref</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">self</span>.refs.<span style="color:var(--pico-8-brown)">fetch_add(</span><span style="color:var(--pico-8-green)">1</span>, <span style="color:var(--pico-8-washed-grey)">Ordering</span>::<span style="color:var(--pico-8-washed-grey)">SeqCst</span><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> value = <span style="color:var(--pico-8-cyan)">unsafe</span> <span style="color:var(--pico-8-brown)">{</span> <span style="color:var(--pico-8-washed-grey)">NonNull</span>::<span style="color:var(--pico-8-brown)">new_unchecked</span><span style="color:var(--pico-8-cyan)">(self</span>.value.<span style="color:var(--pico-8-brown)">get</span><span style="color:var(--pico-8-green)">()</span><span style="color:var(--pico-8-cyan)">)</span> <span style="color:var(--pico-8-brown)">}</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">Ref</span> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;refs: <span style="color:var(--pico-8-cyan)">self</span>.refs.clone<span style="color:var(--pico-8-cyan)">()</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_boo: <span style="color:var(--pico-8-washed-grey)">PhantomData</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>Like I have said a thousand times already, the constructor should be fairly self-explanatory. It creates the <code class="code">UnsafeCell</code> and the reference counter.</p>

<p>Since we went over the theory already, <code class="code">as_mut()</code> should also be fairly straight forward. In a spinlock it constantly checks whether any references exist, and it runs pending jobs if they do. Only when no references exist, a <code class="code">MutableJobCell</code> is created and returned.</p>

<p>If you've worked with Rusts pointers before, <code class="code">borrow()</code> shouldn't be that difficult to understand either. But before we do any pointer magic, we increase the reference count by 1, indicating that from now on, an immutable reference exists. Then, we create a pointer to the data of the <code class="code">UnsafeCell</code>. This value is never modified, or dereferenced mutably, so this is safe. Then we simply construct the <code class="code">Ref</code> struct and return it.</p>

<p>To make my life easier, <code class="code">MutableJobCell</code> implements one additional function:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">impl</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-washed-grey)">MutableJobCell</span><<span style="color:var(--pico-8-cyan)">'_</span>, <span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)"><u>replace</u></span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">mut <u>self</u></span>, value: <span style="color:var(--pico-8-washed-grey)">T</span><span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-washed-grey)">T</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-washed-grey)">mem</span>::<span style="color:var(--pico-8-brown)"><u>replace</u></span>(&<span style="color:var(--pico-8-cyan)">mut</span> *<span style="color:var(--pico-8-cyan)"><u>self</u></span>, value<span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>This is a simple wrapper to replace the inner value of the <code class="code">JobCell</code>.</p>

<p>Now let's implement some traits!</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">impl</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-washed-grey)">Deref</span> <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">MutableJobCell</span><<span style="color:var(--pico-8-cyan)">'_</span>, <span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">type</span> <span style="color:var(--pico-8-washed-grey)">Target</span> = <span style="color:var(--pico-8-washed-grey)">T</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">deref</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-green)">)</span> -> &<span style="color:var(--pico-8-cyan)">Self</span>::<span style="color:var(--pico-8-washed-grey)">Target</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">unsafe</span> <span style="color:var(--pico-8-brown)">{</span> &*<span style="color:var(--pico-8-cyan)">self</span>.value.<span style="color:var(--pico-8-brown)">get</span><span style="color:var(--pico-8-cyan)">()</span> <span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">impl</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-washed-grey)">DerefMut</span> <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">MutableJobCell</span><<span style="color:var(--pico-8-cyan)">'_</span>, <span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)"><u>deref_mut</u></span>(&<span style="color:var(--pico-8-cyan)">mut <u>self</u></span><span style="color:var(--pico-8-green)">)</span> -> &<span style="color:var(--pico-8-cyan)">mut Self</span>::<span style="color:var(--pico-8-washed-grey)">Target</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">unsafe</span> <span style="color:var(--pico-8-brown)">{</span> &<span style="color:var(--pico-8-cyan)">mut</span> *<span style="color:var(--pico-8-cyan)"><u>self</u></span>.value.<span style="color:var(--pico-8-brown)">get</span><span style="color:var(--pico-8-cyan)">()</span> <span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p><code class="code">Deref</code> and <code class="code">DerefMut</code> for <code class="code">MutableJobCell</code> are quite obvious, because we want to access and mutate the underlying data.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">impl</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-washed-grey)">Deref</span> <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">Ref</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">type</span> <span style="color:var(--pico-8-washed-grey)">Target</span> = <span style="color:var(--pico-8-washed-grey)">T</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">deref</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-green)">)</span> -> &<span style="color:var(--pico-8-cyan)">Self</span>::<span style="color:var(--pico-8-washed-grey)">Target</span> <span style="color:var(--pico-8-green)">{</span></><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">unsafe</span> <span style="color:var(--pico-8-brown)">{</span> <span style="color:var(--pico-8-cyan)">self</span>.value.<span style="color:var(--pico-8-brown)">as_ref</span><span style="color:var(--pico-8-cyan)">()</span> <span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p><code class="code">Deref</code> for <code class="code">Ref</code> is also a no brainer. Very important: <code class="code">Ref</code> does NOT implement <code class="code">DerefMut</code>, otherwise this would be undefined behavior galore!</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">impl</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-washed-grey)">Clone</span> <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">Ref</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">clone</span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-green)">)</span> -> <span style="color:var(--pico-8-cyan)">Self</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">self</span>.refs.<span style="color:var(--pico-8-brown)">fetch_add(</span><span style="color:var(--pico-8-green)">1</span>, <span style="color:var(--pico-8-washed-grey)">Ordering</span>::<span style="color:var(--pico-8-washed-grey)">SeqCst</span><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">Self</span> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value: <span style="color:var(--pico-8-cyan)">self</span>.value,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;refs: <span style="color:var(--pico-8-cyan)">self</span>.refs.<span style="color:var(--pico-8-brown)">clone</span><span style="color:var(--pico-8-cyan)">()</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_boo: <span style="color:var(--pico-8-washed-grey)">PhantomData</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>To clone a <code class="code">Ref</code>, we simply increase the reference counter and return a new <code class="code">Ref</code> with the same data.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">impl</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-washed-grey)">Drop</span> <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">Ref</span><<span style="color:var(--pico-8-washed-grey)">T</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)"><u>drop</u></span><span style="color:var(--pico-8-green)">(</span>&<span style="color:var(--pico-8-cyan)">mut <u>self</u></span><span style="color:var(--pico-8-green)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)"><u>self</u></span>.refs.<span style="color:var(--pico-8-brown)">fetch_sub(</span><span style="color:var(--pico-8-green)">1</span>, <span style="color:var(--pico-8-washed-grey)">Ordering</span>::<span style="color:var(--pico-8-washed-grey)">SeqCst</span><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>Dropping a <code class="code">Ref</code> decreases the reference counter. We don't need to free the pointer, because <code class="code">Ref</code> doesn't semantically own it.</p>

<p>And that is basically it! To see the <code class="code">JobCell</code> in action, here's some excerpt from my god job / main game loop:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">run</span><span style="color:var(--pico-8-cyan)">(mut</span <u>god_object</u>: <span style="color:var(--pico-8-washed-grey)">GodObject</span><span style="color:var(--pico-8-cyan)">)</span> -> <span style="color:var(--pico-8-washed-grey)">Result</span><<span style="color:var(--pico-8-washed-grey)">i32</span>, <span style="color:var(--pico-8-washed-grey)">String</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>frame</u> = <span style="color:var(--pico-8-washed-grey)">JobCell</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">FrameData</span>::<span style="color:var(--pico-8-brown)">default()</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>current_input</u> = <span style="color:var(--pico-8-washed-grey)">InputData</span>::<span style="color:var(--pico-8-brown)">default</span><span style="color:var(--pico-8-green)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>previous_input</u> = <span style="color:var(--pico-8-washed-grey)">JobCell</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">InputData</span>::<span style="color:var(--pico-8-brown)">default()</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>current_logic</u> = <span style="color:var(--pico-8-washed-grey)">LogicData</span>::<span style="color:var(--pico-8-brown)">default</span><span style="color:var(--pico-8-green)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>previous_logic</u> = <span style="color:var(--pico-8-washed-grey)">JobCell</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">LogicData</span>::<span style="color:var(--pico-8-brown)">default()</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>current_output</u> = <span style="color:var(--pico-8-washed-grey)">OutputData</span::<span style="color:var(--pico-8-brown)">default</span><span style="color:var(--pico-8-green)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let mut</span> <u>previous_output</u> = <span style="color:var(--pico-8-washed-grey)">JobCell</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-green)">(</span><span style="color:var(--pico-8-washed-grey)">OutputData</span>::<span style="color:var(--pico-8-brown)">default()</span><span style="color:var(--pico-8-green)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">loop</span> <span style="color:var(--pico-8-green)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">// update frame</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>frame</u>.<span style="color:var(--pico-8-brown)">as_mut()</span>.<span style="color:var(--pico-8-brown)">bump()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">// swap buffers</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>current_input</u> = <u>previous_input</u>.<span style="color:var(--pico-8-brown)">as_mut()</span>.<span style="color:var(--pico-8-brown)">replace(</span><u>current_input</u><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>current_logic</u> = <u>previous_logic</u>.<span style="color:var(--pico-8-brown)">as_mut()</span>.<span style="color:var(--pico-8-brown)">replace(</span><u>current_logic</u><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>current_output</u> = <u>previous_output</u>.<span style="color:var(--pico-8-brown)">as_mut()</span>.<span style="color:var(--pico-8-brown)">replace(</span><u>current_output</u><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">// create references</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> frame_for_input = <u>frame</u>.<span style="color:var(--pico-8-brown)">borrow()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> frame_for_logic = <u>frame</u>.<span style="color:var(--pico-8-brown)">borrow()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> frame_for_output = <u>frame</u>.<span style="color:var(--pico-8-brown)">borrow()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> previous_input_for_input = <u>previous_input</u>.<span style="color:var(--pico-8-brown)">borrow()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> previous_input_for_logic = <u>previous_input</u>.<span style="color:var(--pico-8-brown)">borrow()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> previous_logic_for_logic = <u>previous_logic</u>.<span style="color:var(--pico-8-brown)">borrow()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> previous_logic_for_output = <u>previous_logic</u>.<span style="color:var(--pico-8-brown)">borrow()</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> previous_output_for_output = <u>previous_output</u>.<span style="color:var(--pico-8-brown)">borrow()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">// submit jobs</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> output_future = <span style="color:var(--pico-8-washed-grey)">job_system</span>::<span style="color:var(--pico-8-brown)">submit(</span><span style="color:var(--pico-8-cyan)">move</span> || <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">output_frame</span>::<span style="color:var(--pico-8-brown)">run</span><span style="color:var(--pico-8-green)">(</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>current_output</u>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;previous_output_for_output,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;previous_logic_for_output,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame_for_output,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> logic_future = <span style="color:var(--pico-8-washed-grey)">job_system</span>::<span style="color:var(--pico-8-brown)">submit(</span><span style="color:var(--pico-8-cyan)">move</span> || <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">logic_frame</span>::<span style="color:var(--pico-8-brown)">run</span><span style="color:var(--pico-8-green)">(</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>current_logic</u>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;previous_logic_for_logic,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;previous_input_for_logic,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frame_for_logic,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">}</span><span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-brown)">(</span>new_input_data, input_state<span style="color:var(--pico-8-brown)">)</span> =<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>god_object</u><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.input_frame<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.<span style="color:var(--pico-8-brown)">run(</span><u>current_input</u>, previous_input_for_input, frame_for_input<span style="color:var(--pico-8-brown)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">// wait for jobs</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-brown)">(</span>new_logic_data, logic_state<span style="color:var(--pico-8-brown)">)</span> = logic_future.<span style="color:var(--pico-8-brown)">wait()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> <span style="color:var(--pico-8-brown)">(</span>new_output_data, output_state<span style="color:var(--pico-8-brown)">)</span> = output_future.<span style="color:var(--pico-8-brown)">wait()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">// update buffers</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>current_input</u> = new_input_data;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>current_logic</u> = new_logic_data;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>current_output</u> = new_output_data;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">...</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<p>Every buffer exists 2 times: Once as owned and once as <code class="code">JobCell</code>. It's pretty much a front- and back-buffer system. The jobs that own a buffer, can modify them as much as they want. The jobs that only borrow the <code class="code">JobCell</code> cannot mutate the buffer, and can only create new state which follows from the previous state.</p>

<p>Each iteration of the loop does the same: First, it switches each <code class="code">JobCell</code> to <code class="code">MutableJobCell</code> by calling <code class="code">as_mut()</code> on them. If any immutable references exist at this point, these calls will spinlock and run all leftover jobs. Then the owned buffer and the <code class="code">JobCell</code> buffer will be swapped. After that, all necessary <code class="code">Ref</code>s are created. Then these references are passed into the according jobs. Because SDL2 can only pump window events on the thread that spawned the window (which is my main thread), the input frame is not put into a job. And since we need to await it anyway, we might as well call it synchronously. After each job is done, we simply move ownership back, and another iteration of the loop is ready to be run.</p>

<h2>Conclusion</h2>

<p>What a buttload of garbage that I have written here. Does this junk even work?</p>

<p>Yes, surprisingly well actually. It was a lot of work to get this to a running state and I am quite amazed how stable it turned out in the end. There is no undefined behavior to my knowledge. How about performance? I get about the same number of frames as the previous single threaded prototype. This may sound bad, but this is probably due to the fact that this engine is very early in development. I simply don't have enough jobs yet to fully utilize its parallel ability. I have what? 4 jobs in total?! On my 12-core machine, that's hardly parallel at all! Anyway, be rest assured that this job system does indeed use 100% of CPU resources:</p>

<video loop="true" autoplay="autoplay" muted="true" style="max-width:100%; display: block; margin: auto;" loading='lazy'>
<source src="https://www.rismosch.com/articles/building-a-job-system/100_cpu_usage.mp4" type="video/mp4">
</video>

<p>I have nothing else to say. My engine works steadily, and it didn't offer any nasty surprises. It simply brings me joy. But alas, only time will tell how well this system works. Remember: I am still the villain of the phrase <i>"premature optimization is the root of all evil"</i>. This whole blogpost is the exemplification of <i>premature optimization</i>.</p>

<p>As for now, this job system is only a <i>proof of concept</i>. Now all I have to do is to use it, so I can experience firsthand how well it stacks up in the real world.</p>

<p>But until then, we'll hear from each other &#127926;</p>]]></content:encoded></item><item><title>Running Tests in Series in Rust</title><link>https://www.rismosch.com/article?id=running-test-in-series</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">running-test-in-series</guid><pubDate>Sun, 28 Aug 2022 01:06:48 +0200</pubDate><description>Proposing an easy solution, to execute selected tests in series, without using third party crates.</description><content:encoded><![CDATA[<p style="background-color:var(--pico-8-white); border: 5px solid var(--pico-8-cyan); padding: 20px;">If you don't care about motivation and just want a solution, simply jump to the code below or <a href="https://github.com/Rismosch/ris_engine/blob/6f210fc0956f446370ed752c6bb23354c3aac69d/crates/ris_util/src/test_lock.rs" target="_blank" rel="noopener noreferrer">view it on GitHub</a>.<br><br>Have fun &#128521;</p>

<br>

<p>Cargos test runner runs your tests concurrently. In a nutshell, that means <code class="code">cargo test</code> runs <b>multiple tests at the same time</b>. This is a double-edged sword though: On one hand, running all your tests may be significantly faster, because it literally runs more at less time. But the downside is, that your tests need to be 100% thread safe and they need to be completely independent from each other. Most of the time, tests you write in Rust should be independent from the get go, especially since <code class="code">cargo test</code> doesn't provide setup or teardown methods, which are commonly used in other testing frameworks in other languages. But there are a few cases, where even in Rust, data is shared between tests. Most notably: Statically mutable variables, files or database connections.</p>

<br>

<p>Here's how shared data creates problems with <code class="code">cargo test</code>: One test may set it up to "hoi" while another sets it up to "poi". Test one expects it to be "hoi" while the second expects it to be "poi". One possible concurrent execution of the tests may look like this: Test one sets it up to "hoi", but oh no, before it can check the data, test two sets it to "poi". Test two checks and sees the data is "poi" and succeeds. Now test one continues to execute, sees that the data is "poi" instead of "hoi", and the test fails. Even though we implemented our behaviour 100% correctly&#8482;, the test fails, because it has a <i>race condition</i> with another test.</p>

<br>

<img src="https://www.rismosch.com/articles/running-test-in-series/failed.webp" style="display: block; max-width: 100%;" />

<br>

<p>So how do we fix this? Simple: Don't execute tests concurrently. <a href="https://doc.rust-lang.org/book/ch11-02-running-tests.html#running-tests-in-parallel-or-consecutively" target="_blank" rel="noopener noreferrer">The Book</a> even tells us how to run tests on only one thread. But this directly means, that our tests won't run as fast. Bummer.</p>

<br>

<p>Instead, what we want is to selectively run only specific tests in series, while all unrelated tests run concurrently. <a href="https://fdeantoni.medium.com/running-tests-sequentially-in-rust-eed7566f63f0" target="_blank" rel="noopener noreferrer">This blogpost</a> by Ferdinand de Antoni suggests to simply use the <a href="https://crates.io/crates/serial_test" target="_blank" rel="noopener noreferrer">serial_test</a> crate. This works I guess, but I am more of a Terry A. Davis kind of guy, with virtually none of his genius and twice his sanity. So, I want to keep 3rd-party stuff to minimum. Also spoiler: The solution is so quick and easy, it doesn't really deserve a separate crate.</p>

<br>

<p>Ok, so we want to come up with a solution ourselves. We could write our own test harness. Yes, in Rust you can actually write one yourself. But there are 2 strong reasons against it:</p>
<ol>
<li>I only know that you <i>can</i> write your own test harness, but not <i>how</i>. I am really unqualified to give you directions on that. Though Jon Gjengset mentioned how to, in his book "Rust for Rustaceans", if you seriously want to do this.</li>
<li>Secondly: It's absolute overkill. Sure, you can kill a single ant with a nuclear bomb, it gets the job done, but I think there is a simpler solution.</li>
</ol>

<br>

<p>A simple, working approach would be the following: Have some piece of code, which is shared between tests, so <b><i>it</i></b> ensures that no tests are run in parallel. Now we are thinking concurrently! The most obvious data structure would be a <a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html" target="_blank" rel="noopener noreferrer">Mutex</a>. But a Mutex comes with a hefty drawback: <a href="https://doc.rust-lang.org/std/sync/struct.PoisonError.html" target="_blank" rel="noopener noreferrer">PoisonError</a>. Long story short: If a thread panics while holding a locked Mutex, other threads currently waiting to acquire the Mutex will panic too. That is no good, meaning a perfectly fine test will fail, when another using the same Mutex is failing. So we have to use something else.</p>

<br>

<p>What about <a href="https://doc.rust-lang.org/std/sync/atomic/" target="_blank" rel="noopener noreferrer">atomics</a>? Ah yes, that would work. We can set a flag at the start of our test, indicating that this test is running. Other threads trying to set that flag would see it as already set, and thus wait until it is free. We just need to reset that flag at the end of each test, such that other tests can run again.</p>

<br>

<p>Now this is promising, but it still isn't perfect: What if the test fails? Most of the time, your test fails because some panic occurred, whether by some <code class="code">assert!()</code>, <code class="code">unwrap()</code> or because you deliberately throw it in your code. This is bad, because a panic leads to the code afterwards to not be executed. This means a test holding the flag doesn't reset it after it failed. This in turn means, that every waiting test will wait forever, because no one is going to reset the flag.</p>

<br>

<p>But, what if we put it into a drop-guard?</p>

<br>

<p>...</p>

<br>

<p>Genius! Yes! Why didn't I think of that?! Let's put it into a file and ship it! Easy &#128526;</p>

<br>

<a href="https://github.com/Rismosch/ris_engine/blob/6f210fc0956f446370ed752c6bb23354c3aac69d/crates/ris_util/src/test_lock.rs" target="_blank" rel="noopener noreferrer">View on GitHub</a>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">use</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">sync</span>::<span style="color:var(--pico-8-washed-grey)">atomic</span>::<span style="color:var(--pico-8-lime)">{</span><span style="color:var(--pico-8-washed-grey)">AtomicBool</span>, <span style="color:var(--pico-8-washed-grey)">Ordering</span><span style="color:var(--pico-8-lime)">}</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">thread</span>,<br>
<span style="color:var(--pico-8-cyan)">}</span>;<br>
<br>
<span style="color:var(--pico-8-cyan)">pub struct</span> <span style="color:var(--pico-8-washed-grey)">TestLock</span><<span style="color:var(--pico-8-cyan)">'a</span>><span style="color:var(--pico-8-cyan)">(</span>&<span style="color:var(--pico-8-cyan)">'a</span> <span style="color:var(--pico-8-washed-grey)">AtomicBool</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
<br>
<span style="color:var(--pico-8-cyan)">impl</span><<span style="color:var(--pico-8-cyan)">'a</span>> <span style="color:var(--pico-8-washed-grey)">TestLock</span><<span style="color:var(--pico-8-cyan)">'a</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">pub fn</span> <span style="color:var(--pico-8-brown)">wait_and_lock</span><span style="color:var(--pico-8-lime)">(</span><u>lock</u>: &<span style="color:var(--pico-8-cyan)">'a</span> <span style="color:var(--pico-8-washed-grey)">AtomicBool</span><span style="color:var(--pico-8-lime)">)</span> -> <span style="color:var(--pico-8-cyan)">Self</span> <span style="color:var(--pico-8-lime)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink)">while</span> <u>lock</u><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.<span style="color:var(--pico-8-brown)">compare_exchange_weak(</span><span style="color:var(--pico-8-cyan)">false</span>, <span style="color:var(--pico-8-cyan)">true</span>, <span style="color:var(--pico-8-washed-grey)">Ordering</span>::<span style="color:var(--pico-8-washed-grey)">SeqCst</span>, <span style="color:var(--pico-8-washed-grey)">Ordering</span>::<span style="color:var(--pico-8-washed-grey)">SeqCst</span><span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.<span style="color:var(--pico-8-brown)">is_err()</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">thread</span>::<span style="color:var(--pico-8-brown)">yield_now</span><span style="color:var(--pico-8-cyan)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">Self</span><span style="color:var(--pico-8-brown)">(</span><u>lock</u><span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-lime)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">impl</span><<span style="color:var(--pico-8-cyan)">'a</span>> <span style="color:var(--pico-8-washed-grey)">Drop</span> <span style="color:var(--pico-8-cyan)">for</span> <span style="color:var(--pico-8-washed-grey)">TestLock</span><<span style="color:var(--pico-8-cyan)">'a</span>> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)"><u>drop</u></span><span style="color:var(--pico-8-lime)">(</span>&<span style="color:var(--pico-8-cyan)">mut <u>self</u></span><span style="color:var(--pico-8-lime)">) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)"><u>self</u></span>.0.<span style="color:var(--pico-8-brown)">store(</span><span style="color:var(--pico-8-cyan)">false</span>, <span style="color:var(--pico-8-washed-grey)">Ordering</span>::<span style="color:var(--pico-8-washed-grey)">SeqCst</span><span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-lime)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
#<span style="color:var(--pico-8-cyan)">[</span>cfg<span style="color:var(--pico-8-lime)">(</span>test<span style="color:var(--pico-8-lime)">)</span><span style="color:var(--pico-8-cyan)">]</span><br>
<span style="color:var(--pico-8-cyan)">mod</span> <span style="color:var(--pico-8-washed-grey)">examples</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">use</span> <span style="color:var(--pico-8-washed-grey)">std</span>::<span style="color:var(--pico-8-lime)">{</span><span style="color:var(--pico-8-washed-grey)">sync</span>::<span style="color:var(--pico-8-washed-grey)">atomic</span>::<span style="color:var(--pico-8-washed-grey)">AtomicBool</span>, <span style="color:var(--pico-8-washed-grey)">thread</span>, <span style="color:var(--pico-8-washed-grey)">time</span>::<span style="color:var(--pico-8-washed-grey)">Duration</span><span style="color:var(--pico-8-lime)">}</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">use super</span>::<span style="color:var(--pico-8-washed-grey)">TestLock</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">static mut</span> <u>UNSAFE_SHARED_DATA</u>: <span style="color:var(--pico-8-washed-grey)">String</span> = <span style="color:var(--pico-8-washed-grey)">String</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-lime)">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">static</span> <u>LOCK</u>: <span style="color:var(--pico-8-washed-grey)">AtomicBool</span> = <span style="color:var(--pico-8-washed-grey)">AtomicBool</span>::<span style="color:var(--pico-8-brown)">new</span><span style="color:var(--pico-8-lime)">(</span><span style="color:var(--pico-8-cyan)">false</span><span style="color:var(--pico-8-lime)">)</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;#<span style="color:var(--pico-8-lime)">[</span>test<span style="color:var(--pico-8-lime)">]</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">test_one</span><span style="color:var(--pico-8-lime)">() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> lock = <span style="color:var(--pico-8-washed-grey)">TestLock</span>::<span style="color:var(--pico-8-brown)">wait_and_lock(</span>&LOCK<span style="color:var(--pico-8-brown)">)</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">unsafe</span> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>UNSAFE_SHARED_DATA</u> = <span style="color:var(--pico-8-washed-grey)">String</span>::<span style="color:var(--pico-8-brown)">from</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-orange)">"hoi"</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">thread</span>::<span style="color:var(--pico-8-brown)">sleep</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-washed-grey)">Duration</span>::<span style="color:var(--pico-8-brown)">from_millis</span><span style="color:var(--pico-8-lime)">(1)</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">assert_eq</span><span style="color:var(--pico-8-brown)">!</span><span style="color:var(--pico-8-cyan)">(</span><u>UNSAFE_SHARED_DATA</u>, <span style="color:var(--pico-8-orange)">"hoi"</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">drop(</span>lock<span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-lime)">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;#<span style="color:var(--pico-8-lime)">[</span>test<span style="color:var(--pico-8-lime)">]</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">test_two</span><span style="color:var(--pico-8-lime)">() {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">let</span> lock = <span style="color:var(--pico-8-washed-grey)">TestLock</span>::<span style="color:var(--pico-8-brown)">wait_and_lock(</span>&LOCK<span style="color:var(--pico-8-brown)">)</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">unsafe</span> <span style="color:var(--pico-8-brown)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>UNSAFE_SHARED_DATA</u> = <span style="color:var(--pico-8-washed-grey)">String</span>::<span style="color:var(--pico-8-brown)">from</span><span style="color:var(--pico-8-cyan)">(</span><span style="color:var(--pico-8-orange)">"poi"</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">assert_eq</span><span style="color:var(--pico-8-brown)">!</span><span style="color:var(--pico-8-cyan)">(</span><u>UNSAFE_SHARED_DATA</u>, <span style="color:var(--pico-8-orange)">"poi"</span><span style="color:var(--pico-8-cyan)">)</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown)">drop(</span>lock<span style="color:var(--pico-8-brown)">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-lime)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span>
</code>

<br>

<p>Yes, it uses a spinlock. Yes, it uses <code class="code">Ordering::SeqCst</code>. But if I am honest, at this point I don't care. It is better than running the tests on one thread, and it gets the job done.</p>

<br>

<img src="https://www.rismosch.com/articles/running-test-in-series/succeess.webp" style="display: block; max-width: 100%;" />

<br>

<p>Initially, I wanted to explain how this code works in detail and why, for beginners you know. But this got quickly out of hand, and if I would have included it here, then this blog post would've been 5 times as long. Concurrency is a big topic. You can write a book about it, and people have. If you aren't shy of C++, I highly recommend "C++ Concurrency in Action" by Anthony Williams.</p>

<br>

<p>If you don't know why this code works, and are not interested in the book I just recommended, understand this simplified explanation: </p>

<ul>
<li>Atomics are variables that are thread safe.</li>
<li>The while loop attempts to lock the AtomicBool.</li>
<li>If another test holds the lock, setting the lock will fail and the loop executes again. This may happen very, very often. But unless we succeed on setting the lock, the code will never leave the loop. It effectively waits. We say it <i>spins</i>, and this programming pattern is called a <i>spinlock</i>.</li>
<li>Rust is smart and drops values as soon as they are not used anymore. Thus, if we don't use the lock, it will immediately be dropped and the lock will be freed. The manual call <code class="code">drop(lock)</code> at the end of each test prevents the lock of being freed too early.</li>
<li><code class="code">drop()</code> is called, whether because the value falls out of scope, or because of a panic. No matter what our code does, <code class="code">drop()</code> will be called guaranteed. Therefore, it is safe to put cleanup code into it, like freeing our lock. This pattern is called a <i>drop-guard</i>.</li>
</ul>

<br>

<p>And that's all there is about it. Using this solution really boils down to just copying and then using it. I hope this may be helpful for someone &#128521;</p>]]></content:encoded></item><item><title>How to programm Button Down, Up and Hold with 3 lines of code</title><link>https://www.rismosch.com/article?id=button-down-up-and-hold</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">button-down-up-and-hold</guid><pubDate>Mon, 01 Aug 2022 10:12:56 +0200</pubDate><description>In this post I describe a quick and easy solution to compute the single frame, where a button was pressed down and released</description><content:encoded><![CDATA[<p>Maybe you are programming your own engine, and the API you are using to get buttons just returns whether a button is pressed or not. But more often than not, you only care about the single frame the button is pressed down, or released. Maybe you are already using an engine, that provides these features, but you want to implement a virtual button, and now you need to implement that behavior yourself.</p>

<p>Whatever your reason, you have a button that is either on or off, and you want to compute button down, up and hold. Here's a full implementation in Rust:</p>

<code class="code code_block">
#<span style="color:var(--pico-8-cyan)">[</span>derive<span style="color:var(--pico-8-washed-grey)">(Default)</span><span style="color:var(--pico-8-cyan)">]</span><br>
<span style="color:var(--pico-8-cyan)">pub struct</span> <span style="color:var(--pico-8-washed-grey)">Buttons</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;up: <span style="color:var(--pico-8-washed-grey)">u32</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;down: <span style="color:var(--pico-8-washed-grey)">u32</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;hold: <span style="color:var(--pico-8-washed-grey)">u32</span>,<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">pub trait</span> <span style="color:var(--pico-8-washed-grey)">IButtons</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">up</span><span style="color:var(--pico-8-washed-grey)">(</span><span style="color:var(--pico-8-cyan)">&self</span><span style="color:var(--pico-8-washed-grey)">)</span> -> <span style="color:var(--pico-8-washed-grey)">u32</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">down</span><span style="color:var(--pico-8-washed-grey)">(</span><span style="color:var(--pico-8-cyan)">&self</span><span style="color:var(--pico-8-washed-grey)">)</span> -> <span style="color:var(--pico-8-washed-grey)">u32</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">hold</span><span style="color:var(--pico-8-washed-grey)">(</span><span style="color:var(--pico-8-cyan)">&self</span><span style="color:var(--pico-8-washed-grey)">)</span> -> <span style="color:var(--pico-8-washed-grey)">u32</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">update</span><span style="color:var(--pico-8-washed-grey)">(</span>&<span style="color:var(--pico-8-cyan)">mut self</span>, new_state: &<span style="color:var(--pico-8-washed-grey)">u32)</span>;<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">impl</span> <span style="color:var(--pico-8-washed-grey)">IButtons</span> <span style="color:var(--pico-8-pink)">for</span> <span style="color:var(--pico-8-washed-grey)">Buttons</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">up</span><span style="color:var(--pico-8-washed-grey)">(</span>&<span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-washed-grey)">)</span> -> <span style="color:var(--pico-8-washed-grey)">u32 {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">self</span>.up<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">down</span><span style="color:var(--pico-8-washed-grey)">(</span>&<span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-washed-grey)">)</span> -> <span style="color:var(--pico-8-washed-grey)">u32 {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">self</span>.down<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">hold</span><span style="color:var(--pico-8-washed-grey)">(</span>&<span style="color:var(--pico-8-cyan)">self</span><span style="color:var(--pico-8-washed-grey)">)</span> -> <span style="color:var(--pico-8-washed-grey)">u32 {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">self</span>.hold<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">update</span><span style="color:var(--pico-8-washed-grey)">(</span>&<span style="color:var(--pico-8-cyan)">mut self</span>, new_state: &<span style="color:var(--pico-8-washed-grey)">u32) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">self</span>.up = !new_state & <span style="color:var(--pico-8-cyan)">self</span>.hold;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">self</span>.down = new_state & !<span style="color:var(--pico-8-cyan)">self</span>.hold;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">self</span>.hold = *new_state;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey)">}</span><br>
<span style="color:var(--pico-8-cyan)">}</span><br>
</code>

<p>You may or may not be able to read Rust. That's fine. The key things you need is the struct and its update function. The rest is just boilerplate stuff, to provide an interface to client code. So here's the solution again, with the unimportant stuff stripped away:</p>

<p class="code code_block">
<span style="color:var(--pico-8-cyan)">pub struct</span> <span style="color:var(--pico-8-washed-grey)">Buttons</span> <span style="color:var(--pico-8-cyan)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;up: <span style="color:var(--pico-8-washed-grey)">u32</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;down: <span style="color:var(--pico-8-washed-grey)">u32</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;hold: <span style="color:var(--pico-8-washed-grey)">u32</span>,<br>
<span style="color:var(--pico-8-cyan)">}</span><br>
<br>
<span style="color:var(--pico-8-cyan)">fn</span> <span style="color:var(--pico-8-brown)">update</span><span style="color:var(--pico-8-washed-grey)">(</span>&<span style="color:var(--pico-8-cyan)">mut self</span>, new_state: &<span style="color:var(--pico-8-washed-grey)">u32) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">self</span>.up = !new_state & <span style="color:var(--pico-8-cyan)">self</span>.hold;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">self</span>.down = new_state & !<span style="color:var(--pico-8-cyan)">self</span>.hold;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">self</span>.hold = *new_state;<br>
<span style="color:var(--pico-8-washed-grey)">}</span><br>
</p>

<p>Note: This wont compile. As I said, the boilerplate was removed. Treat it as pseudo code.</p>

<p>Let's dissect this, so you can adapt it to your programming language and use case. The <code class="code">Buttons</code> struct stores 3 values. Each value is a 32 bit unsigned integer. Each bit represents a single button, and whether it is pressed (1) or not (0). We need 3 ints, one for button down, button up and button hold. This means this struct stores 32 different buttons, and their down, up and hold state.</p>

<p>Depending on your usecase, 32 buttons may be too much or too little. So feel free to change it to a <spacoden class="code">bool</code> or an integer with more bits.</p>

<p>Now let's talk about the update function. It takes 2 parameters: <code class="code">self</code> and <code class="code">new_state</code>. <code class="code">self</code> in Rust is literally the same as the <code class="code">this</code> pointer in C/C++ and many other programming languages; it references the object itself, in this case an object of the <code class="code">Buttons</code> struct. <code class="code">new_state</code> is a snapshot of the signal, being fed into the buttons. This is simply your on/off signal.</p>

<p>The three lines in the update function are where the magic happens. The trick is, that <code class="code">self.hold</code> is updated last. Thus, when computing <code class="code">self.up</code> and <code class="code">self.down</code>, <code class="code">self.hold</code> stores the button value of the previous frame. If the previous frame was 1 and the current frame is 0, <code class="code">self.up</code> will be 1, otherwise 0. If the previous frame was 0 and the current frame is 1, <code class="code">self.down</code> will be 1, otherwise 0.</p>

<p>Note 1: This implementation uses the bitwise-AND operator <code class="code">&</code>. If you plan to use a <code class="code">bool</code> for your system, I recommend using logic-AND <code class="code">&&</code> instead, because <code class="code">&&</code> is lazy and thus <i>can</i> be a tiny bit faster (Potentionally. Maybe. Maybe not. I give no guarantees.)</p>

<p>Note 2: In Rust, the bitwise-NOT operator is <code class="code">!</code>. In your programming language it's probably <code class="code">~</code> (Potentionally. Maybe. Maybe not. I give no guarantees.)</p>

<img src="https://www.rismosch.com/articles/button-down-up-and-hold/diagram.png" style="display: block; margin: auto; width: 441px; max-width: 100%; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;" />

<p>Above is a diagram, visualizing the output of the code, run for 6 frames. The button is pressed on frame 2, 3 and 4 (<code class="code">new state</code>). Notice that <code class="code">button hold</code> has the same value as <code class="code">new state</code>. <code class="code">button down</code> is 1 only at frame 2, the first frame the button was pressed. And <code class="code">button up</code> is 1 only at frame 5, the first frame the button was released.</p>

<p>If you implement an interface like this implementation, you would call <code class="code">update()</code> each frame, where your input is handled. Then, wherever you have a reference to a <code class="code">Buttons</code> object, you can simply call <code class="code">down</code>, <code class="code">up</code> or <code class="code">hold</code> to get the desired value.</p>

<p>And that's literally it. Have a good one 😊</p>]]></content:encoded></item><item><title>Rebinding Controls via a RebindMatrix</title><link>https://www.rismosch.com/article?id=rebinding-controls-via-a-rebind-matrix</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">rebinding-controls-via-a-rebind-matrix</guid><pubDate>Mon, 11 Jul 2022 11:56:39 +0200</pubDate><description>I propose a RebindSystem, that is quite powerful but also easy to use. It uses matrices, which are inspired by ModMatrices, that are found on some Synthesizers.</description><content:encoded><![CDATA[<p>Every now and then, I see a post pop up online, discussing why there are many games that don't implement rebindable controls. And usually, the problem is swept under the rug with the answer "well, it's just too difficult." Actually, in this blogpost, I am trying to prove that it's not.</p>

<blockquote style="background-color:var(--pico-8-white); border: 5px solid var(--pico-8-cyan); padding: 20px;"><p>Every problem in computer science can be solved with a level of indirection.<p><cite>Professor Jay Black of the University of Waterloo &#183; Quote taken from: &#34;Game Engine Architecture&#34; by Jason Gregory, Third Edition, page 585</cite></blockquote>

<p>Ideally, your game does not care what controller is plugged into it. No matter if the controller is made by Microsoft, Sony or Nintendo, if it's a microwave or a banana. The player may want to play with any controller. You want to program against an interface that abstracts the inputs of the controller. What lies between the controller and this public interface, is your rebind system</p>

<img src="https://www.rismosch.com/articles/rebinding-controls-via-a-rebind-matrix/indirection_layer.gif" style="display: block; margin: auto; max-width: 100%;" />

<p>The rebind system I am proposing here, is somewhat original. Or at least, it's so uncommon in games that I couldn't find it via a quick google. So even if you have a working rebind system in place, this blogpost may still be interesting for you. The system I am proposing is both easy to use, but also stupidly powerful, so buckle up!</p>

<h2>Inspiration: Synthesizers</h2>

<p>First, I want to talk about synthesizers for a bit. You will see in a second, that synthesizers have a similar problem regarding rebindable controls. And I think it's worth discussing synths and the solutions they came up with, so that you can better understand my proposed solution. Synthesizers are quite a bit older than video games. The synth people had much more time to solve this issue than any video game dev. I just let myself be inspired. If you are a fellow synth nerd, you may find the following sections to be a bit oversimplified, but know that I primarily want to get the point across. If you have no idea about synthesizers, then don't worry, I will hand you along safely.</p>

<p>A synthesizers sound is dialed in via its various knobs and buttons. But once the sound is dialed in, it is more or less static. By that I mean, no matter how you press the key on the keyboard, the sound will always sound the same. That is somewhat lame, especially if you compare it to a guitar for example. A guitars sound can be modified quite a lot, depending how you strum it and how you finger it. For example, if you strike the strings strongly, you get a louder sound as if you just brush them lightly. Or when picking a single string, you can move the finger that is holding the string up and down, creating a pitch shift or vibrato. Thus, the guitar is quite an expressive instrument. The synth however, is not.</p>

<p>This is where <i>modulation</i> comes in. Sooner or later, synth people realized that the strength of how hard a key is struck can be measured, and this signal can be fed into the <i>amplifier</i>, thus making the sound louder or more silent. How hard a key is hit is often referred to as <i>velocity</i>. Or you could make a vibrato-like effect, by using a slow-moving wave, that changes the pitch slightly. Such a slow vibrato wave is usually called LFO, standing for Low Frequency Oscillator.</p>

<p>However, what if you want to be a bit more artistic? Maybe a pitch vibrato is boring. You want the vibrato to go to the amplitude of the sound instead. This would make something like a wah-wah-wah sound. If you are familiar with guitars, the tremolo-effect pedal works exactly like this. Or maybe you want the pitch of the sound to change, the harder you hit the key. This may be a little unconventional, but if you really want something like this, you need a rebind system. Things like LFO and velocity are called <i>modulation sources</i>, and things like pitch and amplitude are called <i>modulation destinations</i>, because the former can modulate the latter.</p>

<img src="https://www.rismosch.com/articles/rebinding-controls-via-a-rebind-matrix/rebind_modular.gif" style="display: block; margin: auto; width: 406px; max-width: 100%; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;" />

<p>The oldest synths where modular, where a single module would have a single function. So you would have one LFO module, one velocity module, one pitch module, one amplitude module, and you would connect them with cables. So, if you want a pitch-vibrato, you would patch a cable from the LFO to the pitch module. If you wanted an amplitude-vibrato, you would patch a cable from the LFO to the amplitude module. This gets the job done, but a lot of cables can get very messy very quickly. If you are a touring musician, such cables would only be a hassle, especially if one or more cables where to be unplugged accidently! So another solution was devised.</p>

<p>Instead of using external cables to connect modules together, you would have all modules on a single circuit board and have them connected internally. Then with a switch, you can simply change where the modulation is being routed to. This avoids all messes, but it's quite limiting. Because now, the LFO can only go to either the pitch, or the amplitude, not both. If you tried to implement a switch for every single routing, you would end up with so many switches, that it becomes unpractical.</p>

<img src="https://www.rismosch.com/articles/rebinding-controls-via-a-rebind-matrix/rebind_switch.gif" style="display: block; margin: auto; width: 406px; max-width: 100%; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;" />

<p>Some synths tried to find balance between cables and switches. On one hand, they wanted the absolute freedom to patch every modulation source to every destination, but on the other hand the compactness of cable-less synths. And they came up with the ModMatrix. The idea is simple: On the left side, you have modulation sources, and on the top, you have modulation destinations. A source is routed to a destination, if the cell they both cross is activated. If the cell is not activated, the source is not routed to the destination.</p>

<img src="https://www.rismosch.com/articles/rebinding-controls-via-a-rebind-matrix/polybrute_1.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<p>The image above is a picture of the ModMatrix of my Arturia PolyBrute. A cell is activated if it is glowing blue. In the picture above, you see that LFO 1 is routed to (1) Pitch Global and Velocity is routed to (2) Vca (for our purposes, simply think amplitude). I added some arrows in the picture below to highlight it better:</p>

<img src="https://www.rismosch.com/articles/rebinding-controls-via-a-rebind-matrix/polybrute_1_sketch.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<p>Okay that's cool and all, but what if two cells are active in the same row or column? Well, if cells are in the same row, this one modulation source is routed to multiple destinations. If the cells are in the same column, then all these modulation sources are routed to the same destination.</p>

<img src="https://www.rismosch.com/articles/rebinding-controls-via-a-rebind-matrix/polybrute_2.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<p>In the picture above, Velocity is both being routed to (1) Pitch Global AND (2) Vca. And in the picture below, BOTH Velocity and LFO 1 are routed to (1) Pitch Global (think of it as logical OR).</p>

<img src="https://www.rismosch.com/articles/rebinding-controls-via-a-rebind-matrix/polybrute_3.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<h2>The na&#239;ve solution</h2>

<p>So hopefully you understand the basics of a ModMatrix now. And maybe you know already how this applies to our rebind system. On the left of your <i>RebindMatrix</i>, we have the actual controls that come from our controller. And on the top, we have the interface that our game programs against. To route an actual control to the interface, we need to activate that specific cell.</p>

<img src="https://www.rismosch.com/articles/rebinding-controls-via-a-rebind-matrix/rebind_matrix.png" style="display: block; margin: auto; width: 375px; max-width: 100%; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;" />

<p>How do we actually program this?</p>

<p>At first, I wanted to make an <i>all powerful</i> rebind matrix. Meaning every button of every controller maps to every other available button. After implementing the keyboard controls and starting with the mouse, I've realized that this may not be a good idea. That is because in SDL2, the mouse, keyboard and gamepad are similar, but not quite the same. Thus, I didn't just need a RebindMatrix from keyboard to keyboard, and mouse to mouse, but also mouse to keyboard and keyboard to mouse. Things get even more hairy with the gamepad. I needed unique logic, for every single RebindMatrix. This doesn't scale.</p>

<img src="https://www.rismosch.com/articles/rebinding-controls-via-a-rebind-matrix/controller_rebind_matrices.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>Disaster struck when I decided to remove the sleep statement in my main gameloop. You see, at this point of development of my engine, the console output is literally the only thing that I can interact with. Primitive, but it works. And to better read the output, I use a sleep statement to slow down the loop. When the sleep statement is removed, the loop is able to run at full speed. When I removed it, I was shocked to discover, that the loop ran about 300-400 fps. As a gamer, this may sound amazing to you, but for me it raised huge red flags. Literally everything my gameloop was doing at this point, is some event stuff, framebuffering and control rebinding. This is relatively nothing, and yet I <i>only</i> get a couple hundred fps. This is bad. Real bad. This was before I even started implementing the gamepad. So I went back to the drawing board.</p>

<p>&#10013;Footnote: <span style="color:var(--pico-8-dark-grey);">If you are curious how performance could be <i>that</i> bad, my initial na&#239;ve implementation made heavy use of hashmaps, that mapped keyboard buttons to bools, and which were iterated one too many times. Due to the sheer amount of keyboard buttons, other simpler data structures didn't seem feasible at the time. But in the following sections, you will find a correct implementation, which uses integers, utilizing bitwise operations.</span></p>

<h2>The correct solution</h2>

<p>I was reconsidering what I actually needed from this system. The game that I want to make is still a vague, distant dream with loose goals and blurred requirements. But one way I want it to be playable is in a living room, sitting on a couch in front of a TV and a gamepad in my hand. This means, that the entire game has to be playable with a single gamepad. So I asked myself, is it absolutely necessary that my game supports all 200+ buttons, from all input systems, and them also being remappable? The answer is an obvious, ashamedly no.</p>

<p>Before we continue, there is something that you need to realize: There are a few things that are not rebindable. These include mouse position, mouse wheel and gamepad analog sticks (axes). This implies, that these have to be accessible, no matter which rebind solution will be actually implemented. But keyboard keys, mouse buttons and gamepad buttons are all either pressed down or released. Thus, they can easily be rebound to each other. Since the SDL2 mouse has a method to retrieve the entire button state as a single unsigned 32-bit int (u32), where each bit represents one button, I decided that all buttons I ever need fit into a u32. Thus, my keyboard, mouse and gamepad implementation all expose a single u32, that indicates their current button state.</p>

<p>"Hold on a second!" you may ask, "Doesn't a keyboard have more than 32 keys?" Yes, you are correct. But remember 2 paragraphs ago that I don't need that many buttons to play my game. The keyboard will eventually expose all its keys, which I'll implement the moment I require text input into the game, but only 32 of the keys will be sent to the rebind system. Thus, we only need 4 rebind matrices: keyboard to keymask, keymask to general, mouse to general, and gamepad to general. And because every control system exposes the same u32, and the output is the same, 3 of these 4 rebind matrices can use the same logic.</p>

<img src="https://www.rismosch.com/articles/rebinding-controls-via-a-rebind-matrix/input_rebind_matrix.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>Above is a diagram of the RebindMatrices. And below is a diagram of each input system, the values they expose, and how the data flows.</p>

<img src="https://www.rismosch.com/articles/rebinding-controls-via-a-rebind-matrix/input_system.webp" style="display: block; margin: auto; max-width: 100%;" />

<h2>Coding Keymasks and Buttons</h2>

<p>I will now be starting to talk code. I am currently writing my engine in Rust, so some basic knowledge about Rust syntax may be helpful for you, the reader. Other than the bitwise logic, I won't use complicated stuff. So even if you have limited Rust experience, if you have <i>some</i> programming experience, I think you can follow along.</p>

<p>Let's start with the keyboard keymask. The keymask routes a scancode to a button. A scancode is what SDL2 uses to identify a key on a keyboard. The type of a keymask is <code class="code">[Scancode; 32]</code>, which is simply an array of 32 scancodes. Consider the following example: The scancode for the A key is stored at index 13 in the array. That means, if the user presses the A-key, the keymask will set the 13th bit of the buttons to 1. The code to calculate a given button state from a keymask looks like this:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan);">impl</span> <span style="color:var(--pico-8-washed-grey);">Keyboard</span> <span style="color:var(--pico-8-cyan);">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">pub fn</span> <span style="color:var(--pico-8-brown);">update_state</span><span style="color:var(--pico-8-washed-grey);">(</span>&<span style="color:var(--pico-8-cyan);">mut self</span>, keyboard_state: <span style="color:var(--pico-8-washed-grey);">sdl2</span>::<span style="color:var(--pico-8-washed-grey);">keyboard</span>::<span style="color:var(--pico-8-washed-grey);">KeyboardState</span><span style="color:var(--pico-8-washed-grey);">)</span> <span style="color:var(--pico-8-washed-grey);">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">let mut</span> new_state = <span style="color:var(--pico-8-washed-grey);">0</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink);">for</span> (scancode, value) <span style="color:var(--pico-8-cyan);">in</span> keyboard_state.<span style="color:var(--pico-8-brown);">scancodes() {</span> <span style="color:var(--pico-8-green);">//&#127312;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink);">if</span> !value <span style="color:var(--pico-8-cyan);">{</span> <span style="color:var(--pico-8-green);">//&#127313;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink);">continue</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink);">for</span> i <span style="color:var(--pico-8-cyan);">in</span> <span style="color:var(--pico-8-washed-grey);">0</span>..<span style="color:var(--pico-8-washed-grey);">32</span> <span style="color:var(--pico-8-cyan);">{</span> <span style="color:var(--pico-8-green);">//&#127314;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink);">if</span> <span style="color:var(--pico-8-cyan);">self</span>.keymask<span style="color:var(--pico-8-washed-grey);">[</span>i<span style="color:var(--pico-8-washed-grey);">]</span> == scancode <span style="color:var(--pico-8-washed-grey);">{</span> <span style="color:var(--pico-8-green);">//&#127315;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new_state |= <span style="color:var(--pico-8-washed-grey);">1</span> &lt;&lt; i; <span style="color:var(--pico-8-green);">//&#127316;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey);">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown);">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">self</span>.buttons.<span style="color:var(--pico-8-brown);">update(</span>&new_state<span style="color:var(--pico-8-brown);">)</span>; <span style="color:var(--pico-8-green);">//&#127317;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey);">}</span><br>
<span style="color:var(--pico-8-cyan);">}</span><br>
</code>

<p>We iterate over the entire <code class="code">keyboard_state</code> &#127312;. If the scancode is not pressed down &#127313;, the bit can stay 0 and we can continue to the next scancode. Then we iterate over <code class="code">self.keymask</code> &#127314;. If the keymask contains the scancode &#127315;, the according bit in the <code class="code">new_state</code> will be set to 1 &#127316;. After all iterations, <code class="code">buttons</code> will be updated &#127317;. More on &#127317; in an upcoming blogpost. I came up with a neat trick to easily compute <i>button down</i>, <i>button up</i> and <i>button hold</i> &#128521;</p>

<p>The mouse is quite a bit easier:</p>

<code class="code code_block">
<span style="color:var(--pico-8-green);">// somewhere in impl Mouse</span><br>
<span style="color:var(--pico-8-cyan);">pub fn</span> <span style="color:var(--pico-8-brown);">update_state</span><span style="color:var(--pico-8-washed-grey);">(</span>&<span style="color:var(--pico-8-cyan);">mut self</span>, mouse_state: <span style="color:var(--pico-8-washed-grey);">sdl2</span>::<span style="color:var(--pico-8-washed-grey);">mouse</span>::<span style="color:var(--pico-8-washed-grey);">MouseState) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">let</span> new_state = mouse_state.<span style="color:var(--pico-8-brown);">to_sdl_state()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">self</span>.buttons.<span style="color:var(--pico-8-brown);">update(</span>&new_state<span style="color:var(--pico-8-brown);">)</span>;<br>
<span style="color:var(--pico-8-washed-grey);">}</span><br>
</code>

<p>We simply get the SDL2 state, change it to a <code class="code">u32</code> and then update its buttons. That's literally it. The gamepad is more complicated than the mouse, but compared to the keyboard it's a cakewalk:</p>

<code class="code code_block">
<span style="color:var(--pico-8-green);">// somewhere in gamepad.rs<br>
// called by the gamepads update function</span><br>
<span style="color:var(--pico-8-cyan);">fn</span> <span style="color:var(--pico-8-brown);">get_button_state</span><span style="color:var(--pico-8-cyan);">(</span>game_controller: &<span style="color:var(--pico-8-washed-grey);">GameController</span><span style="color:var(--pico-8-cyan);">)</span> -> <span style="color:var(--pico-8-washed-grey);">u32</span> <span style="color:var(--pico-8-cyan);">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">let mut</span> new_state = <span style="color:var(--pico-8-washed-grey);">0</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink);">for</span> (i, button) <span style="color:var(--pico-8-cyan);">in</span> ALL_BUTTONS.<span style="color:var(--pico-8-brown);">iter</span><span style="color:var(--pico-8-washed-grey);">()</span>.<span style="color:var(--pico-8-brown);">enumerate</span><span style="color:var(--pico-8-washed-grey);">() {</span> <span style="color:var(--pico-8-green);">//&#127312;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink);">if</span> game_controller.<span style="color:var(--pico-8-brown);">button(</span>*button<span style="color:var(--pico-8-brown);">) {</span> <span style="color:var(--pico-8-green);">//&#127313;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new_state |= <span style="color:var(--pico-8-washed-grey);">1</span> &lt;&lt; i; <span style="color:var(--pico-8-green);">//&#127314;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown);">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey);">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;new_state <span style="color:var(--pico-8-green);">//&#127315;</span><br>
<span style="color:var(--pico-8-cyan);">}</span><br>
</code>

<p><code class="code">ALL_BUTTONS</code> is a static array, which includes all gamepad buttons, and we simply iterate over it &#127312;. If it is pressed down &#127313;, we set the according bit to 1 &#127314;. Then we return <code class="code">new_state</code> &#127315;, so that the calling function can update the buttons afterwards.</p>

<h2>Coding the RebindMatrix</h2>

<p>Now that we have all the theory and preparation out of our way, we can finally implement the RebindMatrix. Are you ready? Let's do this:</p>

<p>The general input system is simply a fourth one, beside mouse, keyboard and gamepad. However, it references the buttons of the other systems, such that it can generate a single button state from them. The type of RebindMatrix is simply <code class="code">[u32; 32]</code>, meaning an array of 32 unsigned 32 bit integers. The entire rebind logic is simply this:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan);">impl</span> <span style="color:var(--pico-8-washed-grey);">General</span> <span style="color:var(--pico-8-cyan);">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">pub fn</span> <span style="color:var(--pico-8-brown);">update_state</span>(&<span style="color:var(--pico-8-cyan);">mut self</span>, mouse: &<span style="color:var(--pico-8-washed-grey);">Buttons</span>, keyboard: &<span style="color:var(--pico-8-washed-grey);">Buttons</span>, gamepad: &<span style="color:var(--pico-8-washed-grey);">Buttons) {</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">let</span> rebound_mouse =<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown);">rebind(</span>mouse, &<span style="color:var(--pico-8-cyan);">self</span>.rebind_matrix_mouse<span style="color:var(--pico-8-brown);">)</span>; <span style="color:var(--pico-8-green);">//&#127312;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">let</span> rebound_keyboard =<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown);">rebind(</span>keyboard, &<span style="color:var(--pico-8-cyan);">self</span>.rebind_matrix_keyboard<span style="color:var(--pico-8-brown);">)</span>; <span style="color:var(--pico-8-green);">//&#127313;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">let</span> rebound_gamepad =<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-brown);">rebind(</span>gamepad, &<span style="color:var(--pico-8-cyan);">self</span>.rebind_matrix_gamepad<span style="color:var(--pico-8-brown);">)</span>; <span style="color:var(--pico-8-green);">//&#127314;</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">let</span> new_state = rebound_mouse | rebound_keyboard | rebound_gamepad; <span style="color:var(--pico-8-green);">//&#127315;</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">self</span>.buttons.<span style="color:var(--pico-8-brown);">update(</span>&new_state<span style="color:var(--pico-8-brown);">)</span>; <span style="color:var(--pico-8-green);">//&#127316;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey);">}</span><br>
<span style="color:var(--pico-8-cyan);">}</span><br>
<br>
<span style="color:var(--pico-8-cyan);">fn</span> <span style="color:var(--pico-8-brown);">rebind</span><span style="color:var(--pico-8-cyan);">(</span>buttons: &<span style="color:var(--pico-8-washed-grey);">Buttons</span>, rebind_matrix: &<span style="color:var(--pico-8-washed-grey);">RebindMatrix</span><span style="color:var(--pico-8-cyan);">)</span> -> <span style="color:var(--pico-8-washed-grey);">u32</span> <span style="color:var(--pico-8-cyan);">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">let mut</span> result = <span style="color:var(--pico-8-washed-grey);">0</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">let mut</span> bitset = buttons.<span style="color:var(--pico-8-brown);">hold</span><span style="color:var(--pico-8-washed-grey);">()</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-pink);">while</span> bitset != <span style="color:var(--pico-8-washed-grey);">0 {</span> <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">let</span> bit = bitset & <span style="color:var(--pico-8-brown);">(</span>!bitset + <span style="color:var(--pico-8-washed-grey);">1</span><span style="color:var(--pico-8-brown);">)</span>; <span style="color:var(--pico-8-green);">//&#127317;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">let</span> index = bit.<span style="color:var(--pico-8-brown);">trailing_zeros()</span> <span style="color:var(--pico-8-cyan);">as</span> <span style="color:var(--pico-8-washed-grey);">usize</span>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">let</span> mask = rebind_matrix<span style="color:var(--pico-8-brown);">[</span>index<span style="color:var(--pico-8-brown);">]</span>; <span style="color:var(--pico-8-green);">//&#127318;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result |= mask; <span style="color:var(--pico-8-green);">//&#127319;</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bitset ^= bit; <span style="color:var(--pico-8-green);">//&#127317;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-washed-grey);">}</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;result <span style="color:var(--pico-8-green);">//&#127320;</span><br>
<span style="color:var(--pico-8-cyan);">}</span><br>
</code>

<p>First, we apply the RebindMatrix of mouse &#127312;, keyboard &#127313;, and gamepad &#127314;, to rebind their inputs. Then we simply bitwise-OR them together &#127315; and update our button state &#127316;. To apply a rebind matrix, I use the trick that I learned in <a href=" https://lemire.me/blog/2018/02/21/iterating-over-set-bits-quickly/" target="_blank" rel="noopener noreferrer">this</a> blogpost. Essentially, the while loop and the bit magic &#127317; allow me to iterate through all bits that are set to 1, with their respective indices. For example, <code class="code">0b00101001</code> would fire 3 times, at index 0, 3 and 5. Then I simply take the row of the rebind matrix at that index &#127318;, and apply it to the result &#127319;. And then finally, we return the resulted output &#127320;, such that <code class="code">update_state()</code> can use it further.</p>

<h2>Conclusion</h2>

<p>Phew, that was quite a mouthful. But as you saw in the code, it isn't that much, honestly. You just need some further boilerplate code around it, to make it work in your game, but you should now be well equipped to implement your own rebind system in your game.</p>

<p>But was it worth it? Well, if I remove the sleep statement with this implementation, I get about 9000 to 10000 fps, which is way above what I consider acceptable. But not only is performance acceptable, its usability is insane. If you are handicapped for example and have difficulties pressing multiple buttons at once, you can now easily map a single button to multiple others. You can also map different buttons to the same action if you want. And as a developer, I also got quite the utility out of it: Since each RebindMatrix is simply an array of integers, I can hotswap them at runtime. For example, if I want to disable the "jump" button for any reason, I can just set the according column of the matrix to 0, and change it back to the user setting, to enable it again.</p>

<p>All in all, I am quite happy with it, and I hope you find this useful in any way &#128522;</p>]]></content:encoded></item><item><title>Post Crisis</title><link>https://www.rismosch.com/article?id=post-crisis</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Other]]</category><guid isPermaLink="false">post-crisis</guid><pubDate>Sat, 11 Jun 2022 23:27:35 +0200</pubDate><description>A reflection after the crisis of my previous blogpost. I give my opinion about Rust and how I continue to write my gameengine.</description><content:encoded><![CDATA[<p>In my previous blogpost, I mentioned how I considered throwing in the towel, and build my game engine in Rust instead of C++. Two months later, how are things going?</p>

<p>Honestly, things are going fairly well. I've read "The Rust Programming Language" by Steve Klabnik and Carol Nichols, as well as "Rust for Rustaceans" by Jon Gjengset. The former is a good crash course on the basics of Rust, but too beginner friendly in my taste. I still recommend it, if you know nothing about Rust and want to learn it. However, the latter is absolutely amazing and it's exactly what I want in a programming book. But it definitely covers more advanced topics, and you need some programming experience to better understand the topics in the book.</p>

<img src="https://www.rismosch.com/articles/post-crisis/pic_1.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<p>C++ is powerful, but compared to Rust it feels clunky and, as I mentioned in my last blogpost, full of garbage that you aren't supposed to use. Every book about C++ that I have read so far introduced design patterns and concepts, that you as a programmer must uphold. Otherwise, you get unhandled exceptions and undefined behavior. However, Rust implements these concepts into the compiler and simply doesn't compile your program if you decide to break them. In Rust, these concepts are rules, not suggestions.</p>

<p>Programming in Rust feels very different than any other language that I have experienced so far. Usually, programming goes like this: You write some code and run it through your compiler or interpreter immediately afterwards. Then, while your program is running, you check if it works and then go back to programming. More often than not, some exception is thrown, or some UI element is displayed incorrectly, or something just behaves weirdly. You go back to programming, and fix any issues that you have encountered.</p>

<p>It's a different story in Rust however. Rust doesn't compile your code, if you don't please the burrow checker. And it can be rather frustrating to appease it, as designing data structures around the burrow checker can be very tough. Nevertheless, once your code does compile, it simply works. I can't tell you how blissfully satisfying running Rust code is. The compiler is telling you exactly what not to do. All the hardship you experience comes before you even run your code. With all other programming languages however, you experience misery while running your program, and you are left alone when things break.</p>

<p>Okay, besides falling in love with Rust, what did I actually program? For starters, here's the things that my engine can already do:</p>

<ul>
<li>Basic main loop</li>
<li>Framebuffer, to store data over multiple frames</li>
<li>Random Number Generator based on <a href="https://www.pcg-random.org/index.html" target="_blank" rel="noopener noreferrer">PCG</a></li>
<li>Simple SDL2 window</li>
<li>SDL2 event pump integration</li>
<li>Implementation of Mouse, Keyboard and Gamepad controls</li>
<li>REBINDABLE controls</li>
</ul>

<p>I will definitely make a blogpost about the last point, because I've came up with a solution, that is both easy to use, yet stupidly powerful, and I haven't seen anyone talk about it, so I guess it's somewhat original! Also, the whole repository is (in my opinion) very clean and I've written unit tests wherever I could, with custom testing utility. It's amazing, if I do say so myself &#128522;</p>

<img src="https://www.rismosch.com/articles/post-crisis/pic_2.png" style="display: block; margin: auto; width: 729px; max-width: 100%;" />

<h2>What's coming up next?</h2>

<p>I am taking a break from the engine. The next feature planned would be a multithreaded job system. That's complicated though, and I have a book in my pipeline which I want to read before I tackle multithreading. After that, some logging utility and finally some rendering. Let's see if it's going to be OpenGL or Vulkan; either way I am definitely going to break my neck with it.</p>

<p>Also, there are two other reasons why I want to take a break from the engine.</p>

<p>One: There are some issues on my websites which have been bugging me for quite a while now. I want to take some time to actually fix them.</p>

<p>And two: I want to make music again. After all, I describe myself as a programmer <b>and a music producer</b>. It's been quite a while since I actually made a song. Since then, I've been accumulating music gear. One year ago, I purchased the Arturia Polybrute. It's an amazing instrument and I love everything about it, but I have yet to make a song with it. The time flies whenever I decide to play with it. It's so easy to get lost in the soundscape….</p>

<img src="https://www.rismosch.com/articles/post-crisis/pic_3.webp" style="display: block; margin: auto; width: 100%;" />

<p>Also, this just arrived in my mail: The Dirtywave M8 Tracker! I've heard amazing things about it and I literally waited half a year for it to arrive, and last week it finally came! As of writing this post, I have absolutely no idea how to handle it. It definitely isn't plug and play and it seems to have a learning curve to it. Still, I am so stoked right now &#128522;</p>

<img src="https://www.rismosch.com/articles/post-crisis/pic_4.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<p>To sum up everything: 2 months ago, I felt absolutely miserable and I wasn't happy how my project is going. Today, everything is awesome<a href="https://youtu.be/StTqXEQ2l-Y" target="_blank" rel="noopener noreferrer">!</a> I feel very good about the game engine and its progress, and I am very very satisfied with Rust. Though, I decided to take a break from the engine, to fix things on the website and to make music &#127925;</p>]]></content:encoded></item><item><title>Crisis</title><link>https://www.rismosch.com/article?id=crisis</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Other]]</category><guid isPermaLink="false">crisis</guid><pubDate>Sun, 10 Apr 2022 08:52:53 +0200</pubDate><description>My project to write a gameengine hit a wall. In this post I go over my struggles and possible ways to overcome them.</description><content:encoded><![CDATA[<img src="https://www.rismosch.com/articles/crisis/thumbnail.webp" style="display: block; margin: auto; width: 100%; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;" />

<p style="font-style: italic; color:var(--pico-8-dark-grey);">Thumbnail credit: "VOID KING", found during the 2022 April fools event on r/place, reddit</p>

<p>I've been reading about how game engines work since September last year. And I've been trying to program one since January. I have learned a lot, but made frustratingly little progress. And now, I've hit a roadblock so hard, that I am reconsidering the entire project altogether.</p>

<p>I programmed my engine in C++, because it is fast and the industry standard for this kind of job. It's fun, really. I have read a few books on the language, and I think I know my way around pointers, memory management and the things alike. But while things were doing fine, most of the code I've written was untested. This is because I have lost the motivation to write unit tests at my fulltime job, and thus I attempted to write not a single test. However, I quickly realized that without unit tests, I can't possibly expect all the edge cases to work. Once they turn up in the engine, it could spell disaster. With unit tests I can throw edge case after edge case at my code and see what happens, stomping out bugs before they can even occur.</p>

<p>I know what unit tests are, how to write and design them. I simply never did it in C++ before. So my thinking was optimistic: I relearn the syntax and that's it. Sadly, there were multiple issues ahead. First of all, ReSharper just sucks. Its IntelliSense constantly shows errors in the code editor, despite the fact that the compiler has not a single issue with my code. Then there is also the fact that ReSharper doesn't find all the tests I write. Luckily the Test Explorer of Visual Studio finds them effortlessly, and thus I can use that instead. It's quite frustrating that ReSharper does the opposite of what it's designed to do.</p>

<p>The worst thing however has nothing to do with ReSharper, and it has to do with the Linker and how it refuses to Link pdb files. It does fine linking them in my actual engine, but for whatever reason, it doesn't like to do that for my tests. This means that even though my tests compile and run, I can't debug and step through them.</p>

<img src="https://www.rismosch.com/articles/crisis/pic_2.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>With the books I've read, I feel like I have accumulated a lot of knowledge about C++ and the cool stuff you can do with it. But the things that I fight with most are not the concepts themselves, but the tools I am working with: The IDE and ReSharper.</p>

<p>Now thinking about it, it was always the tools that I was fighting with. Moving files in Visual Studio is horror, as it just updates references and doesn't actually move the files. Then there is the fact that the directories in the Solution Explorer aren't actually directories, but "Filters", which I carefully need to manage so they look like the folder structure beneath. Or how about the issue, that when I run the tests, some process is hoarding all the obj files, meaning that the Linker can't open them when I try to build the project some time afterwards. This is fixable by simply running a "Clean Solution". But this inevitably means that the next build has to build the entire solution, which is unnecessary and takes an unreasonable amount of time.</p>

<p>I feel like I know how to drive a car, maintain it and even build custom parts for it, but I just can't open the car door. I am aware of the dangers of driving a car, like causing accidents, but also the cool stuff I can do, like drifting or what I am most excited about: <i>parallel parking</i>. But these are absolutely non-issues for me, because I just can't open the fucking door.</p>

<p>So, where do I go from here? As far as I can see, there are 3 paths for me to take: 2 painful ones and 1 very scary one. I could just bite the bullet and stick with Visual Studio + ReSharper, trying to find that hidden Linker setting to make everything work again. But considering that this wasn't the first time I had problems with the Linker, I don't think I will have much success with that approach. Thus, another option is to switch to a simple Text editor + CMake. Browsing r/cpp nowadays, it seems that this second option is very popular. But this requires me to learn CMake and I probably need to restructure my entire engine. And then there is also no guarantee that the Linker is still happy with the garbage I am throwing at it. These are the 2 painful solutions to my problem, but there is a third, and very scary one: Rewriting everything in another language.</p>

<img src="https://www.rismosch.com/articles/crisis/pic_3.svg" style="display: block; margin: auto; max-width: 100%;" />

<p>Ever since I started this project, there is this nagging thought at the back of my head: What if C++ dies tomorrow? C++ is an established, successful and popular programming language, but it's no secret that it's old. As such, one disadvantage of C++ is the fact that it accumulated a lot of garbage over time. For big companies and century old code wizards this may be no issue, since they know what to use when and how. But for me as a beginner, sifting through all that garbage is cumbersome. Maybe the issues that I have laid down so far are actual non issues, but simply a result of my poor understanding of what is garbage and what is not. Though this begs the question: How do I know which of the stuff I am using is garbage? All of the books I've read talk about pointers and how the language works, not about how I need to set up my damn compiler.</p>

<p>So, if one option is to face constant struggle via trial and error, and the other to rewrite potentially everything to make it magically work with CMake (which may not work btw), then why don't I just rewrite everything in a newer language? I don't know how long C++ will last. Maybe it doesn't die tomorrow and it will last for another 100 years. But switching languages feels like the safe bet. Though I have to mention that with my experience so far, everything that felt like a safe bet always found a way to hurt me in some way. Though considering my other options, switching languages may be the least painful one that I have.</p>

<img src="https://www.rismosch.com/articles/crisis/pic_4.webp" style="display: block; margin: auto; width: 400px; max-width: 100%;" />

<p>And thus I want to take a shot at Rust. I've heard good things about it. What intrigues me most is that it's comparable in performance and low level to C++ (allegedly). But then Rust also provides a <a href="https://doc.rust-lang.org/nightly/rustc/platform-support.html" target="_blank" rel="noopener noreferrer">tier list</a> of supported platforms. This in itself is a deep relief for me. With C++, even writing a single line of code can sometimes feel very stressful, as you are aware that it may or may not work on all platforms. But Rust itself guarantees that my code definitely works on certain platforms. I hope that I simply don't need to have as much concern about platform independent code as with C++.</p>

<p>So my plan is set: I try out Rust. I throw my bad code at it and see how it responds. In the worst-case scenario, Rust throws the garbage back at me and refuses to do what I want it to do. But in that case, I can then choose: Do I stick with it, or do I go back to my C++ code? What this means is, that in a couple of months down the line, I actually have options on what to do. And considering that the development stage of my engine is so early, I can afford to try out stuff and see what works.</p>

<img src="https://www.rismosch.com/articles/crisis/pic_5.png" style="display: block; margin: auto; width: 375px; max-width: 100%; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;" />

<p>Okay, so it feels like I am attempting to do the job properly now, or how we say in German: "Ich versuche N&#228;gel mit K&#246;pfen zu machen." But there is one thing left, that I want to set straight: The state of my blog.</p>

<p>I haven't titled this blogpost "Crisis" for no reason. And it's not just about me crying about the fact that I am too stupid for C++. No. It's also that I am unhappy with my current life and the work I am doing. The Void King in the thumbnail visualizes my current feelings very well to be honest.</p>

<p>I really love science, and as such I consume a lot of scientific and educational content on the internet, most notably YouTube. While this is a lot of fun, I can't help but feel very useless while consuming such content on the internet. There are amazing people who educate about fascinating stuff. They are doing incredible experiments and demonstrations. I love it. But as much as I love it, it greatly puts all my work to shame. I am here, sitting in my room, debating what language to use or how to name my variables. And then there is <a href="https://youtu.be/2Vrhk5OjBP8" target="_blank" rel="noopener noreferrer">this dude</a> on YouTube, who actually performed Veritasiums thought experiment, to correct him. (I freaking love this dude and his videos. I don't want to sound like I am discrediting him.)</p>

<p>I want to add to this world. But I did not study science. I studied IT. All of the stuff I know, both science and IT, I have learned from other people. And all these people are better at explaining than I could ever be. As a concrete example: This year I fully understood how Unicode works. I even implemented working(!) UTF-8 and UTF-16LE encoders into my engine. And I wrote a blogpost about it. But why would anyone read my crappy blog, when there are better explanations out there? For example <a href="http://www.joelonsoftware.com/articles/Unicode.html" target="_blank" rel="noopener noreferrer">this</a> blogpost, or <a href="https://youtu.be/_mZBa3sqTrI" target="_blank" rel="noopener noreferrer">this</a> talk on YouTube.</p>

<img src="https://www.rismosch.com/articles/crisis/pic_6.webp" style="display: block; margin: auto; max-width: 100%;" />

<p>I concluded that my blog doesn't add anything. It has no value, neither to me, nor to anyone else. And as such, I decided to delete my blogposts about my engine. I will try to post stuff which actually has value. An example of something with value would be my blog about how I wrote this very website: <a href="https://www.rismosch.com/article?id=i-made-a-website-only-with-notepad-plus-plus" target="_blank" rel="noopener noreferrer">LINK</a></p>

<p>While this isn't a tutorial that tells you step by step on how to write a website, it condenses a lot of information into a couple of chapters, about what I have learned on how to make a website. My findings may or may not be best practice, or up to todays standards, but it does work. And I feel the fact that it does work so well, is very important to share.</p>

<p>I hate that this blogpost ends on such a low note. But I feel like it is necessary for the 2 people who read this blogpost, and for myself. I need to grow in my abilities: Both in improving my programming skills and in dealing with huge projects. I don't know how things will look in the future. Only time will tell.</p>]]></content:encoded></item><item><title>Why people love Bad Art</title><link>https://www.rismosch.com/article?id=why-people-love-bad-art</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Other]]</category><guid isPermaLink="false">why-people-love-bad-art</guid><pubDate>Sat, 09 Oct 2021 06:39:14 +0200</pubDate><description>My take, on why people prefer different kinds of art. I go over modern, avantgarde, challenging and popular art, and classify which is liked by whom.</description><content:encoded><![CDATA[<p>One of my most favorite music albums of all time is Philosophy of the World, by The Shaggs. Though whenever I share this masterpiece from 1969, I always get the same responses: "Oh god, they are totally out of tune and the rhythm is all over the place! Can you even consider this music?"</p>

<img src="https://www.rismosch.com/articles/why-people-love-bad-art/shaggs.webp" style="max-width:100%; width: 500px; margin:auto; display: block;" />

<p style="font-style: italic; color:var(--pico-8-dark-grey);">Cover of Philosophy of the World, The Shaggs, <a href="https://www.youtube.com/watch?v=jQqK1CjE9bA" target="_blank" rel="noopener noreferrer">via YouTube</a><p>

<p>To clear any ambiguity, yes, I do love this album. I don't make fun of the band, nor do I participate in schadenfreude. I really do, in fact, greatly enjoy this album. And I am not the only one who enjoys this music; many others have voiced their positive opinions of this album. Most famously, Kurt Cobain put this album in the Top 5 of his most favorite albums.</p>

<p>How can most people question the validity of such a piece of art, yet be so highly regarded by others? How can it be, that some people despise absolute masterful works of art? "Why do people enjoy <span style="font-style: italic;">bad</span> art, and not the <span style="font-style: italic;">good</span> art like me?" Well,</p>

<h2 style="text-align: center;">Art in itself, is meaningless.</h2>

<p>The source of the Shaggs that I have linked above lead to a YouTube video, that is ultimately composed of just 1s and 0s, which eventually get turned into variable air pressure by your speakers. Leonardo da Vinci's Mona Lisa is just Oil on some wood. Michelangelo's David is just a rock, marble to be precise, in a specific shape. Every art piece in the world is nothing but some kind of material in some kind of format. And there is nothing inherently special about anything. To appreciate and to give art meaning, we have to put it into some kind of context. Without context, art ceases to exist.</p>

<div style="margin: auto; display: block;">
<img src="https://www.rismosch.com/articles/why-people-love-bad-art/mona_lisa.webp" style="width:49%; margin:auto; display:inline_block;" />
<img src="https://www.rismosch.com/articles/why-people-love-bad-art/david.webp" style="width:49%; margin:auto; display:inline_block;" />
</div>

<p style="font-style: italic; color:var(--pico-8-dark-grey);">
	Left: Mona Lisa, Leonardo da Vinci, Public domain, via Wikimedia Commons<br>
	Right: David, Michelangelo, <a href="https://creativecommons.org/licenses/by/3.0" target="_blank" rel="noopener noreferrer">CC BY 3.0</a>, via Wikimedia Commons
<p>

<p>The Mona Lisa is a masterpiece, because it is more than just oil on wood. It depicts a woman, and while other paintings attempt similar things, the Mona Lisa excels on a technical and compositional level. David is a similar story. It is a rock, yes, but it's astonishing how something so inflexible and solid can depict a human being, a thing to be made out of flesh and blood.</p>

<p>While a lot of art generates its own context via expertise, context can also be put on art artificially. One infamous example is the story of Robert Florczak, an artist and illustrator, who tests his students to analyze a Jackson Pollock painting. The students quickly comment on the painting, it's composition and why it is good. It manages to invoke emotional reactions in the students. But eventually, Robert pulls the rug from under the students and reveals that actually, this "painting" was nothing more but a closeup of Robert's dirty apron.</p>

<p>The intention of this story is to point out how modern art is nonsensical and indistinguishable from garbage. It's an attempt at proving how modern art is objectively bad. However, I don't think this is the correct takeaway. While it was nothing more but a dirty apron, it did in fact invoke emotional reactions in the students. The painting, being fake or not, managed to create a reaction. Not because there is something about it which makes it scream "I am art", but simply because the students were expecting it to be art. Simply by putting it into the context of "this is art", the dirty apron became art in itself.</p>

<img src="https://www.rismosch.com/articles/why-people-love-bad-art/studio_apron.webp" style="width:100%; margin:auto; display: block;" />


<p style="font-style: italic; color:var(--pico-8-dark-grey);">Studio Apron, Robert Florczak, via <a href="https://youtu.be/lNI07egoefc?t=175" target="_blank" rel="noopener noreferrer">YouTube</a><p>
<p>And thus, we come back to The Shaggs and their album. There are two main ways to contextualize it. One is the story behind it: The 3 girls who made up the band were sisters, and their father was convinced that his daughters would become world famous. Using most of their savings, they recorded an album in one day, despite all of them having little to no musical knowledge. What came out of this is the Philosophy of the world.</p>

<p>While the context of questionable parenting explains why the music is the way it is, it still doesn't quite grasp why the album is so beloved. The second context is to simply realize, that nothing like this album exists in the world. Every music is inspired by something else, and every musician puts their own values and interests into the music they make. The music of The Shaggs doesn't have this inspiration. Even if they had, their lack of skill couldn't possibly translate the inspiration into the music. Because of this, we have an album that lacks any kind of inspiration, and thus is 100% creative and 100% unique. Such music, created by lesser artists, is often put under the general term "outsider music". Music of this style managed to generate a small cult following, due to the absolute uniqueness of its sound.</p>

<p><br></p>

<p>Now, despite my reasoning why I like The Shaggs, you may still argue, even though they are unique, they are still out of tune, and their rhythm is still all over the place. You may argue, even though I am correct with their uniqueness, I can't possibly argue that it is good music, right? Yes, you are correct, kinda. The vast majority of music I listen to is in tune and follows clear rhythmic structure. And all the music I actually make is an attempt to sound good (whatever my definition of good is). But despite this, I and many others are still able to greatly enjoy The Shaggs. But this begs the question, why do people enjoy it anyway? Who are these people who enjoy such bad music?</p>

<p>I've noticed a clear trend that people who create (e.g. other musicians, people who draw or paint, people who make videos, artists in general) usually fall under the type of person who would enjoy The Shaggs. People who are not artists, and thus consume more than they create, usually have a clear view of how art is supposed to be like. Anything that doesn't fit this view or dares to challenge it, is more often than not faced with negative feelings. Art, which has the only purpose to entertain the broadest range of people, plays into the expectations of the audience. I like to call the context this art falls into, as "consumer space". Art that doesn't fall into consumer space and is enjoyed by creators, consequently falls into what I like to call "creator space".</p>

<img src="https://www.rismosch.com/articles/why-people-love-bad-art/creator_consumer.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;" />

<p style="font-style: italic; color:var(--pico-8-dark-grey);">A Venn diagram, showing consumer- and creator space, in which art can reside<p>

<p>The Shaggs don't fall into consumer space, because their utter lack of skill challenges what most people consider music in a very extreme way. Creators however tend to enjoy such art, because they enjoy art in a completely different way. I talked about this in my <a href="https://www.rismosch.com/article?id=the-three-stages-of-competent-enjoyment"  target="_blank" rel="noopener noreferrer">last blogpost</a>. Essentially, as the creator becomes accustomed to the media they create, the magic is broken and the fulfillment of expectations aren't exciting anymore. What's more thrilling for creators isn't the simple consumption of media, but the challenge of their expectations.</p>

<p>This is the ultimate reason why The Shaggs are disliked by consumers, but enjoyed by creators. Consumers dislike how The Shaggs challenge their expectations, while creators exactly enjoy how their expectations get challenged.</p>

<p><br></p>

<p>Okay, this seems to make sense, but we are still missing a very important detail: Art is messy, and not as black and white as I have depicted it so far. While pop music is fairly popular, you don't need to spend much time looking for people, who vocally protest against pop music and claim how tasteless, meaningless and "surface-level" it is. What I am trying to say is, even though consumers are expecting their art to be a certain way, they still know that complete fulfillment of expectations is boring. The industry is trying to satisfy everyone, but as a direct consequence of this, they aren't satisfying anyone.</p>

<p>Thus comes the art which lives in both consumer- and creator space. Such art is experimental enough to break the blandness of the industry and to surprise the consumer, but it doesn't shock the consumer, because it isn't too experimental.</p>

<img src="https://www.rismosch.com/articles/why-people-love-bad-art/prism.webp" style="width:100%; margin:auto;" />

<p style="font-style: italic; color:var(--pico-8-dark-grey);">Imitation of the album cover art of The Dark Side of the Moon by Pink Floyd<p>

<p>Maybe the best example of such art would be The Dark Side of the Moon by Pink Floyd. This album, praised by a lot of people, managed to hit the perfect balance between avantgarde and yet poppy. At the time of its release, the album wasn't well received actually. It was more poppy than the bands earlier works, thus dissatisfying creators. But it was also too avantgarde to be regarded as pop, thus dissatisfying consumers. However, over time the general opinions changed, as people realized that The Dark Side of the Moon is equally as interesting for creators, as it is for consumers. Creators became satisfied, as it is not what you would first expect from rock. And consumers became satisfied, because even though all that experimental sound design is going on, for the most part it still sounds like progressive rock. Despite all the uniqueness, this album still has a sound that you would expect to hear on the radio.</p>

<p>Such art that lives in both consumer- and creator space is truly special, as it manages to satisfy pretty much <span style="font-style: italic;">everyone</span>. It has the potential of capturing the zeitgeist of entire generations and it is usually this type of art that manages to survive history.</p>

<p><br></p>

<h2>Conclusion</h2>

<p>So, to wrap this blogpost up: To be appreciated, Art has to reside in some kind of context or space. Usually, Art falls into either creator- or consumer space, depending if it challenges the audiences' expectations or not. While most art falls into these two contexts, there exists special art that manages to live in both. More often than not, such art manages to capture the current zeitgeist of our society and defines our culture.</p>

<p>But at the end of it all, we shouldn't forget that subjectivity is still the end-all-be-all. If you still consider The Shaggs to be an assault on music, then so be it. Everyone has preferences; it would be dishonest of me to claim that there isn't music I don't like. Most notable I greatly detest music, where I notice the over-the-top production of a mix. But no matter what art you like or dislike, it is objectively wrong to call it bad, because someone actually made it. And it is for this reason, that there is at least one person, who enjoys an art piece, no matter how "bad" it actually is.</p>]]></content:encoded></item><item><title>The three Stages of Competent Enjoyment</title><link>https://www.rismosch.com/article?id=the-three-stages-of-competent-enjoyment</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Other]]</category><guid isPermaLink="false">the-three-stages-of-competent-enjoyment</guid><pubDate>Thu, 07 Oct 2021 10:59:00 +0200</pubDate><description>A short blogpost, in which I document the three levels, one can find themself in, to enjoy art.</description><content:encoded><![CDATA[<p>It seems like every week, someone posts on <a href="https://www.reddit.com/r/gamedev/" target="_blank" rel="noopener noreferrer">r/gamedev</a> about how they aren't enjoying video games anymore, simply because they started learning gamedev. I myself definitely went through this, and I bet most people doing gamedev had similar experiences. If you are currently in the spot where you think you will never enjoy videogames anymore, I can assure you that it won't stay that way. As a matter of fact, after you gain more experience, videogames will be more fun than ever before.</p>

<p>I have developed what I call "The 3 stages of competent enjoyment", a model of different stages that describes what most people will go through. So let's just jump straight into it.</p>

<img src="https://www.rismosch.com/articles/the-three-stages-of-competent-enjoyment/picture.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;" />

<h2>Stage 1: Incompetent Enjoyment</h2>

<p>At this stage, you have no idea how videogames work. Maybe you have heard a bit about gamedev here and there, but mostly videogames are just magic to you. And just like magic, it's the awe, the spectacle what makes you enjoy games.</p>

<p>Most of the human population is at this stage. Most people don't care about gamedev and that is fine. You don't need to be a 5-star cook to judge if the food you were served is tasty or not.</p>

<h2 style="margin-top: 50px;">Stage 2: Competent Unenjoyment</h2>

<p>But people interested in gamedev won't stay at stage 1, and decide to persue it. Stage 2 is fairly easy to reach. All it takes to reach stage 2 is to start learning. Once you start learning about gamedev, you are discovering how the magic works and realize it's all smokes and mirrors. As a consequence of this, the magic will break. You become disillusioned and the spectacle is gone.</p>

<p>It is this stage, that makes people question if their decision to get into gamedev was a mistake or not. At stage 1, spectacle was everything that made videogames worthwhile. But now at stage 2, there is nothing left and videogames simply aren't as enjoyable anymore. Gamedev stole the one and only thing, that made videogames amazing.</p>

<h2 style="margin-top: 50px;">Stage 3: Competent Enjoyment</h2>

<p>Things won't stay at stage 2 forever. Eventually you will gain more experience, and with it, you will discover new enjoyment in videogames. You see, at stage 1, you cannot possibly understand why a game is made in the way it is, nor can you appreciate it's design. This is because you simply don't know why games are the way they are. At stage 3 however, you have mastered the basics and are amazed by the design itself.</p>

<p>It is this stage where you begin to realize, how the game manipulates your behavior, to craft a specific experience. While the game builds this wonderland of fake environments, fake characters and fake mechanics, you begin to see through it, like Neo sees through the matrix. This skill is deeply enjoyable in itself.</p>

<p>The spectacle is long gone, but at this point you don't require it anymore, because you found something more enjoyable.</p>

<h2 style="margin-top: 50px;">Conclusion</h2>

<p>Now, this is most definitely not scientific, as it's just anecdotal. But I think there is at least some truth to it. I also think that this 3-stage-model is applicable to different media as well. For example, I went through the same with music production. As I began to make music myself, I was disgusted by the industry, how everyone uses the same cheap tricks and that seemingly everyone is only in it for the money. But now I listen to all kind of music, different creators and even weird stuff like Philosophy of the World by The Shaggs (more on that in the next blogpost). And more often than not, the weirder and questionable the music is, the more I tend to enjoy it.</p>

<p>Maybe Visual Artists, e.g. people who paint and draw, but also video makers or crafters go through the same or similar changes. But whatever you are doing, more experience will most certainly make you enjoy your media of choice even more!&#128522;</p>]]></content:encoded></item><item><title>A neat Trick to Debug Exceptions in C#</title><link>https://www.rismosch.com/article?id=a-neat-trick-to-debug-exceptions-in-c-sharp</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">a-neat-trick-to-debug-exceptions-in-c-sharp</guid><pubDate>Tue, 24 Aug 2021 12:29:22 +0200</pubDate><description>Using the when-keyword to better debug exceptions in C#.</description><content:encoded><![CDATA[<h2>The Problem</h2>

<p>Assume we have a method called <code class="code">UnsafeMethod()</code>, which throws an exception upon calling it. What we want to do is to debug this method and find out where this exception comes from. The na&#239;ve approach is to simply surround it with a <code class="code">try-catch</code>, and set a debug point in the <code class="code">catch</code>-block:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan);">try</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;UnsafeMethod<span style="color:var(--pico-8-blue);">(</span><span style="color:var(--pico-8-blue);">);</span><br>
}<br>
<span style="color:var(--pico-8-cyan);">catch</span> <span style="color:var(--pico-8-blue);">(</span><span style="color:var(--pico-8-purple);">Exception</span> e<span style="color:var(--pico-8-blue);">)</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine<span style="color:var(--pico-8-blue);">(</span>e<span style="color:var(--pico-8-blue);">);</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">throw</span>;<br>
}
</code>

<p>When the debugger jumps into the <code class="code">catch</code>-block, we know that an exception has been thrown, and we get the exception-object which has been generated. While this may seem okay at first, it isn’t ideal. If the exception comes from lesser written code, the exception itself may proof to be very unhelpful to diagnose the problem. More importantly: Even though we know that <code class="code">UnsafeMethod()</code> threw the exception, if the method is hundreds of lines long and it calls various other methods, we still don’t know where that exception came from.</p>

<p>The latter reason happens by design. When an exception is thrown, execution of the program is stopped and an exception-object is handed up the callstack, until some code handles it via a <code class="code">try-catch</code>. This means an exception naturally collapses the callstack. When the program reaches the <code class="code">catch</code>-block for whatever reason, everything that happened in the <code class="code">try</code>-block is now collapsed and impossible to retrieve. But there is a way to look into the state of the <code class="code">try</code>-block, before the <code class="code">catch</code>-block is even executed.</p>

<h2>The Solution</h2>

<code class="code code_block">
<span style="color:var(--pico-8-cyan);">try</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;UnsafeMethod<span style="color:var(--pico-8-blue);">(</span><span style="color:var(--pico-8-blue);">);</span><br>
}<br>
<span style="color:var(--pico-8-cyan);">catch</span> <span style="color:var(--pico-8-blue);">(</span><span style="color:var(--pico-8-purple);">Exception</span> e<span style="color:var(--pico-8-blue);">)</span> <span style="color:var(--pico-8-cyan);">when</span> <span style="color:var(--pico-8-blue);">(<span style="color:var(--pico-8-cyan);">new</span> <span style="color:var(--pico-8-black);">Func</span>&lt;<span style="color:var(--pico-8-cyan);">bool</span>&gt;<bool>(() => <span style="color:var(--pico-8-cyan);">true</span>)())</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine<span style="color:var(--pico-8-blue);">(</span>e<span style="color:var(--pico-8-blue);">);</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">throw</span>;<br>
}
</code>

<p>If we use the <code class="code">when</code>-statement, put inside a delegate which returns a bool and set a debug point inside that delegate, then we can look into the <code class="code">try</code>-block. When the program reaches the delegate, then we can simply use the debugger and look into the callstack, and see where exactly the exception came from.</p>

<p>So, what is the <code class="code">when</code>-statement and why does this work? The <code class="code">when</code>-statement allows the <code class="code">catch</code>-block to be executed conditionally. If the condition evaluates to <code class="code">true</code>, the exception is caught and the <code class="code">catch</code>-block is executed. If the condition evaluates to false, then the exception is NOT caught and continues to be handed up the callstack.</p>

<p>Because of the <code class="code">when</code>-statement, two different scenarios can happen: Either the exception is being caught, or it is being thrown at the original position. Because the <code class="code">when</code>-statement can cause these two different behaviors, the callstack has to be kept intact during the evaluation of the <code class="code">when</code>-statement, just in case the exception is not being caught. And this is why our trick works: Because we put a delegate as the condition in the <code class="code">when</code>-statement, we can halt the evaluation of the <code class="code">when</code>-statement and then look into the still intact callstack. Thus, if the debugger reaches our delegate, the state of the <code class="code">try</code>-block is conserved.</p>

<p>Alternatively, you may want to write a method, which makes it a bit easier for you:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan);">public</span> <span style="color:var(--pico-8-purple);">bool</span> LogException<span style="color:var(--pico-8-blue);">(</span><span style="color:var(--pico-8-purple);">Exception</span> e, <span style="color:var(--pico-8-purple);">bool</span> shouldCatch = <span style="color:var(--pico-8-cyan);">false</span><span style="color:var(--pico-8-blue);">)</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine<span style="color:var(--pico-8-blue);">(</span>e<span style="color:var(--pico-8-blue);">);</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">return</span> shouldCatch<span style="color:var(--pico-8-blue);">;</span><br>
<span style="color:var(--pico-8-blue);">}</span>
</code>

<p>And then use it like this:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan);">try</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;UnsafeMethod<span style="color:var(--pico-8-blue);">();</span><br>
}<br>
<span style="color:var(--pico-8-cyan);">catch</span> <span style="color:var(--pico-8-blue);">(</span><span style="color:var(--pico-8-purple);">Exception</span> e<span style="color:var(--pico-8-blue);">)</span> <span style="color:var(--pico-8-cyan);">when</span> <span style="color:var(--pico-8-blue);">(</span>LogException<span style="color:var(--pico-8-blue);">(</span>e<span style="color:var(--pico-8-blue);">)) { }</span>
</code>

<p>With this, the exception is always logged. If you hand the method <code class="code">true</code> via the method parameter, the exception will be suppressed. And whenever you want to debug the exception, you can put a debug point in the body of <code class="code">LogException()</code> and look easily into the callstack.</p>

<p>And that's it. It's really a quite neat and easy to use trick, and my goto way of debugging exceptions. Have fun debugging &#128522;</p>]]></content:encoded></item><item><title>Improving Website Performance</title><link>https://www.rismosch.com/article?id=improving-website-performance</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">improving-website-performance</guid><pubDate>Sun, 25 Apr 2021 10:22:41 +0200</pubDate><description>Summary of the tricks I used, to boost the performance of my website.</description><content:encoded><![CDATA[<p>Phew. That was quite a lot of information. Congratulations for making it this far &#127881;</p>

<p>Now there is only one thing left to tackle: Performance.</p>

<p>If you remember all the way back, to the start of this blogpost, one of the reasons why I wanted to program a website from scratch, opposed to just using a website builder, is being able to get the best possible performance out of it. So, did writing it from scratch actually did perform better? No. Not in the slightest.</p>

<p>I mean, what did I expect? I jumped into this, knowing absolutely nothing about web dev. While my site may look nice in the end, it was so obvious that my website wouldn't perform good.</p>

<p>BUT there's light at the end of the tunnel. You are reading this blogpost on my page. At this. Very. Moment. And I am sure you can tell that it runs rather smoothly. Furthermore, if you go to the PageSpeed Insights (a tool by google to measure your website performance) of my website, you will see that it does have a pretty good result:</p>

<img src="https://www.rismosch.com/articles/improving-website-performance/picture_1.webp" style="max-width:100%; margin:auto; display: block;" />

<p><a class="auto-break" href="https://developers.google.com/speed/pagespeed/insights/?url=rismosch.com" target="_blank" rel="noopener noreferrer">https://developers.google.com/speed/pagespeed/insights/?url=rismosch.com</a></p>

<p>The only reason why this isn't 100 points is because of that huge ass Bandcamp widget. If you take a look at a blogpost, it is full on 100 points:</p>

<img src="https://www.rismosch.com/articles/improving-website-performance/picture_2.webp" style="max-width:100%; margin:auto; display: block;" />

<p><a class="auto-break" href="https://developers.google.com/speed/pagespeed/insights/?url=http%3A%2F%2Frismosch.com%2Farticle%3Fid%3D11" target="_blank" rel="noopener noreferrer">https://developers.google.com/speed/pagespeed/insights/?url=http%3A%2F%2Frismosch.com%2Farticle%3Fid%3D11</a></p>

<p>So how was I able to get such a good performance out of it? Well to make it simple: Another reason why I made the website from scratch is, to have full control over the whole code. So to get the best possible performance, all I needed to do was to apply all the tips that PageSpeed Insight told me and presto, I have a well-functioning website.</p>

<p>But this isn't as trivial as you might expect, which is why I am writing this last chapter.</p>

<h2>Overhead</h2>

<p>The very first thing you should do, is pack up all CSS, JavaScript and PHP files into one. While this may or may not be a good organization practice, it does help improve performance. You see, when files are requested and being send, not just the data itself is transferred. Each request and file are wrapped into multiple protocols, which contain header data, for example the sender and receiver identification, what type of data is being send, status codes, how large the actual package is and so much more. While this data is small, it can add up when multiple files are being transferred.</p>

<img src="https://www.rismosch.com/articles/improving-website-performance/picture_3.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;" />

<p>If you just have one big file, this header data is only required a single time, thus reducing the overall data being transferred and increasing performance. Such data is often called overhead, and it's desirable to reduce it. On a tangent note and fun fact, a similar issue arises when rendering with your graphics cards. Always batch render and reduce render calls as much as possible &#128521;</p>

<h2>WebP</h2>

<p>Another performance gain that is relatively easy to implement, is using the WebP image format. WebP is an image format by Google, which is able to drastically reduce the size of your images. Whatever you do, don't use paid internet services to convert pngs into webps; it's actually really easy to do it yourself.</p>

<p>More details and how to use it can be found here: <a class="auto-break" href="https://developers.google.com/speed/webp" target="_blank" rel="noopener noreferrer">https://developers.google.com/speed/webp</a></p>

<p>If this isn't easy enough to you, let me walk you through it. I am going to show you how to do it on Windows. How to do it on Linux or Mac, I leave it as an exercise up to the reader.</p>

<p>First, you head to this link: <a class="auto-break" href="https://storage.googleapis.com/downloads.webmproject.org/releases/webp/index.html" target="_blank" rel="noopener noreferrer">https://storage.googleapis.com/downloads.webmproject.org/releases/webp/index.html</a></p>

<p>This is Googles download repository for precompiled WebP executables. You just pick the latest package for your operating system and the file format that you can extract, and then just download and extract it. Inside the package you will find a bunch of files:</p>

<img src="https://www.rismosch.com/articles/improving-website-performance/picture_4.webp" style="max-width:100%; margin:auto; display: block;" />

<p>The interesting folder is the “bin” folder, because this one includes the program which can translate your pictures into WebP files. Head into the bin folder and click “File” in the top left corner. From the popup you should be able to open a blue console window, called the “PowerShell”.</p>

<img src="https://www.rismosch.com/articles/improving-website-performance/picture_5.webp" style="max-width:100%; margin:auto; display: block;" />
<img src="https://www.rismosch.com/articles/improving-website-performance/picture_6.webp" style="max-width:100%; margin:auto; display: block;" />

<p>In the PowerShell, you type in following command:</p>

<code class="code code_block">./cwebp.exe "&lt;source file&gt;" -o "&lt;target file&gt;"</code>

<p><code class="code">&lt;source file&gt;</code> is the image that you want to convert, for example a png or jpg. <code class="code">&lt;target file&gt;</code> is the generated WebP file. Make sure that you include the whole file path with the file extensions. Also be careful of your target path, because the program will overwrite whatever target you choose.</p>

<p>An example could look something like this:</p>

<code class="code code_block">./cwebp.exe "C:\Users\Rismosch\Desktop\ugly_mug.jpg" -o "C:\Users\Rismosch\Desktop\ugly_mug.webp"</code>

<p>Press Enter and you should see the following thing:</p>

<img src="https://www.rismosch.com/articles/improving-website-performance/picture_7.webp" style="max-width:100%; margin:auto; display: block;" />

<p>Here's the result:</p>

<table>
<tr>
<td><img src="https://www.rismosch.com/articles/improving-website-performance/ugly_mug.jpg" style="max-width:100%; margin:auto; display: block;" /></td>
<td><img src="https://www.rismosch.com/articles/improving-website-performance/ugly_mug.webp" style="max-width:100%; margin:auto; display: block;" /></td>
</tr>
</table>

<p>Left is the original, right is the WebP</p>

<p>They look awfully similar, but the original is 288 KB and the WebP 52 KB in size. This means the WebP image is about 20% of the size of the original, which is absolutely insane. Thanks to that original picture, which is about 40% of the transmitted data of this very page, chances are that this article loads a bit more poorly than the others &#128579;</p>

<p>However, I don't recommend WebP for smaller pictures, like pixel art. I don't recommend it for 2 reasons: One, the compression ruins small pictures. And two, if the files are small enough, the added overhead of the compression will make the file itself bigger actually. For example, in the pictures below, I have the results and properties of a very small 75x42 picture. As you can clearly tell, the compression reduced the quality of the picture and ontop of that the WebP version is actually bigger. It's really a lose lose situation.</p>

<table style="width: 100%;">
<tr>
<td><img src="https://www.rismosch.com/articles/improving-website-performance/small_image.png" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;
" /></td>
<td><img src="https://www.rismosch.com/articles/improving-website-performance/small_image.webp" style="width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;
" /></td>
</tr>
</table>

<img src="https://www.rismosch.com/articles/improving-website-performance/picture_8.webp" style="max-width:100%; margin:auto; display: block;" />

<p>So, just use WebP for everything but pixel art.</p>

<h2>Cached Resources</h2>

<p>One thing to massively improve performance is to cache files. Your browser is able to save files, so when you visit a website, your browser doesn't need to request them again, thus massively reducing the files that need to be transferred. In my home directory I simply put a .htaccess file with the following content:</p>

<code class="code code_block">
&lt;filesMatch ".(css|jpg|jpeg|png|gif|webp|js|ico)$"&gt;<br>
Header set Cache-Control "max-age=2419200, public"<br>
&lt;/filesMatch&gt;
</code>

<p>What this basically means, when your browser requests a css, jpg, jpeg, png, webp, js or ico file, then my webserver tells it to cache that for 2419200 seconds (4 weeks). You can see the effect of this yourself when you head to a browser you don't care (like Edge for example), delete all browser data and then navigate rismosch.com. At first it takes a second or two to load each page, but once they were loaded, if you navigate back to them, they are loaded in a split second.</p>

<h2>Loading Pictures Late</h2>

<p>The most important image on every page, is my banner on top and its animation. Because I want this animation to be seen by everyone, it is super important that the sprite sheet will be loaded first. To guarantee that, I just need to load every other image later. Consider the following HTML:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">&lt;img</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">src</span>=<span style="color:var(--pico-8-purple)">'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">id</span>=<span style="color:var(--pico-8-purple)">'late_image'</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">alt</span>=<span style="color:var(--pico-8-purple)">''</span><br>
<span style="color:var(--pico-8-cyan)">&gt;</span><br>
<br>
<span style="color:var(--pico-8-cyan)">&lt;script&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;document.getElementById(<span style="color:var(--pico-8-dark-grey)">"late_image"</span>).src = <span style="color:var(--pico-8-dark-grey)">"some_image.png"</span>;<br>
<span style="color:var(--pico-8-cyan)">&lt;/script&gt;</span><br>
</code>

<p>The source of the image is literally the entire data of a 1x1 gif. Because the data is literally stored in the HTML, your browser doesn't request an image file. But once the HTML is fully downloaded and displayed in your browser, the script executes. It finds an image with the id <code class="code">late_image</code> and replaces its source with the actual image URL. While this doesn't reduce the overall data transmitted, it makes sure that all other pictures are loaded <i>after</i> my banner spritesheet has been loaded.</p>

<p>To make the process so much easier, I've written following PHP code:</p>

<code class="code code_block" style="color:var(--pico-8-purple)">
<span style="color:var(--pico-8-black)">$img_sources</span> = [];<br>
<span style="color:var(--pico-8-black)">$img_count</span> = <span style="color:var(--pico-8-orange)">0</span>;<br>
<span style="color:var(--pico-8-cyan)">function</span> <span style="color:var(--pico-8-black)">late_image</span>(<span style="color:var(--pico-8-black)">$source</span>, <span style="color:var(--pico-8-black)">$class</span>, <span style="color:var(--pico-8-black)">$style</span>)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">global</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black)">$img_sources</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black)">$img_count</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">echo</span> <span style="color:var(--pico-8-dark-grey)">"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&lt;img<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;src='data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class='<span style="color:var(--pico-8-black)">{$class}</span>'<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;style='<span style="color:var(--pico-8-black)">{$style}</span>'<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id='img<span style="color:var(--pico-8-black)">{$img_count}</span>'<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alt=''<br>
&nbsp;&nbsp;&nbsp;&nbsp;&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;"</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black)">$img_sources</span>[] = <span style="color:var(--pico-8-black)">$source</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;++<span style="color:var(--pico-8-black)">$img_count</span>;<br>
}
</code>

<p>Where I want the image to appear in the HTML, I just call <code class="code">late_image()</code> with the correct source, class and style. It automatically creates this pseudo image tag. It also stores the URL for later. Then finally in my <code class="code">echo_foot()</code> function, I have this piece of code:</p>

<code class="code code_block" style="color:var(--pico-8-purple)">
<span style="color:var(--pico-8-cyan)">global</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black)">$img_sources</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black)">$img_count</span>;<br>
<br>
<span style="color:var(--pico-8-cyan)">echo</span> <span style="color:var(--pico-8-dark-grey)">"\n&lt;script&gt;\n"</span>;<br>
<span style="color:var(--pico-8-cyan)">for</span>(<span style="color:var(--pico-8-black)">$i</span> = <span style="color:var(--pico-8-orange)">0</span>; <span style="color:var(--pico-8-black)">$i</span> &lt; <span style="color:var(--pico-8-black)">$img_count</span>; ++<span style="color:var(--pico-8-black)">$i</span>)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">echo</span> <span style="color:var(--pico-8-dark-grey)">"document.getElementById(\"img<span style="color:var(--pico-8-black)">{$i}</span>\").src = \"<span style="color:var(--pico-8-black)">{$img_sources[$i]}</span>\";\n"</span>;<br>
}<br>
<span style="color:var(--pico-8-cyan)">echo</span> <span style="color:var(--pico-8-dark-grey)">"&lt;/script&gt;\n"</span>;<br>
</code>

<p>This generates the JavaScript to replace all URLs of the pseudo images.</p>

<p>With using this for every picture, except the banner, all images generated by <code class="code">late_image()</code> will be loaded late, except the banner. In the picture below, you see the network analysis of one of my blogposts. You see after the HTML and a bunch of CSS and JavaScript files are loaded, the 1x1 placeholder gif is the first thing to be "downloaded" and right after my sprite sheet. All other pngs or webps are loaded somewhere after.</p>

<img src="https://www.rismosch.com/articles/improving-website-performance/picture_9.webp" style="max-width:100%; margin:auto; display: block;" />

<h2>Third Party Services</h2>

<p>Now at the very end, take a guess which are the 3 least performant elements on my website. In no particular order, these are:</p>

<ul>
<li>The bandcamp widget on my homepage</li>
<li>Disqus on every article and</li>
<li>reCAPTCHA on my Newsletter and Contact page.</li>
</ul>

<p>What do these 3 have in common? Right, these are all 3rd party services. The bandcamp widget makes more than half of the size of my homepage, the Disqus widget also is notoriously bloated and reCAPTCHA results in my newsletter-page to have the worst PageSpeed Insight rating out of all of my pages.</p>

<p>While I am definitely not popular enough to have people comment on my posts, I like to have the option, just in case. I don't want to go through the programming and privacy/legal hell of making a comment section, thus a 3rd party service has to be used. reCAPTCHA is also essential, because as discussed in the previous chapter, I want my collected data to be protected from bots. The only non-essential 3rd party service I use, is the bandcamp widget, which I only use because it looks cool. Depending on how old this blogpost is, the bandcamp widget is most probably gone already.</p>

<p>Disqus can be optimized a bit though, by just loading it when it is visible on the screen. I've used the disqusLoader from Osvaldas Valutis: <a class="auto-break" href="https://css-tricks.com/lazy-loading-disqus-comments/" target="_blank" rel="noopener noreferrer">https://css-tricks.com/lazy-loading-disqus-comments/</a></p>

<p>Their code makes it possible to only load comments, when the user scrolls down far enough. While the amount of data is the same, it improves the browsing experience, to not block the entire website when the user isn't even looking at the comments yet. Also, I have another trick up my sleeve: I display a message which hides the Disqus widget. It warns the user that Disqus does collect their data. If you don't accept that and don't press the button, Disqus literally won't be loaded. Thus, increasing performance by a lot and also preventing Disqus to track your data. That is quite neat.</p>

<p>These 3 services that I use are such a performance drain alone, I can't think of why someone would voluntarily use even more services, like ads or literally tracking your data. I made a bad habit of checking every single blog-post made on r/programming and check their size (I'm not even reading them lol). I am absolutely dumbfounded at the size of some of these blogs! I mean dude, your blog has 500 words and 3 pictures, how the &#9829;&#9829;&#9829;&#9829; is it 2 MB in size?! But well, the best I can do is silently judge people for their bad performing websites and feel intellectually superior to them /s</p>

<h2>The End</h2>

<p>So, at last you have reached the very end of my <i>little</i> blog post. I hope you found it entertaining and learned something from it. Obviously, I skimmed over so many details, but it should've given you a good overview of all the stuff that you can, need or should do when you make a website completely from scratch.</p>

<p>Was it worth it though? Well, it definitely took me a lot longer than I expected. The repository on GitHub may tell you that I needed 2-3 months to code the website, it actually took at least twice as long, because I accidentally pushed my private reCAPTCHA key and database passwords multiple times, which is probably a bad idea when strangers on the internet have access to these things. So I had to nuke the repository multiple times.</p>

<p>I learned a lot from it though, more so than I learned in college. Pulling up a project like this in the real world is actually quite a bit different than running a website in the simulated servers of a school. I can recommend that you write your own page from scratch, because it is a good learning experience, but be aware that it takes a lot of time and work.</p>

<p>Thanks for reading and have a good day &#128540;</p>]]></content:encoded></item><item><title>Newsletter, Collecting Data and reCAPTCHA</title><link>https://www.rismosch.com/article?id=newsletter-collecting-data-and-recaptcha</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">newsletter-collecting-data-and-recaptcha</guid><pubDate>Sun, 25 Apr 2021 10:22:19 +0200</pubDate><description>My implementation of a Newsletter and my opinion on collecting data.</description><content:encoded><![CDATA[<p>Ok, let's discuss my least favorite part of this entire blogpost: Collecting Data &#128532; There is no nice way of saying this, but yes, I am collecting your data. While I don't use cookies, if you use my <a href="https://www.rismosch.com/contact" target="_blank" rel="noopener noreferrer">contact form</a>, an email will be send to me, containing your name, email and the subject+body of the message itself. If you <a href="https://www.rismosch.com/newsletter" target="_blank" rel="noopener noreferrer">subscribe to my newsletter</a>, your email will be saved in my database. While I can only dream of having a filled email list, and my dad being the only one who is subscribed at this very moment, I like to have the option. Also I use third party services, which may or may not collect data.</p>

<p>Because of all that ugly data collecting, I need a <a href="https://www.rismosch.com/privacy" target="_blank" rel="noopener noreferrer">privacy policy</a>, which I got from a freelancer on fiverr. Also it might be a good idea to say this:</p>

<p style="background-color:var(--pico-8-white); border: 5px solid var(--pico-8-cyan); padding: 20px;"><b>I AM NOT A LAWYER. THIS IS NOT LEGAL ADVICE. THIS CHAPTER IS MEANT AS AN EXAMPLE. FOR LEGAL QUESTIONS, CONTACT A PROFESSIONAL.</b></p>

<p>While I don't like the fact that I am collecting data, there is no way around it. When you contact me, your email <i>must</i> be stored in my email client. And if I really want to have a newsletter, I <i>must</i> store emails somewhere. I need to accept, that I will be collecting data. As for third party services, it's all free game. I have absolutely no idea how and what they collect. So if you are serious about privacy, it's probably a good idea to read the privacy policies of the third party services that you are going to use.</p>

<p>Now that the ugly stuff is out of the way, let's talk about the fun stuff again: How my contact and newsletter form actually work. My contact form is mainly inspired from this blog post:<br><a class="auto-break" href="https://mailtrap.io/blog/php-email-contact-form/" target="_blank" rel="noopener noreferrer">https://mailtrap.io/blog/php-email-contact-form/</a></p>

<p>If you read it, (which I expect you didn't) I want to mention that I modified it a bit. Mainly I use PHPMailer to send an email directly to me, instead of google docs:<br><a class="auto-break" href="https://github.com/PHPMailer/PHPMailer" target="_blank" rel="noopener noreferrer">https://github.com/PHPMailer/PHPMailer</a></p>

<p>Also I ditched the client side data validation. At last but not least, because I deviated quite a bit from the error management on that blogpost, the source code for my form is quite a mess. Because my source code is so unwieldy, it's difficult to post code here, without making this blogpost unreadable. So I excluded pretty much every code in this chapter. But if you are brave enough, you can look into my GitHub and try to read along:<br><a class="auto-break" href="https://github.com/Rismosch/risWebsite/blob/main/website/contact.php" target="_blank" rel="noopener noreferrer">https://github.com/Rismosch/risWebsite/blob/main/website/contact.php</a></p>

<p>For those who didn't read the blogpost above, (which I expect none of you did) let me walk you through the whole form. When fully implemented, the contact form does these things in that order:</p>

<ol>
<li>Once the user filled out the form and pressed the send button, a reCAPTCHA request is send to Googles servers.</li>
<li>If the reCAPTCHA is successful, the inserted data will be posted to my webserver.</li>
<li>The data is validated.</li>
<li>The webserver also checks if the reCAPTCHA is actually successful.</li>
<li>If the data is valid and reCAPTCHA was successful, an email will be generated and be send to me.</li>
<li>A success HTML will be created, which is displayed in the users browser.</li>
</ol>

<p>Ha! reCAPTCHA is used in almost every step here, isn't it? So what is reCAPTCHA and why do I use it? Simply put, reCAPTCHA is a technology to check, if your user is an actual human and not a bot. This is quite important, because this contact form directly sends an email to me. Someone could easily program a bot to fill out this form and then spam me with it. reCAPTCHA prevents this.</p>

<p>How it does detect if you are a bot or not, is kinda a mystery. If we would know how reCAPTCHA works, malicious users could easily break it and circumvent it. But on the most abstract level, reCAPTCHA gives you a score, of how human you are. If it suspects that you are a bot, it will give you that infamous picture puzzle.</p>

<img src="https://www.rismosch.com/articles/newsletter-collecting-data-and-recaptcha/picture_1.webp" style="max-width:100%; margin:auto; display: block;" />

<p>After reCAPTCHA thinks that you are a human, or you solved the picture puzzle, reCAPTCHA fires a callback, which will be used to actually submit our data. Once the data is posted to our server, we can do whatever we want with it. But beware: User inputs are very dangerous. At any point of your website where you handle user data, a user can insert stuff which can break your entire system, either by deleting everything, stealing your saved data or more. So it is a must to validate data and sanitize it.</p>

<p>For example, in the case of reCAPTCHA you might think: When the HTML only posts the data when reCAPTCHA is successful, can't I just circumvent reCAPTCHA by writing my own malicious HTML and use that to post to my server? Yes, you can do that. So it is an absolute must to validate data and sanitize it.</p>

<p>The very first thing my PHP checks is, if <code class="code">$_POST</code> is empty. <code class="code">$_POST</code> is simply the header data of the form, that the user has send to my webserver. If it is empty, the user hasn't inserted anything and validating it is useless. If it isn't empty, we can access different fields with <code class="code">$_POST[field name]</code>, check if they are filled out and sanitize them. At last but not least, we check if reCAPTCHA is successful. If the data was submitted via reCAPTCHA and not a malicious HTML, reCAPTCHA attaches it's response to our form data. With this response we connect to the server of reCAPTCHA and ask, <i>“hey, is this response the user send me actually legit?”</i>. If it was, then we can proceed and generate an email, which is finally send to me. If at the data validation any errors occur, the process is terminated and displayed in the HTML. If it was successful, then just a success message will be displayed. The diagram below further visualizes the process:</p>

<img src="https://www.rismosch.com/articles/newsletter-collecting-data-and-recaptcha/picture_2.webp" style="max-width:100%; margin:auto; display: block;" />

<p>Okay, this is quite a hazzle, but this is nothing compared to what comes next &#128579;</p>

<p>The newsletter is implemented on the same basis, but it has one thing that makes this process even more complicated: Emails should be verified. Technically there is no legal reason to verify Emails, but I don't want my email list to be filled with spam. Also I MUST include a feature, that allows the user to delete their email on demand. The user has the right to request that I delete their data. To accommodate this, my newsletter deviates from my contact form in 2 ways: One, it sends an email containing the confirmation link to the user. And two, I have 2 more php files which confirm or delete emails.</p>

<p>Once the user fills out the newsletter form, their email will be inserted into my database, confirmed or not. An id with random characters will be created for each inserted email. On top of that, a timestamp will be inserted, and a bool to track if the email was confirmed or not. The id is very important, because as I mentioned in the previous paragraph, I have 2 more php files which confirm or delete the email. Somehow, I need to tell the server, which email to confirm/delete. I do this via an URL Parameter.</p>

<p>For example, this URL will confirm the email with the id 123456:<br><a class="auto-break" href="https://www.rismosch.com/newsletter_confirm?id=123456" target="_blank" rel="noopener noreferrer">https://www.rismosch.com/newsletter_confirm?id=123456</a></p>

<p>And this URL will delete the email:<br><a class="auto-break" href="https://www.rismosch.com/newsletter_delete?id=123456" target="_blank" rel="noopener noreferrer">https://www.rismosch.com/newsletter_delete?id=123456</a></p>

<p>If I wouldn't use an id and just use a plain email, a user could easily check or delete emails they choose. With randomly generated ids, which contain 32 characters each, it is ludicrously difficult for a malicious user to enter/delete emails. And even if they succeed, they have no way of telling which email actually got confirmed/deleted, thus user data is protected.</p>

<p>Of course, the two PHP files which handle email confirmation/deletion, <code class="code">newsletter_confirm.php</code> and <code class="code">newsletter_delete.php</code>, are also protected with reCAPTCHA, preventing bots that try to spam these PHP files and brute force delete all my emails. But this works automatically and doesn't require the user to push a button. There is a JavaScript function which will be called when each site is loaded. This function will only be called when you first visit it. Then, the PHP does the same as the contact form: validate the data, check if reCAPTCHA was successful and then does whatever it wants.</p>

<p><code class="code">newsletter_confirm.php</code> checks if the id exists. If it exists, it checks if the timestamp is older than a day. If the id doesn't exist, or the timestamp is older than a day, then an error will be displayed. If it isn't expired, simply the bool of the email in the database will be switched from false to true.</p>

<p><code class="code">newsletter_delete.php</code> on the other hand simply deletes the email from the database. In my case it just runs <code class="code">DELETE FROM Emails WHERE id='123456'</code> with our id 123456 as an example. Even when the id is not found and thus nothing is deleted, the SQL query will be successful, and thus a success message will be displayed. So chances are, if you thought you deleted an email by visiting the delete-link above, you actually deleted nothing &#128522;</p>

<p>Okay, now we have a database full of emails, with a bool that tracks if the email was confirmed or not. We finally can send out newsletters to each and every email. But there is a huge problem though: Every email needs to be specific to the user we send to. That is because each email MUST contain a link to unsubscribe the newsletter. Again I preface, the user has the right to delete their data if they choose to do so. And it is my philosophy to make that as easy as possible. Honestly, I only know how to do that with Microsoft Word, Excel and Outlook. For the rest of this chapter I will be assuming that you own these programs. Otherwise you need to look for another solution to mass send individual emails.</p>

<p>But before we send emails, maybe we want to look at the emails that we actually got. For this, I wrote an offline email manager, which connects to my database and retrieves all emails. It is a simple PHP and runs on my local machine, using <a href="https://www.apachefriends.org/index.html" target="_blank" rel="noopener noreferrer">xampp</a>. The manager looks like this:</p>

<img src="https://www.rismosch.com/articles/newsletter-collecting-data-and-recaptcha/picture_3.webp" style="max-width:100%; margin:auto; display: block;" />

<p>It isn't pretty, but since I am the only one interacting with it, it will suffice. There are a bunch of things displayed here. It allows me to reload the page, it shows my total emails, how many are confirmed, how many are expired and then all emails which are stored in my database. With a click of a button, I can delete all expired emails. The export button exports all confirmed emails into an Excel spreadsheet.</p>

<p>By the way, all offline tools I wrote for my website can be found here:<br><a class="auto-break" href="https://github.com/Rismosch/risWebsite/tree/main/offline_utility" target="_blank" rel="noopener noreferrer">https://github.com/Rismosch/risWebsite/tree/main/offline_utility</a></p>

<p>Once the emails are exported into an Excel spread sheet, we can start sending mass emails. In Word, I have created a template, which is then filled with data. It looks like this:</p>

<img src="https://www.rismosch.com/articles/newsletter-collecting-data-and-recaptcha/picture_4.webp" style="max-width:100%; margin:auto; display: block;" />

<p>Obviously, the "INSERT CONTENT HERE" part will be replaced by whatever content I am deciding to send. The important thing in this template, is the little <code class="code">&lt;&lt;id&gt;&gt;</code> at the end of the email-deletion link. This string will be replaced by whatever data is standing in the id-column of the Excel table. So if the mass email will be generated, each user will have an unsubscribe link at the bottom which contains their specific id.</p>

<p>Then we can use the mass email feature. There is a handy wizard, which generates one email for each entry in the Excel table. The generated emails are then send to Outlook, which in turn sends them to each email in the Excel table. Huzza, individual emails are being send!</p>

<p>And that's basically it. If you are more interested in this, you probably want to look at the official documentation on how to send Mass Emails with Microsoft Office Products:<br><a class="auto-break" href="https://support.microsoft.com/en-us/office/use-mail-merge-to-send-bulk-email-messages-0f123521-20ce-4aa8-8b62-ac211dedefa4" target="_blank" rel="noopener noreferrer">https://support.microsoft.com/en-us/office/use-mail-merge-to-send-bulk-email-messages-0f123521-20ce-4aa8-8b62-ac211dedefa4</a></p>]]></content:encoded></item><item><title>PHP, Databases and how my Blog works</title><link>https://www.rismosch.com/article?id=php-databases-and-how-my-blog-works</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">php-databases-and-how-my-blog-works</guid><pubDate>Sun, 25 Apr 2021 10:21:58 +0200</pubDate><description>Introducing the concept of backend. A Brief overview of PHP and SQL.</description><content:encoded><![CDATA[<p>If you have come this far in my blogpost, I have to admit that I lied. In the last chapter I said you only need HTML, CSS and JavaScript to display a website, but there is actually a lot more to it. If you are still here, then there is one deceptively complicated question left: What if you want to dynamically change the HTML that is send to the browser? For example, you are reading this article on the Article page. And depending on what id is entered in the URL, a different HTML is displayed. Crazy! Then there is my blog. I didn't hardcode the selection of projects and posts into the HTML. As a matter of fact, the data lies in a database, and the HTML is dynamically created, depending on what is actually stored in the database. And then there is my Newsletter and Contact form.</p>

<p>That's a lot of stuff which I still haven't covered, and the painful truth is, HTML, CSS and JavaScript are absolutely not capable of implementing these things. What we need, is some sort of backend which generates an HTML, before it is send to the users' browser.</p>

<p>There are many ways to implement a backend. I chose PHP, because it was just plug and play and it worked on the spot. If you believe what Reddit tells you, then PHP is the most horrendous programming language ever conceived. My opinion? I don't mind it. Sure, it has some inconsistencies and is poorly designed, but like with any programming language, you face obstacles which you need to overcome. With Node and Ruby and whatever, you need to install extra stuff. For PHP I just needed to make a PHP file and it just works.</p>

<h2>PHP</h2>

<p>So what actually is PHP? PHP stands for Hypertext Preprocessor (it's actually a backronym, previously it meant “Personal Home Page Tools”) and it exactly solves the problem which I mentioned in the intro of this chapter: When the user requests a PHP file, the webserver runs the code of the PHP file and spits out an HTML, which is then send to the user.</p>

<img src="https://www.rismosch.com/articles/php-databases-and-how-my-blog-works/picture_3.webp" style="max-width:100%; margin:auto; display: block;" />

<p>During the execution of the PHP file, you can do whatever you want. You can handle the request, talk to a database, and generate an HTML. Below is a simple PHP code example:</p>

<code class="code code_block">
<span style="color:var(--pico-8-red)">&lt;?php</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">echo</span> <span style="color:var(--pico-8-dark-grey)">“&lt;h1&gt;Hello World&lt;/h1&gt;”</span><span style="color:var(--pico-8-purple)">;</span><br>
<span style="color:var(--pico-8-red)">?&gt;</span>
</code>

<p><code class="code">echo</code> is the command, which spits out HTML. After running that file, you simply get:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">&lt;h1&gt;</span>Hello World<span style="color:var(--pico-8-cyan)">&lt;/h1&gt;</span>
</code>

<p>Pretty easy. The cool thing about PHP is, that you write it just like regular HTML, except where you want backend code to be executed. You simply need to insert a <code class="code">&lt;?php?&gt;</code> tag and that's it. The PHP tag can be inserted EVERYWHERE, meaning you can not only create HTML tags, but just any string you can imagine.</p>

<p>Take for example the <i>actual</i> source code of my blog-page:</p>

<code class="code code_block">
<span style="color:var(--pico-8-red)">&lt;?php</span><br>
<br>
$article_type_id <span style="color:var(--pico-8-purple)">=</span> <span style="color:var(--pico-8-orange)">0</span><span style="color:var(--pico-8-purple)">;</span><br>
<br>
<span style="color:var(--pico-8-cyan)">include</span> <span style="color:var(--pico-8-dark-grey)">'secret/secret.php'</span><span style="color:var(--pico-8-purple)">;</span><br>
<span style="color:var(--pico-8-cyan)">include</span> <span style="color:var(--pico-8-dark-grey)">'php/articles_database.php'</span><span style="color:var(--pico-8-purple)">;</span><br>
<span style="color:var(--pico-8-cyan)">include</span> <span style="color:var(--pico-8-dark-grey)">'php/util.php'</span><span style="color:var(--pico-8-purple)">;</span><br>
<br>
echo_head<span style="color:var(--pico-8-purple)">();</span><br>
<br>
<span style="color:var(--pico-8-red)">?&gt;</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;title&gt;</span>Blog<span style="color:var(--pico-8-cyan)">&lt;/title&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">name</span>=<span style="color:var(--pico-8-purple)">"description"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"Blog of Simon Sutoris"</span><span style="color:var(--pico-8-cyan)">&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">name</span>=<span style="color:var(--pico-8-purple)">"keywords"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"blog"</span><span style="color:var(--pico-8-cyan)">&gt;</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">name</span>=<span style="color:var(--pico-8-purple)">"robots"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"all"</span><span style="color:var(--pico-8-cyan)">&gt;</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;meta</span> property=<span style="color:var(--pico-8-purple)">"og:title"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"Blog"</span> <span style="color:var(--pico-8-cyan)">/&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;meta</span> property=<span style="color:var(--pico-8-purple)">"og:type"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"website"</span> <span style="color:var(--pico-8-cyan)">/&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;meta</span> property=<span style="color:var(--pico-8-purple)">"og:url"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"https://www.rismosch.com/blog"</span> <span style="color:var(--pico-8-cyan)">/&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;meta</span> property=<span style="color:var(--pico-8-purple)">"og:image"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"https://www.rismosch.com/assets/meta_image_x10.png"</span> <span style="color:var(--pico-8-cyan)">/&gt;</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">name</span>=<span style="color:var(--pico-8-purple)">"author"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"Simon Sutoris"</span><span style="color:var(--pico-8-cyan)">&gt;</span><br>
<br>
<span style="color:var(--pico-8-cyan)">&lt;/head&gt;</span><br>
<span style="color:var(--pico-8-cyan)">&lt;body&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;div</span> <span style="color:var(--pico-8-red)">class</span>=<span style="color:var(--pico-8-purple)">"background"</span><span style="color:var(--pico-8-cyan)">&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">&lt;?php</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo_banner<span style="color:var(--pico-8-purple)">();</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo_selector<span style="color:var(--pico-8-purple)">(</span><span style="color:var(--pico-8-orange)">1</span><span style="color:var(--pico-8-purple)">);</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">?&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;div</span> <span style="color:var(--pico-8-red)">class</span>=<span style="color:var(--pico-8-purple)">"content"</span> <span style="color:var(--pico-8-red)">id</span>=<span style="color:var(--pico-8-purple)">"content"</span><span style="color:var(--pico-8-cyan)">&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;h1&gt;</span>Blog<span style="color:var(--pico-8-cyan)">&lt;/h1&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">&lt;?php</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$dbSelectConnection <span style="color:var(--pico-8-purple)">=</span> <span style="color:var(--pico-8-cyan)">mysqli_connect</span><span style="color:var(--pico-8-purple)">(</span>$dbHost<span style="color:var(--pico-8-purple)">,</span> $dbSelectUsername<span style="color:var(--pico-8-purple)">,</span> $dbSelectPassword<span style="color:var(--pico-8-purple)">,</span> $dbName<span style="color:var(--pico-8-purple)">);</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">if</span><span style="color:var(--pico-8-purple)">(</span>$dbSelectConnection)<span style="color:var(--pico-8-purple)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$pageName <span style="color:var(--pico-8-purple)">=</span> <span style="color:var(--pico-8-dark-grey)">"blog"</span><span style="color:var(--pico-8-purple)">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printDropdown<span style="color:var(--pico-8-purple)">(</span>$dbSelectConnection<span style="color:var(--pico-8-purple)">,</span> $pageName<span style="color:var(--pico-8-purple)">);</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printArticles<span style="color:var(--pico-8-purple)">(</span>$dbSelectConnection<span style="color:var(--pico-8-purple)">,</span> $pageName<span style="color:var(--pico-8-purple)">);</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printSelector<span style="color:var(--pico-8-purple)">(</span>$dbSelectConnection<span style="color:var(--pico-8-purple)">,</span> $pageName<span style="color:var(--pico-8-purple)">);</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-purple)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">else</span><span style="color:var(--pico-8-purple)">{</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">echo</span> <span style="color:var(--pico-8-dark-grey)">"&lt;h1&gt;:(&lt;/h1&gt;&lt;p&gt;Error while loading articles.&lt;/p&gt;"</span><span style="color:var(--pico-8-purple)">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-purple)">}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">?&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;/div&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red)">&lt;?php</span> echo_foot<span style="color:var(--pico-8-purple)">(</span><span style="color:var(--pico-8-cyan)">false</span><span style="color:var(--pico-8-purple)">);</span> <span style="color:var(--pico-8-red)">?&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan)">&lt;/div&gt;</span><br>
<span style="color:var(--pico-8-cyan)">&lt;/body&gt;</span><br>
<span style="color:var(--pico-8-cyan)">&lt;/html&gt;</span>
</code>

<p>So this looks quite different from the HTML which will be displayed in your browser, but it is apparent that the site is dynamically created. So let's talk about what this code is actually doing. The <code class="code">echo_x()</code> methods should be fairly self-explanatory: They echo the specific part of the HTML. All my pages contain a similar header. Also, the banner, selector and foot links are pretty much always the same. Implementing the same thing on every page is a pain in the butt, because if I want to make changes to the banner for example, I need to change it in every single file. It's easier if I have one PHP file, which contains the method to print the banner, so that I can change the banner in just one file.</p>

<p>The methods differ a little bit from each other, for example the banner and the header take no inputs, the <code class="code">echo_selector($active_tab)</code> method takes an <code class="code">int</code>, to know what selector tab needs to be active. The <code class="code">echo_foot($uses_captcha)</code> takes a <code class="code">bool</code>, which displaces the “back to top” button, when reCAPTCHA is used. You may know that if a site uses reCAPTCHA, a small UI window in the bottom right is displayed. I don't want that overlapping with the button, so I displace the button. More to reCAPTCHA in a following chapter.</p>

<p>And this is basically it. Once you wrap your head around it, PHP is actually very simple. If you take a look at my <a href="https://github.com/Rismosch/risWebsite/blob/main/website/php/util.php" target="_blank" rel="noopener noreferrer">util.php</a> code, you will find the code you expect: Just simple echoes which echo the specific HTML. Nothing special.</p>

<h2>Databases</h2>

<p>Okay, so now that we understand what PHP is and how to use it, let's talk about how I used it to make the blog on my website. Here's the main idea: No matter how many blogposts I will create, the surrounding website will always look the same. Wouldn't it be nice if we could store the individual blogposts somewhere, and then use PHP to display them on our page?</p>

<p>Yes, that would be nice. The solution to this answer is simply a database. A database is an organized storing system, that stores data efficiently, consistently and persistently. While there are other storing systems that may also work for a blog, like using a file, a database has a fundamental advantage: As a client, I can get exactly the data that I specify. Why this is such an advantage, we'll see in a moment. But first it may be a good idea to explain how a database actually works.</p>

<p>A database stores data in tables. A table is defined by its columns. A data entry is a simply a row in such a table. A table usually contains a key, which uniquely identifies a row. In most cases, such a key is simply an id. Here's an example how the articles table looks like in my database:</p>

<img src="https://www.rismosch.com/articles/php-databases-and-how-my-blog-works/picture_4.webp" style="max-width:100%; margin:auto; display: block;" />

<p>You may notice, that this table doesn't directly store its type (blog/project) or category (music, blog, etc.). Instead it stores an id of the specific column. The actual types and categories are stored in a separate table. This is to make usage easier and more importantly to reduce redundance. Storing the same data multiple times may eat a lot of space. So by storing it in a separate table, every entry will be stored only once, and then only the id needs to be referenced. Such ids which are referenced by another table, are called foreign keys.</p>

<p>So in a nutshell, a database is just a complicated way to store stuff. Great. Now after storing stuff in a database, you somehow need to retrieve it. This can be done with a language called SQL. SQL stands for Structured Query Language and it is the main way that you will talk to your database. Consider the following SQL statement:</p>

<code class="code code_block">
<span style="color:var(--pico-8-purple);">SELECT</span> <span style="color:var(--pico-8-red);">*</span> <span style="color:var(--pico-8-purple);">FROM</span> Articles
</code>

<p>This statement retrieves all data from the table Articles. So this pretty much results into the screenshot I have posted above. But things get a little bit more exciting when we add conditions:</p>

<code class="code code_block">
<span style="color:var(--pico-8-purple);">SELECT</span> <span style="color:var(--pico-8-red);">*</span> <span style="color:var(--pico-8-purple);">FROM</span> Articles <span style="color:var(--pico-8-purple);">WHERE</span> id<span style="color:var(--pico-8-red);">=</span><span style="color:var(--pico-8-cyan);">'good-enough-is-sometimes-not-good-enough'</span>
</code>

<p>This only retrieves the rows, with the id of "good-enough-is-sometimes-not-good-enough". Since the id is unique, only one row will be returned: <a href="https://www.rismosch.com/article?id=good-enough-is-sometimes-not-good-enough" target="_blank" rel="noopener noreferrer">The gamejam that broke me</a>. With further conditions we can combine tables, sort them or only retrieve a small section of the entire database. Definitely the most complicated SQL statement which I use on my website is this:</p>

<code class="code code_block">
<span style="color:var(--pico-8-purple);">SELECT</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;Articles.<span style="color:var(--pico-8-cyan);">id</span> <span style="color:var(--pico-8-purple);">AS</span> id,<br>
&nbsp;&nbsp;&nbsp;&nbsp;Article_Types.<span style="color:var(--pico-8-cyan);">name</span> <span style="color:var(--pico-8-purple);">AS</span> type,<br>
&nbsp;&nbsp;&nbsp;&nbsp;Article_Categories.<span style="color:var(--pico-8-cyan);">name</span> <span style="color:var(--pico-8-purple);">AS</span> category,<br>
&nbsp;&nbsp;&nbsp;&nbsp;Articles.<span style="color:var(--pico-8-cyan);">title</span> <span style="color:var(--pico-8-purple);">AS</span> title,<br>
&nbsp;&nbsp;&nbsp;&nbsp;Articles.<span style="color:var(--pico-8-cyan);">timestamp</span> <span style="color:var(--pico-8-purple);">AS</span> timestamp,<br>
&nbsp;&nbsp;&nbsp;&nbsp;Articles.<span style="color:var(--pico-8-cyan);">link</span> <span style="color:var(--pico-8-purple);">AS</span> link,<br>
&nbsp;&nbsp;&nbsp;&nbsp;Articles.<span style="color:var(--pico-8-cyan);">thumbnail_path</span> <span style="color:var(--pico-8-purple);">AS</span> thumbnail_path<br>
<span style="color:var(--pico-8-purple);">FROM</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;Articles,<br>
&nbsp;&nbsp;&nbsp;&nbsp;Article_Categories,<br>
&nbsp;&nbsp;&nbsp;&nbsp;Article_Types<br>
<span style="color:var(--pico-8-purple);">WHERE</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;Articles.<span style="color:var(--pico-8-cyan);">category_id</span> <span style="color:var(--pico-8-red);">=</span> Article_Categories.<span style="color:var(--pico-8-cyan);">id</span> <span style="color:var(--pico-8-purple);">AND</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;Articles.<span style="color:var(--pico-8-cyan);">type_id</span> <span style="color:var(--pico-8-red);">=</span> Article_Types.<span style="color:var(--pico-8-cyan);">id</span> <span style="color:var(--pico-8-purple);">AND</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;Articles.<span style="color:var(--pico-8-cyan);">type_id</span> <span style="color:var(--pico-8-red);">=</span> <span style="color:var(--pico-8-cyan);">0</span><br>
<span style="color:var(--pico-8-purple);">ORDER BY</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;Articles.<span style="color:var(--pico-8-cyan);">timestamp</span> <span style="color:var(--pico-8-purple);">DESC</span><br>
<span style="color:var(--pico-8-purple);">LIMIT</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">0</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">10</span>
</code>

<p>I select from 3 tables: <code class="code">Articles</code>, <code class="code">Article_Categories</code> and <code class="code">Article_Types</code>. With the first two <code class="code">WHERE</code>-statements, I make sure that each row only appears once and correct. With <code class="code">ORDER BY</code> I order them from newest to oldest. With <code class="code">LIMIT</code> I specify to only get 10 results and finally with <code class="code">SELECT</code> I select all columns that I actually want to use.</p>

<p>Why do we do that complicated stuff again? Because the conditions allow us to filter the data. For example by changing the <code class="code">LIMIT</code>, I can display more or less blogposts on my site. By changing the third condition <code class="code">“Articles.type_id = 0”</code> I can either display blogs or projects. I can even add another condition to only filter for music, or programming, or whatever. This filtering is super powerful, which is the main reason why I am using a database.</p>

<p>Now that we understand that, we need to implement this into PHP:</p>

<code class="code code_block" style="color:var(--pico-8-purple);">
<span style="color:var(--pico-8-green);">// connect to database</span><br>
<span style="color:var(--pico-8-black);">$dbConn</span> = <span style="color:var(--pico-8-cyan);">mysqli_connect</span>(<span style="color:var(--pico-8-black);">$dbHost</span>, <span style="color:var(--pico-8-black);">$dbUsername</span>, <span style="color:var(--pico-8-black);">$dbPassword</span>, <span style="color:var(--pico-8-black);">$dbName</span>);<br>
<br>
<span style="color:var(--pico-8-green);">// test if connection is successful</span><br>
if(<span style="color:var(--pico-8-black);">$dbConn</span>)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green);">// execute sql query and get the total amount of rows</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$result</span> = <span style="color:var(--pico-8-cyan);">mysqli_query</span>(<span style="color:var(--pico-8-black);">$dbConn</span>,<span style="color:var(--pico-8-black);">$sql</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$numRows</span> = <span style="color:var(--pico-8-cyan);">mysqli_num_rows</span>(<span style="color:var(--pico-8-black);">$result</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">if</span>(<span style="color:var(--pico-8-black);">$numRows</span> > <span style="color:var(--pico-8-orange);">0</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green);">// fetch the result</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">while</span>(<span style="color:var(--pico-8-black);">$row</span> = <span style="color:var(--pico-8-cyan);">mysqli_fetch_assoc</span>(<span style="color:var(--pico-8-black);">$result</span>))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green);">// do stuff with each row</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">echo</span> <span style="color:var(--pico-8-black);">$row</span>[<span style="color:var(--pico-8-dark-grey);">'id'</span>] . " " . <span style="color:var(--pico-8-black);">$row</span>[<span style="color:var(--pico-8-dark-grey);">'title'</span>] . <span style="color:var(--pico-8-dark-grey);">"&lt;br&gt;"</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>This code connects to a database, then if the connection is successful, executes the query, and then fetches each row and finally simply prints the data of each row. <code class="code">$sql</code> is the SQL which I explained before. As you see <code class="code">$row</code> is simply an array with the column names as keys. With this, you can then use the data however you like. You can put it in a list, or table, or generate links. You can really do whatever with your data.</p>

<p>Now that you are a bit better equipped to understand PHP and SQL, you can take a look at my PHP code for various files again and see, that it's just a blown-up case of the code above, just with HTML and CSS to make everything look nice.</p>

<h3>part of blog.php</h3>

<!--<a href="https://github.com/Rismosch/risWebsite/blob/main/website/blog.php" target="_blank" rel="noopener noreferrer"><i>view file on GitHub</i></a>-->

<code class="code code_block">
<span style="color:var(--pico-8-cyan);">&lt;div</span> <span style="color:var(--pico-8-red);">class</span>=<span style="color:var(--pico-8-purple);">"content"</span> <span style="color:var(--pico-8-red);">id</span>=<span style="color:var(--pico-8-purple);">"content"</span><span style="color:var(--pico-8-cyan);">&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">&lt;h1&gt;</span>Blog&lt;<span style="color:var(--pico-8-cyan);">/h1&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-red);">&lt;?php</span><span style="color:var(--pico-8-purple);"><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$dbSelectConnection</span> = <span style="color:var(--pico-8-cyan);">mysqli_connect</span>(<span style="color:var(--pico-8-black);">$dbHost</span>, <span style="color:var(--pico-8-black);">$dbSelectUsername</span>, <span style="color:var(--pico-8-black);">$dbSelectPassword</span>, <span style="color:var(--pico-8-black);">$dbName</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">if</span>(<span style="color:var(--pico-8-black);">$dbSelectConnection</span>){<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$pageName</span> = <span style="color:var(--pico-8-dark-grey);">"blog"</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">printDropdown</span>(<span style="color:var(--pico-8-black);">$dbSelectConnection</span>, <span style="color:var(--pico-8-black);">$pageName</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">printArticles</span>(<span style="color:var(--pico-8-black);">$dbSelectConnection</span>, <span style="color:var(--pico-8-black);">$pageName</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">printSelector</span>(<span style="color:var(--pico-8-black);">$dbSelectConnection</span>, <span style="color:var(--pico-8-black);">$pageName</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">else</span>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">echo</span> <span style="color:var(--pico-8-dark-grey);">"&lt;h1&gt;:(&lt;/h1&gt;&lt;p&gt;Error while loading articles.&lt;/p&gt;"</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:var(--pico-8-red);">?&gt;</span><br>
<span style="color:var(--pico-8-cyan);">&lt;/div&gt;</span><br>
</code>

<h3>part of php/articles_database.php</h3>

<!--<a href="https://github.com/Rismosch/risWebsite/blob/main/website/php/articles_database.php" target="_blank" rel="noopener noreferrer"><i>view file on GitHub</i></a>-->

<code class ="code code_block" style="color:var(--pico-8-purple);">
<span style="color:var(--pico-8-cyan);">function</span> <span style="color:var(--pico-8-black);">printArticles</span>(<span style="color:var(--pico-8-black);">$dbConn</span>, <span style="color:var(--pico-8-black);">$pageName</span>)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">global</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$categoryFilterString</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$show</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$offset</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$article_type_id</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$sqlArticles</span> = <span style="color:var(--pico-8-dark-grey);">"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SELECT<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Articles.id AS id,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Article_Types.name AS type,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Article_Categories.name AS category,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Articles.title AS title,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Articles.timestamp AS timestamp,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Articles.link AS link,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Articles.thumbnail_path AS thumbnail_path<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FROM<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Articles,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Article_Categories,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Article_Types<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WHERE<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Articles.category_id = Article_Categories.id AND<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Articles.type_id = Article_Types.id AND<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Articles.type_id = <span style="color:var(--pico-8-black);">{$article_type_id}</span> AND<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">{$categoryFilterString}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ORDER BY<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Articles.timestamp DESC<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LIMIT<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">{$offset}</span>,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">{$show}</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;"</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$result</span> = <span style="color:var(--pico-8-cyan);">mysqli_query</span>(<span style="color:var(--pico-8-black);">$dbConn</span>,<span style="color:var(--pico-8-black);">$sqlArticles</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$numRows</span> = <span style="color:var(--pico-8-cyan);">mysqli_num_rows</span>(<span style="color:var(--pico-8-black);">$result</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$totalRowsResult</span> = <span style="color:var(--pico-8-cyan);">mysqli_query</span>(<span style="color:var(--pico-8-black);">$dbConn</span>,<span style="color:var(--pico-8-dark-grey);">"SELECT COUNT(id) as count FROM Articles WHERE type_id=<span style="color:var(--pico-8-black);">{$article_type_id}</span> AND <span style="color:var(--pico-8-black);">{$categoryFilterString}</span>"</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$row</span> = <span style="color:var(--pico-8-cyan);">mysqli_fetch_assoc</span>(<span style="color:var(--pico-8-black);">$totalRowsResult</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">echo</span> <span style="color:var(--pico-8-dark-grey);">"<span style="color:var(--pico-8-black);">{$numRows}</span> of total <span style="color:var(--pico-8-black);">{$row['count']}</span> posts&lt;/p&gt;"</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">if</span>(<span style="color:var(--pico-8-black);">$numRows</span> &gt; <span style="color:var(--pico-8-orange);">0</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">echo</span> <span style="color:var(--pico-8-dark-grey);">"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;table style=\"width: 100%;\"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr class=\"row_empty\"&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr class=\"row_empty row_devider\"&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">while</span>(<span style="color:var(--pico-8-black);">$row</span> = <span style="color:var(--pico-8-cyan);">mysqli_fetch_assoc</span>(<span style="color:var(--pico-8-black);">$result</span>))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$timestamp</span> = <span style="color:var(--pico-8-cyan);">strtotime</span>(<span style="color:var(--pico-8-black);">$row</span>[<span style="color:var(--pico-8-dark-grey);">'timestamp'</span>]);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$newTimestampFormat</span> = <span style="color:var(--pico-8-cyan);">date</span>(<span style="color:var(--pico-8-dark-grey);">'M jS, Y'</span>,<span style="color:var(--pico-8-black);">$timestamp</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">if</span>(!<span style="color:var(--pico-8-cyan);">is_null</span>(<span style="color:var(--pico-8-black);">$row</span>[<span style="color:var(--pico-8-dark-grey);">'link'</span>]))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$link</span> = <span style="color:var(--pico-8-black);">$row</span>[<span style="color:var(--pico-8-dark-grey);">'link'</span>];<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">else</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$link</span> = <span style="color:var(--pico-8-dark-grey);">"https://www.rismosch.com/article?id={<span style="color:var(--pico-8-black);">$row['id']}</span>"</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-black);">$thumbnail</span> = <span style="color:var(--pico-8-black);">GetThumbnailPath</span>(<span style="color:var(--pico-8-black);">$row</span>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">echo</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey);">"&lt;tr&gt;&lt;td&gt;&lt;a title=\"<span style="color:var(--pico-8-black);">{$row['title']}</span>\" href=\"<span style="color:var(--pico-8-black);">{$link}</span>\" class=\"articles_entry_link\"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div class=\"articles_mobile\"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;table class=\"articles_entry\"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div class=\"articles_thumbnail_wrapper_outside\"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div class=\"articles_thumbnail_wrapper_inside\"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"<span style="color:var(--pico-8-purple);">; <span style="color:var(--pico-8-black);">late_image</span>(<span style="color:var(--pico-8-black);">$thumbnail</span>, <span style="color:var(--pico-8-dark-grey);">"articles_thumbnail"</span>, <span style="color:var(--pico-8-dark-grey);">""</span>); <span style="color:var(--pico-8-cyan);">echo</span> </span>"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div class=\"articles_thumbnail_information\"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;h3&gt;<span style="color:var(--pico-8-black);">{$row['title']}</span>&lt;/h3&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;<span style="color:var(--pico-8-black);">{$row['category']}</span> &#38;&#35;183; <span style="color:var(--pico-8-black);">{$newTimestampFormat}</span>&lt;/p&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/table&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div class=\"articles_desktop\"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;table class=\"articles_entry\"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td class=\"articles_thumbnail_row_desktop\"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div class=\"articles_thumbnail_wrapper\"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"<span style="color:var(--pico-8-purple);">; <span style="color:var(--pico-8-black);">late_image</span>(<span style="color:var(--pico-8-black);">$thumbnail</span>, <span style="color:var(--pico-8-dark-grey);">"articles_thumbnail"</span>, <span style="color:var(--pico-8-dark-grey);">""</span>); <span style="color:var(--pico-8-cyan);">echo</span> </span>"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div class=\"articles_thumbnail_information\"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;h3&gt;<span style="color:var(--pico-8-black);">{$row['title']}</span>&lt;/h3&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;br&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;<span style="color:var(--pico-8-black);">{$row['category']}</span> &#38;&#35;183; <span style="color:var(--pico-8-black);">{$newTimestampFormat}</span>&lt;/p&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/table&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr class=\"row_empty\"&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr class=\"row_empty row_devider\"&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">echo</span> <span style="color:var(--pico-8-dark-grey);">"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/table&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">else</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">echo</span> <span style="color:var(--pico-8-dark-grey);">"&lt;p&gt;no articles found &#38;&#35;175;&#38;&#35;92;&#38;&#35;95;&#38;&#35;40;&#38;&#35;12484;&#38;&#35;41;&#38;&#35;95;&#38;&#35;47;&#38;&#35;175;&lt;/p&gt;"</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<h2>article.php</h2>

<p>Now we got an article selection, cool. But how do I actually display an article? Well, glad you ask. Just like with the other PHP files, the container around the article is always the same, just the content changes. Each article has a title, a date, links to the next and previous posts, and a comment section. How to change these things and what content to display is handled by one PHP file, the aforementioned database and a file system.</p>

<p>When you access <code class="code">article.php</code>, it gets the URL parameter “id”. The “id” of this very post is “php-databases-and-how-my-blog-works”. With SQL it retrieves the correct row of the article table. In the row I get the title of the post, its timestamp and its category. Then with the timestamp, I gather the article with the next highest and next lowest timestamp, thus retrieving the next and previous post.</p>

<p>All of this will simply be displayed around the article. I have a directory “articles”, which contains contents of each blog. It gets the directory, which has the same name as the id of the post and checks if it contains a file called <code class="code">page_0.php</code>. If it contains this file, then it will simply be included, thus its content being displayed on the page. If <code class="code">article.css</code> exists, it will be included. This allows me to have individual CSS for every article. Finally, <code class="code">article.php</code> contains a method, which allows <code class="code">page_0.php</code> to easily access assets, like pictures and other files.</p>

<p>Putting everything together, it looks like this:</p>

<img src="https://www.rismosch.com/articles/php-databases-and-how-my-blog-works/picture_5.webp" style="max-width:100%; margin:auto; display: block;" />

<p>This is the articles-directory, which contains all articles.</p>

<img src="https://www.rismosch.com/articles/php-databases-and-how-my-blog-works/picture_6.webp" style="max-width:100%; margin:auto; display: block;" />

<p>These are the files for this very post.</p>
<p>The method to access an asset looks like this:</p>

<code class="code code_block" style="color: var(--pico-8-purple);">
<span style="color:var(--pico-8-cyan);">function</span> <span style="color:var(--pico-8-black);">get_source</span>(<span style="color:var(--pico-8-black);">$file</span>)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">global</span> <span style="color:var(--pico-8-black);">$article_id</span>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">return</span> <span style="color:var(--pico-8-dark-grey);">"https://www.rismosch.com/articles/<span style="color:var(--pico-8-black);">{$article_id}</span>/<span style="color:var(--pico-8-black);">{$file}</span>"</span>;<br>
}
</code>

<p>And it is easily called like this:</p>

<code class="code code_block"><span style="color: var(--pico-8-red);">&lt;?php <span style="color: var(--pico-8-purple);"><span style="color:var(--pico-8-black);">late_image</span>(<span style="color:var(--pico-8-black);">get_source</span>(<span style="color:var(--pico-8-dark-grey);">"picture_1.webp"</span>),<span style="color:var(--pico-8-dark-grey);">""</span>,<span style="color:var(--pico-8-dark-grey);">"max-width:100%; margin:auto; display:block;"</span>);</span> ?&gt;</span></code>

<p>More on <code class="code">late_image()</code> in a later chapter.</p>

<p>And that is basically everything regarding my blog. From it's PHP, how each article is stored in the database, how it is build up with multiple files, and how an article is actually displayed.</p>]]></content:encoded></item><item><title>CSS on Mobile, and The Most Important Header Tag</title><link>https://www.rismosch.com/article?id=css-on-mobile-and-the-most-important-header-tag</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">css-on-mobile-and-the-most-important-header-tag</guid><pubDate>Sun, 25 Apr 2021 10:19:00 +0200</pubDate><description>Tackling meta-tags. And a solution to make the website responsive, such that it is perfectly usable on any device.</description><content:encoded><![CDATA[<p>One thing, that I struggled with more than I should have, is making my website look nice on mobile. Problem is, the text on mobile was super inconsistent. Some text was big, some text was small.</p>

<p>Fixing the inconsistency is pretty easy with this CSS:</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">body</span>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">-webkit-text-size-adjust</span>: none;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">-moz-text-size-adjust</span>: none;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">-ms-text-size-adjust</span>: none;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">text-size-adjust</span>: none;<br>
}
</code>

<p>But now that everything is consistent, when you view your website on mobile, the text is too small. As it turns out, most mobile browsers &#34;boost&#34; the text size, so that text remains readable. But the Problem with this boosting is, that it is super inconsistent, and you are probably better off by disabling it with the code I posted above.</p>

<p>I tried many things to fix the text size issue, from detecting if you are a using a mobile client or not with JavaScript, to sending the browser a different CSS with PHP (more on PHP in a later chapter), none of which worked in a satisfying way. Then, I found a header tag, which solved this issue immediately. I may present you, the most important HTML Header Tag, which you should probably implement in your website:</p>

<code class="code code_block"><span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">name</span>=<span style="color:var(--pico-8-purple)">&#34;viewport&#34;</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">&#34;width=device-width,initial-scale=1&#34;</span> <span style="color:var(--pico-8-cyan)">&#47;&gt;</span></code>

<p>So what does it do and how does it fix the text-size issue? CSS has a quirk which I seriously don’t understand: CSS resolution is independent from your device resolution. Let’s say for simplicity’s sake, your desktop pc display is 200 pixels wide. Now you want to implement a button which is 100 pixels wide. It’s only logical to conclude, that this button will fit half of your screen. Now you have a mobile device which is 50 pixels wide, you would assume that the button will the fill the whole screen from left to right. But for some reason, the CSS resolution is larger than the resolution of your mobile device. Thus the button is displayed way smaller than you would expect.</p>

<p>In the image below, left is desktop and right is mobile. Because CSS- and device resolution doesn't match, the Button is smaller on mobile.</p>

<img src="https://www.rismosch.com/articles/css-on-mobile-and-the-most-important-header-tag/picture_1.png" style="max-width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;" />

<p>The meta tag posted above fixes this, by basically telling the browser that the CSS resolution is the same as the device resolution. If you implement this tag, this button will be properly displayed.</p>

<img src="https://www.rismosch.com/articles/css-on-mobile-and-the-most-important-header-tag/picture_2.png" style="max-width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;" />

<p>Depending how your website should look like, this may actually be not that important. But if you are going to use one single HTML file for both desktop and mobile (like I do), this tag should do the trick. And once that works, you can now properly work with media queries.</p>

<p>Media queries allow you to adapt your CSS, depending on the devices resolution. Take for example the following CSS:</p>

<code class="code code_block">
.<span style="color:var(--pico-8-red)">myContainer</span>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">background-color</span>: var(--pico-8-red);<br>
}<br>
<br>
@media only screen and (max-width: 500px) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;.<span style="color:var(--pico-8-red)">myContainer</span>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">background-color</span>: var(--pico-8-yellow);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}
</code>

<p>What this tells your browser, is that the container should only be yellow, if the screen is at maximum 500 pixels wide. Otherwise it will be red. To demonstrate, consider this rectangle:</p>

<div class="myContainer" style="width:300px; height:100px; display:block; margin:auto;"></div>

<p>When you are on desktop, this rectangle is probably red. But when you take your browser into windowed mode and make it smaller, you will notice that it will change its color to yellow. If you are on mobile, it is yellow, if you view this page in vertical. But it will be red, if you view this page in horizontal.</p>

<p><b>Disclaimer:</b> This demo <i>only</i> works on mobile, if your device is less than 500 pixels wide and more than 500 pixels high. If your resolution is outside of these criteria, then the rectangle will not change color.</p>

<p>This is pretty neat, because this allows us to have different UI elements, depending if the device is wide enough or not. Take for example the Selector-Tabs again. These are way too wide to be displayed on most mobile phones. I have two media queries, which look a bit like this:</p>

<code class="code code_block">
@media only screen and (min-width: 681px) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;.<span style="color:var(--pico-8-red)">desktop</span>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">display</span>: block;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;.<span style="color:var(--pico-8-red)">mobile</span>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">display</span>: none;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}<br>
<br>
@media only screen and (max-width: 680px) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;.<span style="color:var(--pico-8-red)">desktop</span>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">display</span>: none;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;.<span style="color:var(--pico-8-red)">mobile</span>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">display</span>: block;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}<br>
</code>

<p>Basically, what this does is, as long as your device width is larger than 680 pixels, every tag with the class <code class="code">desktop</code> will be displayed and every tag with the class <code class="code">mobile</code> will be hidden. If your screen is smaller than that, <code class="code">mobile</code> will be displayed and <code class="code">desktop</code> will be hidden. When you take a look at the source code of my website, you will notice that the selector tabs are implemented twice, once as the tabs, and once as a dropdown menu. One has the <code class="code">desktop</code> class, and the other the <code class="code">mobile</code> class, so depending on how wide your screen is, a different selector will be displayed. Pretty neat.</p>

<code class="code code_block" style="color:var(--pico-8-cyan)">
&lt;div <span style="color:var(--pico-8-red)">class</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"selector"</span> <span style="color:var(--pico-8-red)">id</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"selector"</span>&gt;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&lt;ul <span style="color:var(--pico-8-red)">class</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"selector_tabs desktop"</span> <span style="color:var(--pico-8-red)">id</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"selector_tabs"</span>&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;li <span style="color:var(--pico-8-red)">class</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"selector_tab active_tab"</span> <span style="color:var(--pico-8-red)">id</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"selector_tab"</span>&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;a <span style="color:var(--pico-8-red)">href</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"https://www.rismosch.com/"</span>&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div&gt;&lt;b&gt;<span style="color:var(--pico-8-black)">Home</span>&lt;/b&gt;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/a&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/li&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;li <span style="color:var(--pico-8-red)">class</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"selector_tab "</span> <span style="color:var(--pico-8-red)">id</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"selector_tab"</span>&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;a <span style="color:var(--pico-8-red)">href</span><span style="color:var(--pico-8-black)">=</span>"<span style="color:var(--pico-8-purple)">https://www.rismosch.com/blog"</span>&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div&gt;&lt;b&gt;<span style="color:var(--pico-8-black)">Blog</span>&lt;/b&gt;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/a&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/li&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;li <span style="color:var(--pico-8-red)">class</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"selector_tab "</span> <span style="color:var(--pico-8-red)">id</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"selector_tab"</span>&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;a <span style="color:var(--pico-8-red)">href</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"https://www.rismosch.com/projects"</span>&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div&gt;&lt;b&gt;<span style="color:var(--pico-8-black)">Projects</span>&lt;/b&gt;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/a&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/li&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;li <span style="color:var(--pico-8-red)">class</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"selector_tab "</span> <span style="color:var(--pico-8-red)">id</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"selector_tab"</span>&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;a <span style="color:var(--pico-8-red)">href</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"https://www.rismosch.com/about"</span>&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div&gt;&lt;b&gt;<span style="color:var(--pico-8-black)">About</span>&lt;/b&gt;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/a&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/li&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/ul&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&lt;div <span style="color:var(--pico-8-red)">class</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"mobile"</span>&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div <span style="color:var(--pico-8-red)">onclick</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"showDropdown('dropdownSelector')"</span> <span style="color:var(--pico-8-red)">class</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"dropdownButton dropdownSelector selector_menu pixel_image"</span> <span style="color:var(--pico-8-red)">id</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"dropdownButton"</span>&gt;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div <span style="color:var(--pico-8-red)">class</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"dropdownContent dropdownSelector dropdown"</span>&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;a <span style="color:var(--pico-8-red)">class</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"dropdown_selected"</span> <span style="color:var(--pico-8-red)">href</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"https://www.rismosch.com/"</span>&gt;<span style="color:var(--pico-8-black)">Home</span>&lt;/a&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;a <span style="color:var(--pico-8-red)">href</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"https://www.rismosch.com/blog"</span>&gt;<span style="color:var(--pico-8-black)">Blog</span>&lt;/a&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;a <span style="color:var(--pico-8-red)">href</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"https://www.rismosch.com/projects"</span>&gt;<span style="color:var(--pico-8-black)">Projects</span>&lt;/a&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;a <span style="color:var(--pico-8-red)">href</span><span style="color:var(--pico-8-black)">=</span><span style="color:var(--pico-8-purple)">"https://www.rismosch.com/about"</span>&gt;<span style="color:var(--pico-8-black)">About</span>&lt;/a&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&lt;/div&gt;
</code>

<p>Now since I touched on meta tags with the most important HTML meta tag, it’s probably also a good idea to also talk about the other header tags. Here’s the header tags of the website you are viewing right now:</p>

<code class="code code_block"><span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">charset</span>=<span style="color:var(--pico-8-purple)">"utf-8"</span><span style="color:var(--pico-8-cyan)">&#47;&gt;</span></code>

<p>This tag defines the encoding of the text on your site. <del>UTF-8 basically means Unicode, and for most purposes this will be good enough.</del><br><br><b>(Jan 09th, 2022) EDIT:</b> This is incorrect. For a detailed explanation check out this <a href="http://www.joelonsoftware.com/articles/Unicode.html" target="_blank" rel="noopener noreferrer">this</a> blogpost by Joel Spolsky. Read it. Now. No excuses.</p>

<code class="code code_block"><span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">name</span>=<span style="color:var(--pico-8-purple)">"viewport"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"width=device-width,initial-scale=1"</span> <span style="color:var(--pico-8-cyan)">&#47;&gt;</span></code>

<p>This is the already mentioned most important HTML header tag.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">&lt;link</span> <span style="color:var(--pico-8-red)">rel</span>=<span style="color:var(--pico-8-purple)">"apple-touch-icon"</span> <span style="color:var(--pico-8-red)">sizes</span>=<span style="color:var(--pico-8-purple)">"180x180"</span> <span style="color:var(--pico-8-red)">href</span>=<span style="color:var(--pico-8-purple)">"apple-touch-icon.png"</span><span style="color:var(--pico-8-cyan)">&gt;</span><br>
<span style="color:var(--pico-8-cyan)">&lt;link</span> <span style="color:var(--pico-8-red)">rel</span>=<span style="color:var(--pico-8-purple)">"icon"</span> <span style="color:var(--pico-8-red)">type</span>=<span style="color:var(--pico-8-purple)">"image/png"</span> <span style="color:var(--pico-8-red)">href</span>=<span style="color:var(--pico-8-purple)">"favicon.png"</span> <span style="color:var(--pico-8-red)">sizes</span>=<span style="color:var(--pico-8-purple)">"32x32"</span><span style="color:var(--pico-8-cyan)">&gt;</span><br>
<span style="color:var(--pico-8-cyan)">&lt;link</span> <span style="color:var(--pico-8-red)">rel</span>=<span style="color:var(--pico-8-purple)">"shortcut icon"</span> <span style="color:var(--pico-8-red)">href</span>=<span style="color:var(--pico-8-purple)">"favicon.ico"</span><span style="color:var(--pico-8-cyan)">&gt;</span><br>
<span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">name</span>=<span style="color:var(--pico-8-purple)">"msapplication-TileImage"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"mstile-144x144.png"</span><span style="color:var(--pico-8-cyan)">&gt;</span><br>
<span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">name</span>=<span style="color:var(--pico-8-purple)">"msapplication-TileColor"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"#00aba9"</span><span style="color:var(--pico-8-cyan)">&gt;</span>
</code>

<p>These basically define the small icon on the tab at the very top of your browser. Each browser follows different standards, so I implemented them multiple times to confine to all of them. I do not have every single browser in existence, but from what I have found, this should cover all mainstream browsers, like Firefox, Chrome, Edge, Safari and so on.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">&lt;link</span> <span style="color:var(--pico-8-red)">rel</span>=<span style="color:var(--pico-8-purple)">"stylesheet"</span> <span style="color:var(--pico-8-red)">href</span>=<span style="color:var(--pico-8-purple)">"css/desktop.css"</span><span style="color:var(--pico-8-cyan)">&gt;</span><br>
<span style="color:var(--pico-8-cyan)">&lt;link</span> <span style="color:var(--pico-8-red)">rel</span>=<span style="color:var(--pico-8-purple)">"stylesheet"</span> <span style="color:var(--pico-8-red)">href</span>=<span style="color:var(--pico-8-purple)">"css/main.css"</span><span style="color:var(--pico-8-cyan)">&gt;</span>
</code>

<p>These are basically the CSS files, that define the style of my website. They need to be included, so that they can be used by your browser.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">&lt;script</span> <span style="color:var(--pico-8-red)">src</span>=<span style="color:var(--pico-8-purple)">"3rd_party_libraries/disqusloader.js"</span><span style="color:var(--pico-8-cyan)">&gt;&lt;/script&gt;</span><br>
<span style="color:var(--pico-8-cyan)">&lt;script</span> <span style="color:var(--pico-8-red)">src</span>=<span style="color:var(--pico-8-purple)">"javascript/util.js"</span><span style="color:var(--pico-8-cyan)">&gt;&lt;/script&gt;</span>
</code>

<p>These are javascript files, which are used on this site. Like CSS, JavaScript can be outsourced to another file and be imported like this.</p>

<code class="code code_block"><span style="color:var(--pico-8-cyan)">&lt;title&gt;</span>CSS on Mobile, and The Most Important Header Tag<span style="color:var(--pico-8-cyan)">&lt;/title&gt;</span></code>

<p>This is the title, which is displayed on your browser tab.</p>

<code class="code code_block"><span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">name</span>=<span style="color:var(--pico-8-purple)">"robots"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"all"</span><span style="color:var(--pico-8-cyan)">&gt;</span></code>

<p>This tag is very important for search engines. It basically tells search engines what to do with your page, when they find it. <code class="code">all</code> means, the search engine will display it without a problem in their search result. Setting it to <code class="code">noindex</code> will prevent them from displaying that site. This is most helpful for redirect pages. When someone subscribes/unsubscribes to my newsletter, there are sites to handle that. With <code class="code">noindex</code>, they won’t be displayed in the search results. That is good, because a normal user probably isn’t searching for these sites and most likely doesn’t care. Thus, displaying them does probably more harm than good.</p>

<code class="code code_block">
<span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">property</span>=<span style="color:var(--pico-8-purple)">"og:title"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"Mobile, and The Most Important Header Tag"</span> <span style="color:var(--pico-8-cyan)">/&gt;</span><br>
<span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">property</span>=<span style="color:var(--pico-8-purple)">"og:type"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"article"</span> <span style="color:var(--pico-8-cyan)">/&gt;</span><br>
<span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">property</span>=<span style="color:var(--pico-8-purple)">"og:url"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"https://www.rismosch.com/article?id=16"</span> <span style="color:var(--pico-8-cyan)">/&gt;</span><br>
<span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">property</span>=<span style="color:var(--pico-8-purple)">"og:image"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"https://www.rismosch.com/articles/16/thumbnail.jpg"</span> <span style="color:var(--pico-8-cyan)">/&gt;</span>
</code>

<p>These are data used by external sites and programs. For example, if you post a link in any social media, usually a title, thumbnail and whatever will also be displayed. These things can be set with these tags.</p>

<code class="code code_block"><span style="color:var(--pico-8-cyan)">&lt;meta</span> <span style="color:var(--pico-8-red)">name</span>=<span style="color:var(--pico-8-purple)">"author"</span> <span style="color:var(--pico-8-red)">content</span>=<span style="color:var(--pico-8-purple)">"Simon Sutoris"</span><span style="color:var(--pico-8-cyan)">&gt;</span></code>

<p>And at last, you probably want to tell the world who actually wrote the source code of your website &#128521;</p>

<p>And that’s it. This is pretty much everything you need to know to display something in your browser. HTML, CSS and JavaScript will cover most of what you need in a website. Sure, I elided a lot of details, but that’s why search engines exist. Good resources on these things are w3schools and the Mozilla Development Network.</p>

<p class="auto-break">
	<a href="https://www.w3schools.com/" target="_blank" rel="noopener noreferrer">https://www.w3schools.com/</a><br>
	<a href="https://developer.mozilla.org/de/" target="_blank" rel="noopener noreferrer">https://developer.mozilla.org/de/</a>
</p>

<p>Read the next chapters only if you dare…</p>]]></content:encoded></item><item><title>How I Build My Website</title><link>https://www.rismosch.com/article?id=how-i-build-my-website</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">how-i-build-my-website</guid><pubDate>Sun, 25 Apr 2021 10:18:42 +0200</pubDate><description>An overview, of how I used HTML, CSS, and Javascript to build my website.</description><content:encoded><![CDATA[<p>If at any time you want to see the actual source code, just press [Ctrl]+[Shift]+[i] or [Cmd]+[Opt]+[i] for macOS while your browser is open. This key combination will display the inspector of your browser. You can then simply hover over the HTML elements and see how things are actually build up.</p>

<img src="https://www.rismosch.com/articles/how-i-build-my-website/picture_1.webp" style="max-width:100%; margin:auto; display: block;" />

<p>Alternatively, you can just type <code class="code">view-source:</code> before the URL, for example like this:</p>

<code>
<p class="code code_block">view-source:https://rismosch.com/</p>
</code>

<p>With this, you can see the actual HTML. This even works on mobile! By the way, you can do these things with every website, not just mine. So if you ever want to see how Googles HTML looks like, there is literally nothing stopping you to check that out. If you don’t want to do any of that, you can also just check out my GitHub, in which I made all the source code of this website open source.</p>

<p class="auto-break"><a href="https://github.com/Rismosch/risWebsite" target="_blank" rel="noopener noreferrer">https://github.com/Rismosch/risWebsite</a></p>

<p>But since I don’t expect you to read the code and immediately understand everything right away, let’s talk about what I actually build &#128579; Every page is built exactly the same: The body’s background is set to a dark-blue and contains a black <code class="code">&lt;div&gt;</code>. In this <code class="code">&lt;div&gt;</code> there are 4 Elements:</p>

<ol>
<li>The Rismosch Banner</li>
<li>The Selector Tabs</li>
<li>The Actual Content and</li>
<li>Some Foot Links</li>
</ol>

<img src="https://www.rismosch.com/articles/how-i-build-my-website/picture_2.png" style="max-width:100%; margin:auto; width: 455px; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;" />

<p>The easiest of these 4 to implement, are the Foot Links. These are literally just a GIF, 4 pictures and 3 links. CSS makes them look nice. That’s literally it.</p>

<p>The next easiest, is the Content, which is just a <code class="code">&lt;div&gt;</code> with grey background, white border and some padding. Again, that’s literally it. Depending on which site you are viewing, different content is displayed in this <code class="code">&lt;div&gt;</code>.</p>

<p>The Banner and Selector tabs are quite a bit more complicated. Let’s start with the Tabs, because these are just pretty CSS magic. I briefly mentioned in the CSS chapter, that HTML Tags can be defined with classes and ids.</p>

<code>
<p class="code code_block">
	<span style="color:var(--pico-8-cyan);">&lt;div</span> <span style="color:var(--pico-8-red);">class</span>=<span style="color:var(--pico-8-purple);">&#34;myClass1 myClass2&#34;</span> <span style="color:var(--pico-8-red);">id</span>=<span style="color:var(--pico-8-purple);">&#34;myId&#34;</span><span style="color:var(--pico-8-cyan);">&gt;&lt;&#47;div&gt;</span>
</p>
</code>

<p>The main difference between a class and an id is, that a tag can have multiple classes, but only one id. You can easily add and remove, even toggle classes. The Selector Tabs abuse this feature. The tabs are just a horizontal list. Each element has the class <code class="code">selector_tab</code>, which gives them a white border, a dark grey background, white text, and most importantly: A small margin on top. This margin makes it so, that there is a little space above the tab. You will notice that one of the tabs isn’t dark grey though, that is because additionally to the other class, it also has the <code class="code">active_tab</code> class, which overwrites the colors. It also removes the margin on top and makes the tab a little larger. Since the other tabs have this margin while the active one doesn’t, it makes it appear that the active tab is sticking out. Additionally, the margin is also removed, when you hover over the tab, thus making the tab stick out when you hover over them.</p>

<p>The banner is the most complicated UI Element on my website, and it’s using JavaScript. Essentially, it’s just an <code class="code">&lt;img&gt;</code> tag. This image, has a background image, which is this sprite-sheet:</p>

<img src="https://www.rismosch.com/articles/how-i-build-my-website/picture_3.png" style="max-width:100%; margin:auto; display: block;" />

<p>By making the width and height smaller than the whole sheet, the image only shows a small section. Then, with some JavaScript magic, the Background-Position offset is adjusted each frame, thus scrolling through the whole sprite sheet and playing the animation.</p>

<p>What you may have noticed, is that the banner uses pixel art. And when using pixel art, it’s a good idea to only use the resolution required, otherwise your images become unnecessarily big. Setting the width and height of the image bigger than it actually is, or using <code class="code">transform:scale(5)</code> for the banner, which makes the image 5 times larger, we can scale up low resolution pixel art. However, the problem with that is, that scaled up images end up blurred. That is because the browser needs to generate new pixels to make the image bigger, and it usually does this by taking the average of surrounding pixels, which blurs it. In most cases this is the preferred way to upscale images, but not for pixelart, where you want crisp and clearly defined edges. To fix that I have the following selector in my main CSS file:</p>

<code>
<p class="code code_block">
.<span style="color:var(--pico-8-red)">pixel_image</span>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">image-rendering</span>: -moz-crisp-edges;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">&#47;* Firefox *&#47;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">image-rendering</span>: -o-crisp-edges;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">&#47;* Opera *&#47;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">image-rendering</span>: -webkit-optimize-contrast;<span style="color:var(--pico-8-green)">&#47;* Webkit (non-standard naming) *&#47;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">image-rendering</span>: pixelated;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">-ms-interpolation-mode</span>: nearest-neighbor;&nbsp;&nbsp;<span style="color:var(--pico-8-green)">&#47;* IE (non-standard property) *&#47;</span><br>
}
</p>
</code>

<p>Now adding the class <code class="code">pixel_image</code> to <i>any</i> upscaled pixelart, creates the result that we want. Below is the same picture twice. However, one has and the other has not the class <code class="code">pixel_image</code>.</p>

<img src="https://www.rismosch.com/articles/how-i-build-my-website/picture_4.png" style="width: 365px; max-width:100%; margin:auto; display: block;" />
<img src="https://www.rismosch.com/articles/how-i-build-my-website/picture_4.png" style="width: 365px; max-width:100%; margin:auto; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;" />

<p>The final thing I want to mention is the color scheme that I used. You can actually use variable-like colors with CSS. I wanted to use the PICO-8 color scheme, not that I ever worked with the PICO-8, but because I just like the colors. On the very top of my main CSS I have the following code:</p>

<code>
<p class="code code_block">
:<span style="color:var(--pico-8-orange)">root</span>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-black</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#000000;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-blue</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#1d2b53;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-purple</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#7e2553;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-green</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#008751;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-brown</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#ab5236;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-dark-grey</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#5f574f;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-light-grey</span>:&nbsp;&nbsp;&nbsp;&nbsp;#c2c3c7;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-white</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#fff1e8;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-red</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#ff004d;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-orange</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#ffa300;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-yellow</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#ffec27;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-lime</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#00e436;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-cyan</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#29adff;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-washed-grey</span>:&nbsp;&nbsp;&nbsp;#83769c;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-pink</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#ff77a8;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">--pico-8-flesh</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#ffccaa;<br>
}
</p>
</code>

<p>And then in the rest of the CSS I can use these like this:</p>

<code>
<p class="code code_block">
<span style="color:var(--pico-8-cyan)">p</span>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey)">color</span>: var(--pico-8-red);<br>
}
</p>
</code>

<p>When you take a look at my source code, you will notice that every single color in every HTML and CSS uses var(), thus creating a consistent color scheme.</p>]]></content:encoded></item><item><title>HTML, CSS and JavaScript</title><link>https://www.rismosch.com/article?id=html-css-and-javascript</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">html-css-and-javascript</guid><pubDate>Sun, 25 Apr 2021 10:18:14 +0200</pubDate><description>An explanation of what a browser is, and a Hello-World example with HTML, CSS and Javascript.</description><content:encoded><![CDATA[<p>Okay, so we got a webserver, now what? You could be a professional and reasonable person and use a website-builder, if your host provides one, or install WphpordPress or whatever. But I wanted to make things myself, so I got cPanel, a Linux based platform for web hosting. And this is where the fun starts:</p>

<p>Did you know that your browser can display a lot of different files? Like PNG, JPEG, MP3, WAV, TXT and so much more. If you are on a desktop PC you can test that right now, make a TXT file, put in some words (e.g. “Hello World”), save and then just drag and drop it into your browser of choice. Voilà, your browser displays your txt-file. This works with the files I just mentioned. What you can also do is copy a path from your file explorer, paste it into the URL bar of your browser, and you will be able to navigate your files, but in a browser. And once you realize that, it’s easy to grasp how a webserver works. The webserver also contains a filesystem, like your file explorer, and you can simply upload files there. And once they are on there, you can view them by just entering your domain plus the correct path to that specific file.</p>

<img src="https://www.rismosch.com/articles/html-css-and-javascript/picture_1.webp" style="width:100%; display: block;" />

<p>So that’s pretty neat, but TXT and PNG files are rather dull. What we want are layouts, colors, animations, <i>extravaganza</i>, and a simple TXT file just doesn’t cut it. This is where HTML comes in. HTML stands for Hypertext Markup Language, and as its name suggest, it’s a language to describe markup, or in proper English: how your website looks.</p>

<p>HTML uses tags, which do very different things. For instance: </p>

<code>
<div style="background-color: var(--pico-8-white);" class="code code_block">
<p><span style="color:var(--pico-8-cyan);">&lt;html&gt;</span> contains the entire website</p>
<p><span style="color:var(--pico-8-cyan);">&lt;head&gt;</span> contains diverse data, like the title of the tab, or the little icon displayed next to it. Here comes usually important stuff to make the website work, but won’t be displayed <span style="color:var(--pico-8-cyan);">&lt;&#47;head&gt;</span></p>
<p><span style="color:var(--pico-8-cyan);">&lt;body&gt;</span> contains all visual stuff</p>
<p><span style="color:var(--pico-8-cyan);">&lt;h1&gt;</span> is a header <span style="color:var(--pico-8-cyan);">&lt;&#47;h1&gt;</span></p>
<p><span style="color:var(--pico-8-cyan);">&lt;p&gt;</span> is a paragraph <span style="color:var(--pico-8-cyan);">&lt;&#47;p&gt;</span></p>
<p><span style="color:var(--pico-8-cyan);">&lt;a </span><span  style="color:var(--pico-8-red);">href</span><span style="color:var(--pico-8-black);">=</span><span style="color:var(--pico-8-purple);">&#34;https://youtu.be/dQw4w9WgXcQ&#34;</span><span style="color:var(--pico-8-cyan);">&gt;</span> is a hyperlink <span style="color:var(--pico-8-cyan);">&lt;&#47;a&gt;</span></p>
<p><span style="color:var(--pico-8-cyan);">&lt;div&gt;</span> is a container, in which you can insert other tags <span  style="color:var(--pico-8-cyan);">&lt;&#47;div&gt;</span></p>
<p><span style="color:var(--pico-8-cyan);">&lt;ul&gt;</span> is a list, which contains <span style="color:var(--pico-8-cyan);">&lt;li&gt;</span> individual items <span style="color:var(--pico-8-cyan);">&lt;&#47;li&gt;</span><span style="color:var(--pico-8-cyan);">&lt;&#47;ul&gt;</span></p>
<p><span style="color:var(--pico-8-cyan);">&lt;table&gt;</span> is a table (duh)<br><span style="color:var(--pico-8-cyan);">&lt;tr&gt;</span> defines a row in a table, and<br><span style="color:var(--pico-8-cyan);">&lt;td&gt;</span> defines a single cell in a row <span style="color:var(--pico-8-cyan);">&lt;&#47;td&gt;</span><br><span style="color:var(--pico-8-cyan);">&lt;&#47;tr&gt;</span><br><span style="color:var(--pico-8-cyan);">&lt;&#47;table&gt;</span></p>
<p><span style="color:var(--pico-8-cyan);">&lt;img </span><span style="color:var(--pico-8-red);">href</span><span style="color:var(--pico-8-black);">=</span><span style="color:var(--pico-8-purple);">&#34;this is an image, and&#34;</span><span style="color:var(--pico-8-cyan);">&gt;</span></p>
<p><span style="color:var(--pico-8-cyan);">&lt;button&gt;</span> is simply a button <span style="color:var(--pico-8-cyan);">&lt;&#47;button&gt;</span></p>
<p><span style="color:var(--pico-8-cyan);">&lt;&#47;body&gt;</span></p>
<p><span style="color:var(--pico-8-cyan);">&lt;&#47;html&gt;</span></p>
</div>
</code>

<p>There are more tags than this, but these are the most essential ones. The whole layout of your website is pretty much just a creative combination of these tags. Since you already know that a webserver works like a filesystem, even if you don’t have a host, you can make an HTML file right now, throw in some HTML tags and display it in your browser.</p>

<p>Take for example the following HTML:</p>

<code>
<p class="code code_block">
&lt;!DOCTYPE html&gt;<br>
<span style="color:var(--pico-8-cyan);">&lt;html </span><span style="color:var(--pico-8-red);">lang</span>=<span style="color:var(--pico-8-purple);">&#34;en&#34;</span><span style="color:var(--pico-8-cyan);">&gt;</span><br>
<span style="color:var(--pico-8-cyan);">&lt;head&gt;</span><br>
<span style="color:var(--pico-8-cyan);">&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;</span>my first html<span style="color:var(--pico-8-cyan);">&lt;&#47;title&gt;</span><br>
<span style="color:var(--pico-8-cyan);">&lt;&#47;head&gt;</span><br>
<span style="color:var(--pico-8-cyan);">&lt;body&gt;</span><br>
<span style="color:var(--pico-8-cyan);">&nbsp;&nbsp;&nbsp;&nbsp;&lt;h1&gt;</span>Hello World<span style="color:var(--pico-8-cyan);">&lt;&#47;h1&gt;</span><br>
<span style="color:var(--pico-8-cyan);">&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;</span>this is some text<span style="color:var(--pico-8-cyan);">&lt;&#47;p&gt;</span><br>
<span style="color:var(--pico-8-cyan);">&lt;&#47;body&gt;</span><br>
<span style="color:var(--pico-8-cyan);">&lt;&#47;html&gt;</span>
</p>
</code>

<img src="https://www.rismosch.com/articles/html-css-and-javascript/picture_2.webp" style="max-width:100%; margin:auto; display: block;" />

<p>If you just tested it out for yourself, you may notice that everything is just black text on white background. BOOOORING. What we want is style, literally. Pretty much every tag inside and including <code class="code">&lt;body&gt;</code>, can be equipped with a style-parameter. In this parameter, you can define a multitude of things, like color, size, border, whether it’s left, center or right aligned, and so much more. If you want to do something on the display side, you can literally google &#34;css &lt;anything you want to display&gt;&#34; and you will find solutions, exactly what you need. For example &#34;css background color&#34;, &#34;css font&#34;, &#34;css align center&#34;. It’s so easy to gather information, that it’s almost plug and play, without much thinking required.</p>

<p>But hold on a second. Do I really need to implement style for every single tag? My website contains a homepage, and blog page, and an about page, and privacy policy, and newsletter and so on and on and on. Implementing style for every single page sucks. Well, what we need, is CSS.</p>

<p>CSS, or Cascading Style Sheets, allow you to put all your styles into one single file. With so called selectors, you can apply styles to tags.</p>

<code>
<p class="code code_block">
<span style="color:var(--pico-8-cyan);">p</span>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey);">color</span>: red;<br>
}<br>
</p>
</code>

<p>This selector for example, makes the text of all paragraphs red. HTML-Tags can be assigned classes and ids, so that CSS-Selectors can be more specific.</p>

<code>
<p class="code code_block">
<span style="color:var(--pico-8-cyan);">p</span>.<span style="color:var(--pico-8-red);">myClass</span>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-dark-grey);">color</span>: blue;<br>
}<br>
</p>
</code>

<p>This selector only applies to paragraph tags, which have the class &#34;myClass&#34;.<br>Using the two CSS selectors above and the HTML below, we get something like this:</p>

<code>
<p class="code code_block">
<span style="color:var(--pico-8-cyan);">&lt;p&gt;</span>this is some text<span style="color:var(--pico-8-cyan);">&lt;&#47;p&gt;</span><br>
<span style="color:var(--pico-8-cyan);">&lt;p </span><span style="color:var(--pico-8-red);">class</span>=<span style="color:var(--pico-8-purple);">&#34;myClass&#34;</span><span style="color:var(--pico-8-cyan);">&gt;</span>this is some blue text<span style="color:var(--pico-8-cyan);">&lt;&#47;p&gt;</span><br>
</p>
</code>

<img src="https://www.rismosch.com/articles/html-css-and-javascript/picture_3.webp" style="max-width:100%; margin:auto; display: block;" />

<p>The last of the unholy trio is JavaScript, which essentially allows you to run code. With JavaScript, you can dynamically change the styling of your tags, calculate stuff and talk to other servers.</p>

<p>
	<button onclick="myFunction()">click me</button>
	&nbsp;click count: <span id="counter">0</span>
</p>

<script>
	var clickCount = 0;
	
	function myFunction(){
		clickCount++;
		var counterElement = document.getElementById("counter");
		counterElement.innerHTML = clickCount;
	}
</script>

<code>
<p class="code code_block">
<span style="color:var(--pico-8-cyan);">&lt;p&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-cyan);">&lt;button </span><span style="color:var(--pico-8-red);">onclick</span>=<span style="color:var(--pico-8-purple);">&#34;myFunction()&#34;</span><span style="color:var(--pico-8-cyan);">&gt;</span>click me<span style="color:var(--pico-8-cyan);">&lt;&#47;button&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="background-color: var(--pico-8-yellow);"><i>&#38;nbsp&#59;</i></span> click count: <span style="color:var(--pico-8-cyan);">&lt;span </span><span style="color:var(--pico-8-red);">id</span>=<span style="color:var(--pico-8-purple);">&#34;counter&#34;</span><span style="color:var(--pico-8-cyan);">&gt;</span>0<span style="color:var(--pico-8-cyan);">&lt;&#47;span&gt;</span><br>
<span style="color:var(--pico-8-cyan);">&lt;&#47;p&gt;</span><br>
<br>
<span style="color:var(--pico-8-cyan);">&lt;script&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-blue);"><i>var</i></span> clickCount = <span style="color:var(--pico-8-red);">0</span>&#59;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-blue);"><i>function</i></span> myFunction(){<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clickCount++&#59;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:var(--pico-8-blue);"><i>var</i></span> counterElement = document.getElementById(<span style="color:var(--pico-8-dark-grey);">&#34;counter&#34;</span>)&#59;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;counterElement.innerHTML = clickCount&#59;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<span style="color:var(--pico-8-cyan);">&lt;&#47;script&gt;</span><br>
</p>
</code>

<p>In this example, when you click the button, it increases the <code class="code">clickCount</code> by one, then it finds the element with the id <code class="code">counter</code> and finally replaces the HTML inside this element by the new value of <code class="code">clickCount</code>.</p>

<p>But while this works great, I myself found limited use for JavaScript. In my case it powers just 4 things:</p>

<ul>
<li>The banner animation on top</li>
<li>The “back to top” button in the lower right corner of each page</li>
<li>The dropdown menu, which you will find on my Blog and Project site and</li>
<li>A performance improvement, loading images late (more on that in the last chapter)</li>
</ul>

<p>Okay, so now that we have a solid grasp of the building-blocks which creates the stuff you see in your browser. Let’s talk about how I used them to build my website.</p>
]]></content:encoded></item><item><title>Hosting a Webserver and Money</title><link>https://www.rismosch.com/article?id=hosting-a-webserver-and-money</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">hosting-a-webserver-and-money</guid><pubDate>Sun, 25 Apr 2021 10:17:50 +0200</pubDate><description>A brief summary, of what services you need to buy to get a website running.</description><content:encoded><![CDATA[<p>If you think about it, the internet is just computers which are connected to each other. The computers which make out the world wide web (www), are webservers. With a program called a browser (like the window you are using at this very moment to read this blogpost), you can request files from a webserver, which are then displayed in the browser.</p>

<img src="https://www.rismosch.com/articles/hosting-a-webserver-and-money/picture_1.webp" style="max-width:100%; margin: auto; display: block;" />

<p>So, if you want to make a website, you need a webserver. This webserver contains all files which build up your website. You will most likely use a hosting service for this, because they have the resources to run a server 24/7. I chose GoDaddy, for no particular reason. I have not tested any other hosts, so I can’t give an opinion if this is the best or if others are better. It was literally my first choice, and because I am satisfied at the moment, I don’t plan on changing my host.</p>

<p>Once you sign up to a hosting service, you can get yourself a domain. The domain is pretty much just the address of your website. It’s a bit more complicated than this, but for now you only need to understand that the domain is nothing more than just the address. For example, the domain of my blog is rismosch.com. The domain of Googles search engine is google.com. It’s literally that easy.</p>

<p>Domains aren’t free, but generally they don’t cost the world. There is a market for them, so different domains cost different amounts. There are also other things you might need, that also need to be paid. These things include, but may not be limited to: Domain Protection, Email service and the hosting itself. The money adds up and you should consider the cost.</p>

<p>Another thing you should seriously consider, is buying an SSL certificate. Any time your browser requests files, it uses HTTP (short for Hypertext Transfer Protocol). Problem with that is, it is not encrypted. This means, if anyone decides to sit between your webserver and the user’s browser, they can read ALL the data plainly. This is a huge security issue for user data, especially password and other sensible information that might be interchanged. With an SSL certificate, the data is encrypted, so anyone trying to read the data, can’t, because for them it’s just gibberish. HTTP connections which use SSL are is simply called HTTPS. This SSL certificate, also costs money.</p>

<p>All these things are being paid annually. In my case, I need to pay every 2 years.</p>

<p style="text-align: center;"><b>All in all, my costs add up to about 330€ per 2 years.</b></p>

<p>I am just throwing this number out there, so you get an idea of how much it costs to run a website. If this is worth it for you, I can’t tell you, you need to decide that for yourself. If you run a website you need to pay money, but you have complete freedom on whatever you want to show to the world.</p>

<p>If it is worth it for you and you are still interested, we can finally talk about something more exciting! Paying for the hosting is actually the easy stuff, now you need to design and actually code the website.</p>]]></content:encoded></item><item><title>How to make a website from scratch</title><link>https://www.rismosch.com/article?id=i-made-a-website-only-with-notepad-plus-plus</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Programming]]</category><guid isPermaLink="false">i-made-a-website-only-with-notepad-plus-plus</guid><pubDate>Sun, 25 Apr 2021 10:16:37 +0200</pubDate><description>Summary of the things which I have learned, by writing this very website only with Notepad++.</description><content:encoded><![CDATA[<img src="https://www.rismosch.com/assets/thumbnails/web_dev_crash_course.webp" style="width: 100%; display: block; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor;
" />

<p>So here I am. I programmed this very website with nothing but Notepad++. While this may or may not have been a good idea, I did it and it taught me a lot about WebDev and how websites work. Now why would someone go trough the insanity and intentionally avoid website-builders or other (arguably easier) means of making a website? Well, as it turns out there are a multitude of reasons why:</p>

<ol>
<li>I am stupid.</li>
<li>Without using a website-builder, I have absolute control over the entire website. I can create and display whatever HTML, game or app that I want.</li>
<li>Elaborating on the previous point, I can get the best possible performance. I am not dependent on boilerplate code or cookies or ads or whatever. My code only includes what it really needs.</li>
<li>Most importantly, it inflates my ego. Now I have the universal right to scoff at other webdevs. “What?! You mere mortal used WordPress? PAH! You can’t even compare to my godlike status. I <i>breath</i> HTML.”</li>
<li>I had absolutely no idea what I was getting into. This may or may not influence the previous reasons.</li>
</ol>

<p>But whatever the reasons are, I did it and the website is up now. With the following blogposts I am sharing my knowledge which I gathered over the past months.</p>

<p>These blogposts will be skipping a lot of details and are mainly targeted at people, who already have some experience with programming. The main intend of these posts is to lead you the way, if you decide to go through the same hell as I did. Be prepared for a large information dump, because these posts aren’t small. The total read time is about one hour. So buckle up!</p>

<p>The source code is public. So if you want, you can take a look at it at any time: <a href="https://github.com/Rismosch/risWebsite" target="_blank" rel="noopener noreferrer">https://github.com/Rismosch/risWebsite</a></p>

<h3>Chapters:</h3>
<ol>
<li><a href="https://www.rismosch.com/article?id=hosting-a-webserver-and-money">Hosting a Webserver and Money</a></li>
<li><a href="https://www.rismosch.com/article?id=html-css-and-javascript">HTML, CSS and JavaScript</a></li>
<li><a href="https://www.rismosch.com/article?id=how-i-build-my-website">How I Build My Website</a></li>
<li><a href="https://www.rismosch.com/article?id=css-on-mobile-and-the-most-important-header-tag">CSS on Mobile, and The Most Important Header Tag 	</a></li>
<li><a href="https://www.rismosch.com/article?id=php-databases-and-how-my-blog-works">PHP, Databases and how my Blog works</a></li>
<li><a href="https://www.rismosch.com/article?id=newsletter-collecting-data-and-recaptcha">My Newsletter, Collecting Data and reCAPTCHA</a></li>
<li><a href="https://www.rismosch.com/article?id=improving-website-performance">Improving Website Performance</a></li>
</ol>]]></content:encoded></item><item><title>Good enough is sometimes not good enough</title><link>https://www.rismosch.com/article?id=good-enough-is-sometimes-not-good-enough</link><dc:creator><![CDATA[Simon Sutoris]]></dc:creator><category>![CDATA[Other]]</category><guid isPermaLink="false">good-enough-is-sometimes-not-good-enough</guid><pubDate>Sun, 07 Mar 2021 08:35:15 +0100</pubDate><description>My post mortem of the GMTK GameJam 2020, which changed my perspective on how I approach my projects.</description><content:encoded><![CDATA[
<img src="https://www.rismosch.com/articles/good-enough-is-sometimes-not-good-enough/gmtk_game_jam_2020_banner_2.webp" style="width: 100%; display: block;" />

<p>Last year, Mark Brown, from the YouTube channel <a href="https://www.youtube.com/channel/UCqJ-Xo29CKyLTjn6z2XwYAw">Game Maker's Toolkit</a>, ran the GMTK Game Jam 2020, in which you had 48 hours to make a game. Like the Game Jams before it, this jam focused on a clever design idea, which challenged traditional games and forced you to think outside the box. This time, the idea was “out of control”. The theme was open for interpretation, and I wanted to make a game, where the player became faster over time, eventually becoming so fast that they are literally out of control.</p>

<p>It was a multiplayer game, in which you controlled a bumper car. Goal of the game was to rack up points, by bumping into others. If you hit another car or a special cube in the center of the map, your car would increase its speed as well as its size. The game started slow and is rather easy to play, but as you rack up points, the gameplay became very fast and hectic.</p>

<img src="https://www.rismosch.com/articles/good-enough-is-sometimes-not-good-enough/bad_game.webp" style="margin:auto; max-width:100%; display: block;" />

<p>At its completion, I was really proud of it. It was fun to play with friends and family. And the absurd speed of the gameplay made people laugh out loud multiple times. But the other participants of Game Jam didn’t quite like it as much. As to my utter disbelief, the game was ranked to be in the worst 20% of all submitted games. And since over 5000 games were submitted, this was quite an accomplishment. It was then, when I realized that I was just so out of touch with reality and that good enough is sometimes just not good enough.</p>

<p>The game idea was fine, I still believe this to this day, but the execution was lacking.</p>

<ul>
<li>I hid a text-based tutorial in a menu option. People usually don’t look for tutorials and they are expecting the game to be understandable right away.</li>
<li>The graphics were ugly and the music was unfitting. Contrary to what people may tell you, graphics do matter, a lot actually, because no one wants to look at an ugly game.</li>
<li>Also, the game was multiplayer. This was just a dumb idea in general, considering that most people in this game jam were expecting single player games.</li>
<li>To make the previous point so much worse, I was actually aware that most people weren’t testing games with friends, and thus I programmed bots. Problem is, making good bots is stupidly difficult and even the hot mess that I came up with, ate like half of the development time.</li>
<li>To make the multiplayer thing so much worse, I did not program networking code. Instead, I mentioned in the tutorial (that no one read), to use an external program, which requires the players to make an extra account. No one will go out of their way and download arbitrary programs, just to play a bad game.</li>
</ul>

<img src="https://www.rismosch.com/articles/good-enough-is-sometimes-not-good-enough/bad_game_end.webp" style="margin:auto; max-width:100%; display: block;" />

<p>Due to the 48-hour time limit, a lot of corners had to be cut to finish the game. As bad as these decisions were, at the time they actually didn’t seem that bad. They honestly seemed good enough. But in retrospect, it’s obvious how bad these decisions actually were.</p>

<p>This post is not complaining about people not appreciating bad games. Because the thing is, I can’t possibly expect others to play the bad game that I have made, when I myself can’t give damn about the bad game that the dev next to me made. Instead, I decided to increase the quality of my work and put a lot more effort into the projects I want to make. Complaining won’t get you far (unless you’re a critic) and I want to accomplish something, that I can be proud of.</p>
<p>With this blogpost I am trying to kick off a future of amazing projects :)</p>

<p>&#10013;Footnote: <span style="color:var(--pico-8-dark-grey);">This post is not advocating to perfectionism. Perfectionism and “good-enough-ism” are both obstacles that hinder you from creating stuff. If you sway too much into perfectionism, you will never finish a project. If you say to yourself “good enough is good enough” too easily and too many times, you will lose track of what makes your project truly good. The key is to strike a balance, so that you will finish your projects, but don’t produce something that is absolute horse&#9829;&#9829;&#9829;&#9829;.</span></p>]]></content:encoded></item></channel></rss>