<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>blog</title>
    <link>https://evilcookie.de</link>
    <description>Hi, I&#39;m Raphael. I write about my software developer journey. You can find my stuff on &lt;a href=&#39;https://github.com/RaphaelPour/&#39;&gt;github&lt;/a&gt;.</description>
    <managingEditor> (Raphael Pour)</managingEditor>
    <pubDate>Tue, 20 Feb 2024 17:38:29 +0100</pubDate>
    <item>
      <title>let&#39;s boot with riscv</title>
      <link>https://evilcookie.de/lets-boot-with-riscv.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>let&rsquo;s boot with riscv</h1>

<p>Let&rsquo;s boot some C code<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> with <a href="https://en.wikipedia.org/wiki/RISC-V">riscv64</a> using <a href="https://www.qemu.org/docs/master/system/target-riscv.html">qemu</a>: <a href="https://github.com/RaphaelPour/riscy/tree/main">riscy</a><sup class="footnote-ref" id="fnref:credits"><a href="#fn:credits">2</a></sup></p>

<p>After about <a href="https://evilcookie.de/lets-boot.html">half a year of os development abstinence</a>. I fell into the riscv-os-dev-rabbit-hole. Those risc, arm, riscv buzzwords are in my news bubble for a while. Now it&rsquo;s time to get my hands dirty.</p>

<h4>Contents</h4>

<ul>
<li><a href="#riscv-vs-arm">RISC-V vs. ARM vs. ARM64 vs. AArch64</a></li>
<li><a href="#getting-started">Getting started - barebone tutorial</a>

<ul>
<li><a href="#build">Build</a></li>
</ul></li>
<li><a href="#interact">Interact with the outside world</a>

<ul>
<li><a href="#devices">Devices</a></li>
<li><a href="#drivers">Drivers</a></li>
<li><a href="#magic">Magic address</a></li>
<li><a href="#uart">UART</a></li>
<li><a href="#rtc">RTC</a></li>
</ul></li>
<li><a href="#summary">Summary</a></li>
</ul>

<h2>RISC-V vs. ARM vs. ARM64 vs. AArch64<a id='riscv-vs-arm'/></h2>

<p><a href="https://en.wikipedia.org/wiki/AArch64">ARM64</a> and Aarch64 are both the same<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">3</a></sup>: an implementation of the  proprietary <a href="https://www.ibm.com/history/risc">RISC</a>  architecture family <a href="https://en.wikipedia.org/wiki/ARM_architecture_family">ARM</a>. <a href="https://en.wikipedia.org/wiki/RISC-V">RISC-V</a> on the other side is an open-source architecture.</p>

<p>Those RISC&rsquo;s are fairly modern<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">4</a></sup> and faster than CISC due to <a href="https://cs.stanford.edu/people/eroberts/courses/soco/projects/risc/risccisc/">their nature</a> of being <em>reduced</em> instead of <em>complex</em>. I&rsquo;m not sure what this &ldquo;faster&rdquo; actually means while a CISC operation may be slower than a single RISC operation, but with RISC more operations are needed.</p>

<h2>Getting started - barebone tutorial<a id="getting-started"/></h2>

<p>I initialized my <a href="https://github.com/RaphaelPour/riscy">riscy</a> bootloader using the <a href="https://wiki.osdev.org/RISC-V_Bare_Bones">os.dev risc-v bare bones</a> tutorial containing everything needed for a hello world:</p>

<ul>
<li><a href="https://wiki.osdev.org/RISC-V_Bare_Bones#entry.S"><code>entry.S</code></a>: Entry point and initial bootloader preparing everything before calling the main function in the C kernel code.</li>
<li><a href="https://wiki.osdev.org/RISC-V_Bare_Bones#kernel.c"><code>kernel.c</code></a>: C kernel printing hello world and reading from the keyboard by <a href="https://docs.arduino.cc/learn/communication/uart/">UART</a>.</li>
<li><a href="https://wiki.osdev.org/RISC-V_Bare_Bones#linker.ld"><code>linker.ld</code></a>: Defines the <a href="https://evilcookie.de/lets-boot.html#memory-layout">memory layout</a> of the resulting binary image that can be booted by qemu.</li>
</ul>

<h3>Build<a id="build"/></h3>

<p>In order to compile and link riscv code on a x86 machine, a cross-compiler version of gcc is needed. For Ubuntu and Fedora I could make out the package <code>gcc-riscv64-linux-gnu</code> containing all needed binaries.</p>

<p>Despite the different binaries names and the dropped <code>-lgcc</code> flag<sup class="footnote-ref" id="fnref:4"><a href="#fn:4">5</a></sup>, the commands look the same as in the Tutorial:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ riscv64-linux-gnu-gcc -Wall -Wextra -c -mcmodel<span class="o">=</span>medany kernel.c -o kernel.o -ffreestanding
</span></span><span class="line"><span class="cl">$ riscv64-linux-gnu-gcc -c entry.S -o entry.o
</span></span><span class="line"><span class="cl">$ riscv64-linux-gnu-ld -T linker.ld -nostdlib kernel.o entry.o -o kernel.elf
</span></span></code></pre>
<p>Let&rsquo;s boot it via <code>qemu-system-riscv64 -machine virt -bios none -kernel kernel.elf -serial mon:stdio</code>.</p>

<p><img src="lets-boot-with-riscv_first_boot.png"/></p>

<p>\o/</p>

<h2>Interact with the outside world<a id="interact"/></h2>

<p>Devices and their drivers are needed to interact with the outside world. Usually devices are defined by the underlying hardware. In our case Qemu and the used machine type <code>virt</code> defines what devices can be used. A driver is defined by the operating system and provides an abstraction of such devices. The Tutorial makes use of the UART device for providing a simple console. Let&rsquo;s discover devices and drivers separately.</p>

<h3>Devices<a id="devices"/></h3>

<p>Qemu provides <a href="https://www.qemu.org/docs/master/system/riscv/virt.html">a list of supported devices</a> for our machine type <code>virt</code>. We also can make out our UART device.</p>

<p>But how can we make use of them?</p>

<h3>Drivers<a id="drivers"/></h3>

<p>Looking at the <a href="https://wiki.osdev.org/RISC-V_Bare_Bones">Tutorial</a>, the driver consists of a magic address and&hellip; well actually nothing more than read and write from it:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">uart</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x10000000</span><span class="p">;</span> 
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">putchar</span><span class="p">(</span><span class="kt">char</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="o">*</span><span class="n">uart</span> <span class="o">=</span> <span class="n">c</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">putchar</span><span class="p">(</span><span class="o">*</span><span class="n">uart</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>How can this make any sense?</p>

<h4>Magic address<a id="magic"/></h4>

<p>The address is actually well-defined by Qemu&rsquo;s machine type for the UART device. As far as I understood it, the address-space of the devices are mapped into our address space and directly usable. Qemu can dump all those devices and addresses which can be made readable using the device-tree-compiler, as I found out via <a href="https://twilco.github.io/riscv-from-scratch/2019/07/08/riscv-from-scratch-3.html#hardware-layout-in-review">this riscv-from-scratch blog post</a>.</p>

<p>And again, we can can make out our UART device with some additional information:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">chosen {
</span></span><span class="line"><span class="cl">  bootargs = [00];
</span></span><span class="line"><span class="cl">  stdout-path = &#34;/soc/uart@10000000&#34;;
</span></span><span class="line"><span class="cl">};
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl">uart@10000000 {
</span></span><span class="line"><span class="cl">  interrupts = &lt;0x0a&gt;;
</span></span><span class="line"><span class="cl">  interrupt-parent = &lt;0x03&gt;;
</span></span><span class="line"><span class="cl">  clock-frequency = &#34;\08@&#34;;
</span></span><span class="line"><span class="cl">  reg = &lt;0x00 0x10000000 0x00 0x100&gt;;
</span></span><span class="line"><span class="cl">  compatible = &#34;ns16550a&#34;;
</span></span><span class="line"><span class="cl">};
</span></span></code></pre>
<ul>
<li>uart device emulates the  <a href="https://en.wikipedia.org/wiki/16550_UART#A">ns16550A</a> IC</li>
<li>address spaces starts at <em>magic address</em> <code>0x10000000</code></li>
<li>qemu uses this device for serial stdin/stdout</li>
</ul>

<h3>UART<a id="uart"/></h3>

<p><img src="lets-boot-with-riscv_uart_works.gif"/></p>

<p>The <a href="https://docs.arduino.cc/learn/communication/uart/">Universal Asynchronous Receiver-Transmitter</a> is used for serial console. Its implementation
is fairly simple.</p>

<h3>RTC<a id="rtc"/></h3>

<p>After uart is working good enough, I wondered which other devices Qemu&rsquo;s virt machinetype offers. Right in the beginning of the
device-tree-map, a goldfish got my attention:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">rtc@101000 {
</span></span><span class="line"><span class="cl">  interrupts = &lt;0x0b&gt;;
</span></span><span class="line"><span class="cl">  interrupt-parent = &lt;0x03&gt;;
</span></span><span class="line"><span class="cl">  reg = &lt;0x00 0x101000 0x00 0x1000&gt;;
</span></span><span class="line"><span class="cl">  compatible = &#34;google,goldfish-rtc&#34;;
</span></span><span class="line"><span class="cl">};
</span></span></code></pre>
<p>This is the google goldfish rtc device mapped at <code>0x101000</code>. Qemu has a documentation about the <a href="https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT#203">rtc device</a> and the linux kernel has a <a href="https://github.com/torvalds/linux/blob/master/drivers/rtc/rtc-goldfish.c#L110">pretty small implementation</a>.</p>

<p>I came up with something like this:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kt">uint64_t</span> <span class="nf">time</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">volatile</span> <span class="kt">uint32_t</span> <span class="o">*</span><span class="n">rtc</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span> <span class="o">*</span><span class="p">)</span> <span class="mh">0x101000</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kt">uint64_t</span> <span class="n">time_low</span> <span class="o">=</span> <span class="n">rtc</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kt">uint64_t</span> <span class="n">time_high</span> <span class="o">=</span> <span class="n">rtc</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">(</span><span class="n">time_high</span> <span class="o">&lt;</span><span class="o">&lt;</span> <span class="mi">32</span> <span class="o">|</span> <span class="n">time_low</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>Which lead to the first ever nanosecond unix timestamp printed to the riscy console: <code>1707410202187052000</code><sup class="footnote-ref" id="fnref:5"><a href="#fn:5">6</a></sup>.</p>

<h2>Inline assembler<a id="inline-assembler"/></h2>

<p>After having some convenience with basic drivers and an essential standard lib, it&rsquo;s time to checkout riscv assembler itself using inline assembler.</p>

<p>Incrementing a number should be a simple start, right? Well, unlike x86&rsquo;s <code>inc</code>, there is no pedant here. But <code>addi</code> gotcha covered: <code>addi result, a, number</code>  where <code>result</code> and <code>a</code> are variables and <code>number</code> is a so-called <em>imediate</em> (literal) value. The inline syntax is a bit odd since it breaks the usual format we know from C/printf. <a href="https://stackoverflow.com/q/72640997">This SO Post</a> helped me to find the right syntax.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">inc</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">volatile</span> <span class="kt">int</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">asm</span> <span class="k">volatile</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="sa"></span><span class="s">&#34;</span><span class="s">addi %0, %1, 1;</span><span class="s">&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="o">:</span> <span class="sa"></span><span class="s">&#34;</span><span class="s">=r</span><span class="s">&#34;</span> <span class="p">(</span><span class="n">result</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="o">:</span> <span class="sa"></span><span class="s">&#34;</span><span class="s">r</span><span class="s">&#34;</span> <span class="p">(</span><span class="n">n</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>The keyword <code>volatile</code> is recommended to prevent compiler optimizations.</p>

<h2>Summary<a id="summary"/></h2>

<p>Although I learned a bit about RISC and the hardware qemu provides for it, I barely touched the differences between x86 and RISC. I wouldn&rsquo;t wonder
if the C &ldquo;core&rdquo; lib (despite the machine type specialities) is architecture-agnostic. But I really enjoyed starting with nothing and introduce concepts
like strings or time. The bootloader is still a bit mysterious for me and I couldn&rsquo;t figure out how to support VGA, but the UART driver was pretty straight forward.</p>

<p>Developing my first driver from scratch with my own findings, going through kernel code and tinkering around was awesome. It&rsquo;s just a small goldfish but it meant a lot.</p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">Assembler won&rsquo;t matter much as I use the bootloader from the bare-bones tutorial and start development with C for convenience.</li>

<li id="fn:credits">Together with <a href="https://github.com/Tch1b0/">Tch1b0</a></li>

<li id="fn:2">Based on <a href="https://stackoverflow.com/a/47274698">SO</a>: Apple named it <code>arm64</code> and all the others <code>aarch64</code>.</li>

<li id="fn:3">RISC-V is from <a href="https://en.wikipedia.org/wiki/RISC-V">2014</a> and not unlike the famous x86/i386 from <a href="https://en.wikipedia.org/wiki/X86">1978</a>.</li>

<li id="fn:4"><code>riscv64-linux-gnu-ld: cannot find -lgcc: no error</code> ¯\<em>(ツ)</em>/¯</li>

<li id="fn:5"><code>$ date -d @1707410202.187052000 +&quot;%Y-%m-%d %H:%M:%S.%N&quot;</code>: 2024-02-08 17:36:42.187052000</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Tue, 20 Feb 2024 17:38:16 +0100</pubDate>
    </item>
    <item>
      <title>execute c source files</title>
      <link>https://evilcookie.de/execute-c-source-files.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>execute c source files</h1>

<p><em>tl;dr</em>:</p>

<ol>
<li>add <code>//usr/bin/gcc &quot;$0&quot; &amp;&amp; exec ./a.out &quot;$@&quot;</code> to the first line of your <code>example.c</code></li>
<li>make executable: <code>chmod +x example.c</code></li>
<li>run it: <code>./example.c</code></li>
</ol>

<p>I&rsquo;ve a folder called <code>lab</code> for those quick &lsquo;n&rsquo; dirty programs to test some language features or other interesting behavior. While <code>golang</code> programs can be easily executed via <a href="https://pkg.go.dev/cmd/go#hdr-Compile_and_run_Go_program"><code>go run &lt;go file&gt;</code></a> and this is not the case for c programs needing a built step. There is AFAIK no such command like <code>gcc run</code>.</p>

<p><img src="execute-c-source-files_lab.png"/></p>

<h2>Shebang</h2>

<p>Linux&rsquo;s <a href="https://linux.die.net/man/2/execve"><code>execve(2)</code></a> syscall supports <a href="https://en.wikipedia.org/wiki/Shebang_%28Unix%29">shebangs</a>. When the first line starts with <code>#!</code> aka shebang, it will get parsed by the kernels <a href="https://github.com/torvalds/linux/blob/3e732ebf7316ac83e8562db7e64cc68aec390a18/fs/binfmt_script.c#L34">binfmt_script</a> module and used for executing the rest of the file. This enables to run various non-binary scripts (bash, python, ruby, <your-fancy-new-language>)  like <code>./program</code> without using the interpreter.</p>

<p>Can we use a shebang for c source files? tl;dr: nope, as far as I tried this is not possible.</p>

<p>I&rsquo;ve ended up with something like:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="cp">#!/usr/bin/tail -n+2 main.c /tmp/main.c &amp;&amp; /usr/bin/gcc /tmp/main.c -o main &amp;&amp; ./main #
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="c1">#include &lt;stdio.h&gt;</span>
</span></span><span class="line"><span class="cl"><span class="c1">#include &lt;stdlib.h&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">int main<span class="o">(</span>int argc, char *argv<span class="o">[</span><span class="o">]</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span><span class="o">(</span>int <span class="nv">i</span> <span class="o">=</span> 0<span class="p">;</span>i&lt;argc<span class="p">;</span> i++<span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    printf<span class="o">(</span><span class="s2">&#34;%d: %s\n&#34;</span>, i, argv<span class="o">[</span>i<span class="o">]</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">/*
</span></span><span class="line"><span class="cl"> * $ ./main.c <span class="m">1</span> <span class="m">2</span> <span class="m">3</span>
</span></span><span class="line"><span class="cl"> * /usr/bin/tail: invalid number of lines: ‘+2 main.c /tmp/main.c <span class="o">&amp;&amp;</span> /usr/bin/gcc /tmp/main.c -o main <span class="o">&amp;&amp;</span> ./main <span class="c1">#’</span>
</span></span><span class="line"><span class="cl"> */
</span></span></code></pre>
<p>This doesn&rsquo;t work while everything after <code>tail</code> gets <a href="https://github.com/torvalds/linux/blob/3e732ebf7316ac83e8562db7e64cc68aec390a18/fs/binfmt_script.c#L81">interpreted as one argument</a>.</p>

<h2>binfmt fallback</h2>

<p>Just before I was about to give up, I&rsquo;ve found an <a href="https://stackoverflow.com/a/29709521">SO post</a> suggesting:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">//usr/bin/clang <span class="s2">&#34;</span><span class="nv">$0</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> <span class="nb">exec</span> ./a.out <span class="s2">&#34;</span><span class="nv">$@</span><span class="s2">&#34;</span>
</span></span></code></pre>
<p>I&rsquo;ve adapted it to my use-case and voila:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="c1">//usr/bin/gcc &#34;$0&#34; &amp;&amp; ./a.out &#34;$@&#34;;exit
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[</span><span class="p">]</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">argc</span><span class="p">;</span> <span class="n">i</span><span class="o">+</span><span class="o">+</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">%d: %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="cm">/* 
</span></span></span><span class="line"><span class="cl"><span class="cm"> * $ ./main.c 1 2 3
</span></span></span><span class="line"><span class="cl"><span class="cm"> * 0: ./a.out
</span></span></span><span class="line"><span class="cl"><span class="cm"> * 1: 1
</span></span></span><span class="line"><span class="cl"><span class="cm"> * 2: 2
</span></span></span><span class="line"><span class="cl"><span class="cm"> * 3: 3
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span></code></pre>
<ul>
<li><code>//</code>: c single-line comment to avoid gcc to interpret this line</li>
<li><code>//usr/bin/gcc &quot;$0&quot;</code>: compile file itself  using the absolute path to the compiler, multiple slashes will automatically compacted to one, so // is no problem</li>
<li><code>exec ./.aout &quot;$@&quot;</code>: execute the built binary (named <code>a.out</code> per default) with all arguments which were initially added to the program call <code>./program arg1 arg2...</code>, exec replaces the current process which is important as the rest of the c source file otherwise gets interpreted</li>
</ul>

<p>Well, I guess this works because after <code>binfmt</code> fails to detect any elf-binary or shebang, bash executes it in the current context, which is actually bash.</p>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Tue, 30 Jan 2024 16:28:16 +0100</pubDate>
    </item>
    <item>
      <title>go integration tests with ginkgo and gomega</title>
      <link>https://evilcookie.de/go-integration-tests-with-ginkgo-and-gomega.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>go integration tests with ginkgo and gomega</h1>

<p><img src="go-integration-tests-with-ginkgo-and-gomega_bdd.png"/></p>

<p>Today, I&rsquo;ve checked out the BDD<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> testing framework <a href="https://pkg.go.dev/github.com/onsi/ginkgo/v2">ginkgo</a> with the matcher library <a href="https://pkg.go.dev/github.com/onsi/gomega">gomega</a> for integration tests with go. The motivation was to find an alternative for my go-to testing framework <a href="https://rspec.info/documentation/3.9/rspec-expectations/">rspec</a>. Although in ruby, I anyway used it for go projects like <a href="https://github.com/RaphaelPour/blogctl/blob/main/spec.rb">blogctl</a>.</p>

<ul>
<li><a href="#rspec">rspec - Were I came from</a></li>
<li><a href="#integration-test-frameworks">Integration test frameworks in go</a></li>
<li><a href="#ginkgo">ginkgo</a>

<ul>
<li><a href="#setup">Setup</a></li>
<li><a href="#show-version">Show version</a></li>
<li><a href="#real-tests">Real tests</a></li>
</ul></li>
<li><a href="#thoughts">Thoughts</a></li>
</ul>

<h2>rspec - Where I came from<a id='rspec'/></h2>

<p>The rspec <a href="https://martinfowler.com/dsl.html">DSL</a> together with ruby itself makes it easy to write down tests pretty quickly. At least for me its quicker than doing the same in go (until now?):</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nb">require</span> <span class="s1">&#39;rspec&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nb">require</span> <span class="s1">&#39;open3&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">describe</span> <span class="s1">&#39;CLI&#39;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  <span class="n">context</span> <span class="s1">&#39;Trivial test cases&#39;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    <span class="n">it</span> <span class="s1">&#39;shows a version&#39;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">      <span class="n">out</span><span class="p">,</span> <span class="n">err</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="no">Open3</span><span class="o">.</span><span class="n">capture3</span><span class="p">(</span><span class="s2">&#34;</span><span class="s2">blogctl --version</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="n">expect</span><span class="p">(</span><span class="n">err</span><span class="p">)</span><span class="o">.</span><span class="n">to</span> <span class="n">eq</span> <span class="s2">&#34;</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="n">expect</span><span class="p">(</span><span class="n">out</span><span class="p">)</span><span class="o">.</span><span class="n">to</span> <span class="n">match</span><span class="p">(</span><span class="sr">/</span><span class="sr">BuildVersion:</span><span class="sr">/</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="n">expect</span><span class="p">(</span><span class="n">out</span><span class="p">)</span><span class="o">.</span><span class="n">to</span> <span class="n">match</span><span class="p">(</span><span class="sr">/</span><span class="sr">BuildDate:</span><span class="sr">/</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">end</span>
</span></span><span class="line"><span class="cl">  <span class="k">end</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span>
</span></span></code></pre>
<h2>Integration test frameworks in go<a id="integration-test-frameworks"/></h2>

<p>There are a bunch of testing frameworks on the  <a href="https://github.com/avelino/awesome-go#testing">awesome-go list</a> that look interesting for BDD integration testing.</p>

<table>
<thead>
<tr>
<th>Project</th>
<th>Active development</th>
<th>Specify tests within go</th>
<th>Various nestable containers</th>
<th><code>(Before|After)(All|Each)</code> scripts</th>
</tr>
</thead>

<tbody>
<tr>
<td><a href="https://github.com/fulldump/biff">fulldump/biff</a></td>
<td>y</td>
<td>n</td>
<td>?</td>
<td>?</td>
</tr>

<tr>
<td><a href="https://github.com/hedhyw/gherkingen">hedhyw/gherkingen</a></td>
<td>y</td>
<td>n</td>
<td>?</td>
<td>?</td>
</tr>

<tr>
<td><a href="https://github.com/onsi/ginkgo">ginkgo</a></td>
<td>y</td>
<td>y</td>
<td>y</td>
<td>y</td>
</tr>

<tr>
<td><a href="https://github.com/smartystreets/goconvey/">smartystreets/goconvey/</a></td>
<td>y</td>
<td>y</td>
<td>n</td>
<td>?</td>
</tr>

<tr>
<td><a href="https://github.com/cucumber/godog">cucumber/godog</a></td>
<td>y</td>
<td>n</td>
<td>y</td>
<td>?</td>
</tr>

<tr>
<td><a href="https://github.com/corbym/gogiven">corbym/gogiven</a></td>
<td>y</td>
<td>n</td>
<td>?</td>
<td>?</td>
</tr>

<tr>
<td><a href="https://github.com/luontola/gospec">luontola/gospec</a></td>
<td>n</td>
<td>y</td>
<td>?</td>
<td>?</td>
</tr>

<tr>
<td><a href="https://github.com/stesla/gospecify">stesla/gospecify</a></td>
<td>n</td>
<td>?</td>
<td>?</td>
<td>?</td>
</tr>

<tr>
<td><a href="https://github.com/pavlo/gosuite">pavlo/gosuite</a></td>
<td>n</td>
<td>y</td>
<td>n</td>
<td>y</td>
</tr>
</tbody>
</table>

<ul>
<li>Active development: last contribution was within the last year</li>
<li>Specify tests within go:  The test can be specified within go.</li>
<li>Various nestable containers: Analog to rspecs <code>decribe</code> and  <code>context</code> container that can be nested.</li>
<li><code>(Before|After)(All|Each)</code> scripts: rspec alike setup and tear down functions for all and test-wise</li>
<li><code>?</code>: I skipped evaluating this feature as it wasn&rsquo;t obvious from the readme and another feature was unsupported anyway.</li>
</ul>

<h2>ginkgo<a id="ginkgo"/></h2>

<p><a href="https://pkg.go.dev/github.com/onsi/ginkgo/v2">Ginkgo</a> offers a similar Given-When-Then approach after <a href="https://github.com/onsi/ginkgo#ginkgo">looking at the example in the readme</a>. <a href="https://pkg.go.dev/github.com/onsi/gomega">Gomega</a> is the matcher library, used by ginkgo. They&rsquo;re both from the same author.</p>

<p>I&rsquo;ve used my renaming tool <a href="https://evilcookie.de/how-to-rename-files-without-specifying-the-path-twice.html">r</a> to check it out.</p>

<h3>Setup<a id="setup"/></h3>

<ol>
<li>get ginkgo cli: <code>go install github.com/onsi/ginkgo/v2/ginkgo@latest</code></li>
<li>add gomega dependency to your go-mod-managed project: <code>go get github.com/onsi/gomega@latest</code></li>
<li>initialize ginkgo which creates a testing entrypoint aka test suite: <code>ginkgo bootstrap</code></li>
<li>generate spec for main: <code>ginkgo generate</code></li>
<li>run tests: <code>ginkgo</code></li>
</ol>

<p>This should&rsquo;ve created two files:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="c1">// test suite
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="c1">// r_suite_test.go
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kn">package</span> <span class="nx">r_test</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span> <span class="s">&#34;github.com/onsi/ginkgo/v2&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span> <span class="s">&#34;github.com/onsi/gomega&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;testing&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">TestBooks</span><span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nf">RegisterFailHandler</span><span class="p">(</span><span class="nx">Fail</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="nf">RunSpecs</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span> <span class="s">&#34;R Suite&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre><pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="c1">// spec
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="c1">// r_test.go
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kn">package</span> <span class="nx">r_test</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span> <span class="s">&#34;github.com/onsi/ginkgo/v2&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span> <span class="s">&#34;github.com/onsi/gomega&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">_</span> <span class="p">=</span> <span class="nf">Describe</span><span class="p">(</span><span class="s">&#34;R&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="p">)</span>
</span></span></code></pre>
<h3>Show version<a id="show-version"/></h3>

<p>At first I&rsquo;ve  adapted the version test from the previous rspec example:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main_test</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;os&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;os/exec&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;path/filepath&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="s">&#34;github.com/bsm/gomega/gbytes&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;github.com/bsm/gomega/gexec&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span> <span class="s">&#34;github.com/onsi/ginkgo/v2&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span> <span class="s">&#34;github.com/onsi/gomega&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">_</span> <span class="p">=</span> <span class="nf">Describe</span><span class="p">(</span><span class="s">&#34;R&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nf">When</span><span class="p">(</span><span class="s">&#34;binary is used correctly&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nf">It</span><span class="p">(</span><span class="s">&#34;shows version&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="nx">session</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">gexec</span><span class="p">.</span><span class="nf">Start</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">				<span class="nx">exec</span><span class="p">.</span><span class="nf">Command</span><span class="p">(</span><span class="s">&#34;ci-build/r&#34;</span><span class="p">,</span> <span class="s">&#34;--version&#34;</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">				<span class="nx">GinkgoWriter</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">				<span class="nx">GinkgoWriter</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="p">.</span><span class="nf">ShouldNot</span><span class="p">(</span><span class="nf">HaveOccurred</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Eventually</span><span class="p">(</span><span class="nx">session</span><span class="p">)</span><span class="p">.</span><span class="nf">Should</span><span class="p">(</span><span class="nx">gexec</span><span class="p">.</span><span class="nf">Exit</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">session</span><span class="p">.</span><span class="nx">Out</span><span class="p">)</span><span class="p">.</span><span class="nf">Should</span><span class="p">(</span><span class="nx">gbytes</span><span class="p">.</span><span class="nf">Say</span><span class="p">(</span><span class="s">`</span><span class="s">(?m)BuildVersion:.*\nBuildDate:</span><span class="s">`</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">session</span><span class="p">.</span><span class="nx">Err</span><span class="p">)</span><span class="p">.</span><span class="nf">Should</span><span class="p">(</span><span class="nx">gbytes</span><span class="p">.</span><span class="nf">Say</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="p">)</span>
</span></span></code></pre>
<ul>
<li>provides <a href="https://onsi.github.io/ginkgo/#organizing-specs-with-container-nodes">containers</a> like <code>Describe</code>, <code>When</code> and <code>It</code> similar to rspecs <code>describe</code>, <code>context</code> and <code>it</code></li>
<li>few more lines, words and brackets, as expected in go</li>
<li>gomega provides so-called <a href="https://onsi.github.io/gomega/#making-asynchronous-assertions">Asynchronous Assertions</a> like <code>Eventually</code> which checks the expection periodically for some time, which is very handy</li>
<li>helper libs like <code>gexec</code> and <code>gbytes</code> simplify the matcher that would otherwise be a bit more fiddly in go</li>
<li><code>gbytes</code> directly awaits the saying to be a regex, like a charm!</li>
</ul>

<h3>Real tests<a id="real-tests"/></h3>

<p>The following tests use before and after scripts that set up the temporary environment for some real<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> tests:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main_test</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;os&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;os/exec&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;path/filepath&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="s">&#34;github.com/bsm/gomega/gbytes&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;github.com/bsm/gomega/gexec&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span> <span class="s">&#34;github.com/onsi/ginkgo/v2&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="p">.</span> <span class="s">&#34;github.com/onsi/gomega&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">_</span> <span class="p">=</span> <span class="nf">Describe</span><span class="p">(</span><span class="s">&#34;R&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nf">When</span><span class="p">(</span><span class="s">&#34;binary is used correctly&#34;</span><span class="p">,</span> <span class="nx">Ordered</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="kd">var</span> <span class="nx">tempFile</span> <span class="o">*</span><span class="nx">os</span><span class="p">.</span><span class="nx">File</span>
</span></span><span class="line"><span class="cl">		<span class="kd">var</span> <span class="nx">tempDir</span> <span class="kt">string</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="nf">BeforeAll</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="kd">var</span> <span class="nx">err</span> <span class="kt">error</span>
</span></span><span class="line"><span class="cl">			<span class="nx">tempDir</span><span class="p">,</span> <span class="nx">err</span> <span class="p">=</span> <span class="nx">os</span><span class="p">.</span><span class="nf">MkdirTemp</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nf">TempDir</span><span class="p">(</span><span class="p">)</span><span class="p">,</span> <span class="s">&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="p">.</span><span class="nf">Should</span><span class="p">(</span><span class="nf">BeNil</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="nf">AfterAll</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="nx">os</span><span class="p">.</span><span class="nf">RemoveAll</span><span class="p">(</span><span class="nx">tempDir</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="nf">BeforeEach</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">ctx</span> <span class="nx">SpecContext</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="kd">var</span> <span class="nx">err</span> <span class="kt">error</span>
</span></span><span class="line"><span class="cl">			<span class="nx">tempFile</span><span class="p">,</span> <span class="nx">err</span> <span class="p">=</span> <span class="nx">os</span><span class="p">.</span><span class="nf">CreateTemp</span><span class="p">(</span><span class="nx">tempDir</span><span class="p">,</span> <span class="s">&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="p">.</span><span class="nf">ShouldNot</span><span class="p">(</span><span class="nf">HaveOccurred</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="nf">It</span><span class="p">(</span><span class="s">&#34;renames file&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="nx">renamed</span> <span class="o">:=</span> <span class="nx">filepath</span><span class="p">.</span><span class="nf">Base</span><span class="p">(</span><span class="nx">tempFile</span><span class="p">.</span><span class="nf">Name</span><span class="p">(</span><span class="p">)</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#34;2&#34;</span>
</span></span><span class="line"><span class="cl">			<span class="nx">session</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">gexec</span><span class="p">.</span><span class="nf">Start</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">				<span class="nx">exec</span><span class="p">.</span><span class="nf">Command</span><span class="p">(</span><span class="s">&#34;ci-build/r&#34;</span><span class="p">,</span> <span class="nx">tempFile</span><span class="p">.</span><span class="nf">Name</span><span class="p">(</span><span class="p">)</span><span class="p">,</span> <span class="nx">renamed</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">				<span class="nx">GinkgoWriter</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">				<span class="nx">GinkgoWriter</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="p">.</span><span class="nf">ShouldNot</span><span class="p">(</span><span class="nf">HaveOccurred</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Eventually</span><span class="p">(</span><span class="nx">session</span><span class="p">)</span><span class="p">.</span><span class="nf">Should</span><span class="p">(</span><span class="nx">gexec</span><span class="p">.</span><span class="nf">Exit</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">			<span class="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="p">=</span> <span class="nx">os</span><span class="p">.</span><span class="nf">Stat</span><span class="p">(</span><span class="nx">tempFile</span><span class="p">.</span><span class="nf">Name</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="p">.</span><span class="nf">To</span><span class="p">(</span><span class="nf">MatchError</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">IsNotExist</span><span class="p">,</span> <span class="s">&#34;It is not existing&#34;</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">			<span class="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="p">=</span> <span class="nx">os</span><span class="p">.</span><span class="nf">Stat</span><span class="p">(</span><span class="nx">filepath</span><span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="nx">tempDir</span><span class="p">,</span> <span class="nx">renamed</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="p">.</span><span class="nf">Should</span><span class="p">(</span><span class="nf">BeNil</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="nf">It</span><span class="p">(</span><span class="s">&#34;shows version&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="nx">session</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">gexec</span><span class="p">.</span><span class="nf">Start</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">				<span class="nx">exec</span><span class="p">.</span><span class="nf">Command</span><span class="p">(</span><span class="s">&#34;ci-build/r&#34;</span><span class="p">,</span> <span class="s">&#34;--version&#34;</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">				<span class="nx">GinkgoWriter</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">				<span class="nx">GinkgoWriter</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="p">.</span><span class="nf">ShouldNot</span><span class="p">(</span><span class="nf">HaveOccurred</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Eventually</span><span class="p">(</span><span class="nx">session</span><span class="p">)</span><span class="p">.</span><span class="nf">Should</span><span class="p">(</span><span class="nx">gexec</span><span class="p">.</span><span class="nf">Exit</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">session</span><span class="p">.</span><span class="nx">Out</span><span class="p">)</span><span class="p">.</span><span class="nf">Should</span><span class="p">(</span><span class="nx">gbytes</span><span class="p">.</span><span class="nf">Say</span><span class="p">(</span><span class="s">`</span><span class="s">(?m)BuildVersion:.*\nBuildDate:</span><span class="s">`</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">session</span><span class="p">.</span><span class="nx">Err</span><span class="p">)</span><span class="p">.</span><span class="nf">Should</span><span class="p">(</span><span class="nx">gbytes</span><span class="p">.</span><span class="nf">Say</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nf">When</span><span class="p">(</span><span class="s">&#34;binary is used incorrectly&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nf">It</span><span class="p">(</span><span class="s">&#34;fails without any argument&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="nx">command</span> <span class="o">:=</span> <span class="nx">exec</span><span class="p">.</span><span class="nf">Command</span><span class="p">(</span><span class="s">&#34;ci-build/r&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nx">session</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">gexec</span><span class="p">.</span><span class="nf">Start</span><span class="p">(</span><span class="nx">command</span><span class="p">,</span> <span class="nx">GinkgoWriter</span><span class="p">,</span> <span class="nx">GinkgoWriter</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="p">.</span><span class="nf">ShouldNot</span><span class="p">(</span><span class="nf">HaveOccurred</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Eventually</span><span class="p">(</span><span class="nx">session</span><span class="p">)</span><span class="p">.</span><span class="nf">Should</span><span class="p">(</span><span class="nx">gexec</span><span class="p">.</span><span class="nf">Exit</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">session</span><span class="p">.</span><span class="nx">Out</span><span class="p">)</span><span class="p">.</span><span class="nf">Should</span><span class="p">(</span><span class="nx">gbytes</span><span class="p">.</span><span class="nf">Say</span><span class="p">(</span><span class="s">&#34;usage: r &lt;path&gt; &lt;new_filename&gt;&#34;</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="nf">Expect</span><span class="p">(</span><span class="nx">session</span><span class="p">.</span><span class="nx">Err</span><span class="p">)</span><span class="p">.</span><span class="nf">Should</span><span class="p">(</span><span class="nx">gbytes</span><span class="p">.</span><span class="nf">Say</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="p">)</span>
</span></span></code></pre>
<ul>
<li><code>Ordered</code> container caveat: When defining before scripts, the superior container (which is <code>When</code> in this case) needs to have the <code>Ordered</code> <a href="https://onsi.github.io/ginkgo/#ordered-containers">Decorator</a> set. Looking at their example, they assume that resources are reused outside of one <code>It</code>, as some variables are defined in the superior container. But I&rsquo;m not sure why it can&rsquo;t just run all before&rsquo;s in hierarchical order like rspec can do it&hellip;</li>
<li>Despite the previous point, there are before and after scripts for suite, all and each. It just lacks in rspec&rsquo;s <code>around</code>.</li>
</ul>

<h2>Thoughts<a id="thoughts"/></h2>

<p>The tested framework feels much more like rspec than the standard library testing framework. It looks promising for BDD-alike tests in go.
I&rsquo;ll keep an eye on that when implementing integration tests for my next go projects.</p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1"><a href="https://en.wikipedia.org/wiki/Behavior-driven_development">Behavior-Driven-Development</a> having <a href="https://en.wikipedia.org/wiki/Given-When-Then">Given-When-Then</a>-alike structures.</li>

<li id="fn:2">Real as in it modifies the system environment by creating and removing files</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Tue, 23 Jan 2024 18:09:23 +0100</pubDate>
    </item>
    <item>
      <title>Continue interrupted uploads via dd</title>
      <link>https://evilcookie.de/continue-interrupted-uploads-via-dd.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Continue interrupted uploads via dd skip</h1>

<p><img src="continue-interrupted-uploads-via-dd_upload.jpg"/></p>

<p>While falling into <a href="https://github.com/Project-OSRM/osrm-backend">the routing engine rabbit hole</a> planing my next hiking trip via nextcloud maps, I needed to upload a big file to my server. Upload bandwidth sucked as it mostly does in Germany<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>. Well <code>scp</code> is my friend I guess:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ scp jakobsweg.tar.gz root@my.server:~/
</span></span><span class="line"><span class="cl">lost connection
</span></span></code></pre>
<p>Oops, after ten minutes with slow progress, the upload suddenly stopped due to a connection error.</p>

<h2>Problem</h2>

<p>Unfortunately scp can&rsquo;t continue an interrupted upload. There are some StackOverflow solutions about using <a href="https://stackoverflow.com/a/20860920">rsync</a> but
<a href="https://superuser.com/a/421688">this</a> solution using dd with its skip option got my attention.</p>

<h2>Upload what&rsquo;s missing</h2>

<p><a href="https://superuser.com/a/421688">The solution</a> suggest to just skip the already written bytes and append the rest to the destination file. Since this command is from
the server perspective and my local machine is in a NAT&rsquo;ed network which isn&rsquo;t accessible from the www, I did the steps manually:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="c1"># checkout sizes of the source and aborted destination file</span>
</span></span><span class="line"><span class="cl">server $ ls jakobsweg.tar.gz
</span></span><span class="line"><span class="cl">-rw-r--r--  <span class="m">1</span> root root <span class="m">490766336</span> Jan <span class="m">14</span> 14:26 jakobsweg.tar.gz
</span></span><span class="line"><span class="cl"><span class="nb">local</span> $ ls jakobsweg.tar.gz
</span></span><span class="line"><span class="cl">-rw-r--r-- <span class="m">1</span> raphael raphael <span class="m">1102126303</span> Jan <span class="m">14</span> 14:18 jakobsweg.tar.gz
</span></span><span class="line"><span class="cl"><span class="nb">local</span> $ <span class="nv">UPLOADED</span><span class="o">=</span><span class="m">490766336</span>
</span></span><span class="line"><span class="cl"><span class="nb">local</span> $ <span class="nv">REMAINING</span><span class="o">=</span><span class="k">$((</span><span class="m">1102126303</span> <span class="o">-</span> <span class="nv">$UPLOADED</span><span class="k">))</span>
</span></span><span class="line"><span class="cl"><span class="c1"># copy source file locally but skip the already transmitted bytes, divide remaining by something to raise the blocksize</span>
</span></span><span class="line"><span class="cl"><span class="c1"># while copying with a blocksize takes ages, better fill up the filesystem alignment</span>
</span></span><span class="line"><span class="cl"><span class="nb">local</span> $ dd <span class="k">if</span><span class="o">=</span>jakobsweg.tar.gz <span class="nv">of</span><span class="o">=</span>jakobsweg.tar.gz.part2 <span class="nv">skip</span><span class="o">=</span><span class="nv">$UPLOADED</span> <span class="nv">count</span><span class="o">=</span><span class="k">$((</span><span class="nv">$REMAINING</span><span class="o">/</span><span class="m">1024</span><span class="o">)</span> <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">status</span><span class="o">=</span>progress
</span></span><span class="line"><span class="cl"><span class="c1"># upload the remaining data as usual</span>
</span></span><span class="line"><span class="cl"><span class="nb">local</span> $ scp jakobsweg.tar.gz.part2 root@my.server:~/
</span></span><span class="line"><span class="cl"><span class="c1"># append the remaining data to the aborted file</span>
</span></span><span class="line"><span class="cl">remote $ cat jakobsweg.tar.gz.part2 &gt;&gt; jakobsweg.tar.gz
</span></span><span class="line"><span class="cl"><span class="c1"># compare checksum -&gt; tada</span>
</span></span><span class="line"><span class="cl"><span class="nb">local</span> $ shasum jakobsweg.tar.gz
</span></span><span class="line"><span class="cl">a8b00b334319932b5794595f3eafc1c5bedfaa35  jakobsweg.tar.gz
</span></span><span class="line"><span class="cl">remote $ shasum jakobsweg.tar.gz
</span></span><span class="line"><span class="cl">a8b00b334319932b5794595f3eafc1c5bedfaa35  jakobsweg.tar.gz
</span></span></code></pre>
<div class="footnotes">

<hr>

<ol>
<li id="fn:1">citation needed</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Mon, 15 Jan 2024 23:44:55 +0100</pubDate>
    </item>
    <item>
      <title>verbose v1.1.0-edit support</title>
      <link>https://evilcookie.de/verbose-v110-edit-support.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>verbose v1.1.0 - example and edit support</h1>

<p>I recently <a href="https://evilcookie.de/hola-docker-mucho-gusto.html">got a new motivation</a> to update my vocabulary service <a href="https://verbose.raphaelpour.de">verbose</a>.
Each word can have an example sentence together with its translation now. Verbose has also a new edit page.</p>

<h2>Example support</h2>

<p><img src="verbose-v110-edit-support_verbose1.png"/></p>

<p>When learning new words it could be useful to have a helpful example. This adds more context to the translation. Having an example
is also useful for learning a whole new language, <a href="https://evilcookie.de/hola-docker-mucho-gusto.html">like spanish in my case</a>. I barely know 100 words, where an example sentece would not only contain
one unknown/hard to remember word but multiple.</p>

<p>To follow the <a href="https://en.wikipedia.org/wiki/KISS_principle">KISS principle</a> together with my <a href="https://evilcookie.de/rework-of-verbose.html">I-only-add-a-word-per-month-and-view-it-once-a-day</a> use-case, I still use my json file and added two fields containing the original example sentence such as its translation.</p>

<h2>Edit support</h2>

<p><img src="verbose-v110-edit-support_verbose2.png"/></p>

<p>In the past, if I made a typo, I ssh&rsquo;ed to the server, opened the json file and corrected the word manually. However, having a new &ldquo;column&rdquo; which is initialy empty for each word, I felt the need of
edit each entry via the service itself. I&rsquo;ve added another site that just POST&rsquo;s the changes. Unfortunately I can&rsquo;t use PUT, which would be the right method to
modify a resource, since <a href="https://softwareengineering.stackexchange.com/a/211790">this is not allowed</a>.</p>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Mon, 08 Jan 2024 13:02:41 +0100</pubDate>
    </item>
    <item>
      <title>Hola docker, mucho gusto</title>
      <link>https://evilcookie.de/hola-docker-mucho-gusto.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Hola docker, mucho gusto!<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup></h1>

<p><img src="hola-docker-mucho-gusto_docker.png"/></p>

<p>I&rsquo;m currently learning Spanish for my next vacation<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>. While Duolingo does an impressive job of <a href="https://raw.studio/blog/how-duolingo-utilises-gamification/">gamifying the learning process</a>, I thought about
combining this fairly unknown world with one that I&rsquo;m familiar with.</p>

<p>I use Linux and its utils a lot. I like to read man pages and I know a bunch of them. Why not switch the system language to Spanish then?</p>

<p>Well, maybe because 100 words is not enough&hellip; but in a fire-and-forget environment like a virtual machine or Docker container, it should be safe.</p>

<h3>Contents</h3>

<ul>
<li><a href="#dockerfile">Dockerfile</a>

<ul>
<li><a href="#intermezzo">Intermezzo - Minimized containers</a></li>
</ul></li>
<li><a href="#groping">Groping in the dark, anticipating light</a>

<ul>
<li><a href="#apt-update">apt update</a></li>
<li><a href="#apropos">apropos .</a></li>
<li><a href="#man-bash">man bash</a></li>
</ul></li>
<li><a href="#learnings">Today I learned</a></li>
</ul>

<h2>Dockerfile<a id='dockerfile'/></h2>

<p>After some fiddling with <a href="https://www.man7.org/linux/man-pages/man1/locale.1.html"><code>locale</code></a> I came up with this Dockerfile:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">FROM ubuntu:latest
</span></span><span class="line"><span class="cl">RUN yes|unminimize
</span></span><span class="line"><span class="cl">RUN apt update &amp;&amp; \
</span></span><span class="line"><span class="cl">    DEBIAN_FRONTEND=noninteractive apt install -y locales \
</span></span><span class="line"><span class="cl">                                                  man-db \
</span></span><span class="line"><span class="cl">                                                  manpages-es \
</span></span><span class="line"><span class="cl">                                                  manpages-es-dev \
</span></span><span class="line"><span class="cl">                                                  language-pack-es
</span></span><span class="line"><span class="cl">RUN sed -i -e &#39;s/# en_US.UTF-8 UTF-8/es_ES.UTF-8 UTF-8/&#39; /etc/locale.gen &amp;&amp; \
</span></span><span class="line"><span class="cl">    dpkg-reconfigure --frontend=noninteractive locales &amp;&amp; \
</span></span><span class="line"><span class="cl">        update-locale LANG=es_ES.UTF-8
</span></span><span class="line"><span class="cl">ENV LANG es_ES.UTF-8
</span></span></code></pre>
<ul>
<li>unminimize Ubuntu container so man pages works</li>
<li>install man-db and their Spanish translations</li>
<li>install the language pack containing the translations for the system</li>
<li>replace the language where needed</li>
</ul>

<h3>Intermezzo - Minimized containers<a id='intermezzo'/></h3>

<p>Skip this if you just want to learn Spanish.</p>

<p>The Ubuntu container <a href="https://hub.docker.com/_/ubuntu"><em>[&hellip;] is a minimal install of Ubuntu[&hellip;]</em></a> and needs to get unminimized in order to be &ldquo;human-friendly&rdquo;.</p>

<p>Otherwise, <code>man bash</code> prints:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">This system has been minimized by removing packages and content that are
</span></span><span class="line"><span class="cl">not required on a system that users do not log into.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">To restore this content, including manpages, you can run the &#39;unminimize&#39;
</span></span><span class="line"><span class="cl">command. You will still need to ensure the &#39;man-db&#39; package is installed.
</span></span></code></pre>
<p>Actually <code>/usr/bin/man</code> is a bash script that only outputs this text.</p>

<p>What does the <code>unminimize</code> actually do? Tell me, <code>cat $(which unminimize)</code>: I&rsquo;ve put the output <a href="https://gist.github.com/RaphaelPour/e1a192beaae97f785033944ef96f4c83">into a gist</a>. It basically enabled documentation and man-pages again.</p>

<h2>Groping in the dark, anticipating light<a id='groping'/></h2>

<p>Those 100 words I know are more about traveling and less about updating Ubuntu packages&hellip;</p>

<p>But, hey, you know what the messages should be about and anticipate their translation.</p>

<h3>apt update<a id='apt-update'/></h3>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">root@1e7e70970891:/# apt update
</span></span><span class="line"><span class="cl">Des:1 http://security.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
</span></span><span class="line"><span class="cl">Des:2 http://security.ubuntu.com/ubuntu jammy-security/universe amd64 Packages [1.046 kB]
</span></span><span class="line"><span class="cl">Obj:3 http://archive.ubuntu.com/ubuntu jammy InRelease
</span></span><span class="line"><span class="cl">Des:4 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [119 kB]
</span></span><span class="line"><span class="cl">Obj:5 http://archive.ubuntu.com/ubuntu jammy-backports InRelease
</span></span><span class="line"><span class="cl">Des:6 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages [1.599 kB]
</span></span><span class="line"><span class="cl">Des:7 http://archive.ubuntu.com/ubuntu jammy-updates/universe amd64 Packages [1.305 kB]
</span></span><span class="line"><span class="cl">Descargados 4.179 kB en 6s (755 kB/s)
</span></span><span class="line"><span class="cl">Leyendo lista de paquetes... Hecho
</span></span><span class="line"><span class="cl">Creando árbol de dependencias... Hecho
</span></span><span class="line"><span class="cl">Leyendo la información de estado... Hecho
</span></span><span class="line"><span class="cl">Todos los paquetes están actualizados.
</span></span></code></pre>
<ul>
<li><em>Hecho</em> must be something like &lsquo;done&rsquo;: it literaly means something like <em>fact</em> or <em>complete</em></li>
<li><em>dependencias</em> is easy:  dependencies</li>
<li><em>información</em> too: information</li>
</ul>

<h3>apropos .<a id='apropos'/></h3>

<p><code>apropos .</code> is a great way to display one tool per line, including a description<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup>. Some favorites of mine:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">echo (1)             - muestra una línea de texto
</span></span><span class="line"><span class="cl">futex (7)            - bloqueos rápidos en espacio de usuario
</span></span><span class="line"><span class="cl">hostname (7)         - descripción de la resolución del nombre de equipo
</span></span><span class="line"><span class="cl">man (1)              - interfaz de los manuales de referencia del sistema
</span></span><span class="line"><span class="cl">memccpy (3)          - copia un área de memoria
</span></span><span class="line"><span class="cl">memcmp (3)           - compara areas de memoria
</span></span><span class="line"><span class="cl">memcpy (3)           - copiar area de memoria
</span></span><span class="line"><span class="cl">memmem (3)           - localiza una subcadena
</span></span><span class="line"><span class="cl">memmove (3)          - copia un área de memoria
</span></span><span class="line"><span class="cl">memset (3)           - rellena una zona de memoria con bytes repetidos
</span></span><span class="line"><span class="cl">md5sum (1)           - genera y verifica sumas de comprobación MD5
</span></span><span class="line"><span class="cl">stpcpy (3)           - copia una cadena devolviendo un apuntador a su final
</span></span><span class="line"><span class="cl">strcasecmp (3)       - comparan dos cadenas ignorando si son mayúsculas o minúsculas
</span></span><span class="line"><span class="cl">strstr (3)           - localiza una subcadena
</span></span><span class="line"><span class="cl">strchr (3)           - localizan un carácter en una cadena de ellos
</span></span><span class="line"><span class="cl">strdup (3)           - duplican una cadena de caracteres
</span></span><span class="line"><span class="cl">strlen (3)           - calcula la longitud de una cadena de caracteres
</span></span></code></pre>
<p>Especially all those C <em>mem*</em> and <em>str*</em> functions were fairly easy to anticipate when listed together:</p>

<ul>
<li><em>caracteres</em>: character, personality, both English and Spanish words seem to have the same origin, while both can be a &ldquo;written symbol&rdquo;, such as &ldquo;personality&rdquo;</li>
<li><em>copia</em>: copy</li>
<li><em>compara</em>: compare</li>
<li><em>interfaz</em>: interface</li>
<li><em>repetidos</em>: he repeats, male form of repetide</li>
<li><em>texto</em>: text</li>
<li><em>sumas</em>: you add, join</li>
</ul>

<h3>man bash<a id='man-bash'/></h3>

<p>Every time I accidentally look for the man page of a bash built-in, I get the huge bash man-page containing lots of essentials. In this case, this is exactly what we want.
It offers everything from abstract basics like lists, expressions and comparisons to more practical features like the actual built-in commands.</p>

<p>Some of my favorite entries:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">(lista)       lista se ejecuta en un subshell
</span></span><span class="line"><span class="cl">{ lista; }    lista se ejecuta en el entorno actual de la shell
</span></span><span class="line"><span class="cl">((expresión)) La expresión se evalúa de acuerdo a las reglas descritas abajo bajo la sección EVALUACIÓN ARITMÉTICA.
</span></span><span class="line"><span class="cl">
</span></span></code></pre>
<h2>Today I learned<a id='learnings'/></h2>

<table>
<thead>
<tr>
<th>es</th>
<th>en</th>
<th>example es</th>
<th>example en</th>
</tr>
</thead>

<tbody>
<tr>
<td>información</td>
<td>information</td>
<td>Yo tengo información.</td>
<td>I have information.</td>
</tr>

<tr>
<td>dependecias</td>
<td>dependencies</td>
<td>Vim necesite dependencias.</td>
<td>Vim needs dependencies.</td>
</tr>

<tr>
<td>memoria</td>
<td>memory</td>
<td>Copiar area de memoria.</td>
<td>Copy memory area.</td>
</tr>

<tr>
<td>caracteres</td>
<td>character, personality</td>
<td>ASCII tiene 128 characteres</td>
<td>ASCII has 128 characters.</td>
</tr>

<tr>
<td>copia</td>
<td>copy</td>
<td>El programa copia el texto.</td>
<td>The program copies the text.</td>
</tr>

<tr>
<td>compara</td>
<td>compare</td>
<td>Compara ambios programas</td>
<td>Compare both programs.</td>
</tr>

<tr>
<td>interfaz</td>
<td>interface</td>
<td>Está activa sur interfaz de eth0?</td>
<td>Is your eth0 interface up?</td>
</tr>

<tr>
<td>repetidos</td>
<td colspan="3">he repeats</td>
</tr>

<tr>
<td>texto</td>
<td>text</td>
<td>Soy un texto</td>
<td>I&rsquo;m a text.</td>
</tr>

<tr>
<td>sumas</td>
<td>you add, join</td>
<td>Él suma los números.</td>
<td>He adds the numbers.</td>
</tr>

<tr>
<td>hecho</td>
<td>done, complete, fact</td>
<td>Bien hecho!</td>
<td>Well done!</td>
</tr>
</tbody>
</table>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1"><em>Hello docker, nice to meet you</em></li>

<li id="fn:2">The caminho portugeś &ldquo;Jakobsweg&rdquo; (<a href="https://en.wikipedia.org/wiki/Camino_de_Santiago">Caminoh de Santiago</a>) with <a href="https://github.com/Tch1b0">Johannes</a>.</li>

<li id="fn:3">Where I still see a lot of English. Either I forgot some settings/packages, or the translation is still in progress.</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Thu, 04 Jan 2024 17:50:36 +0100</pubDate>
    </item>
    <item>
      <title>hashsets in go</title>
      <link>https://evilcookie.de/hashsets-in-go.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Hashsets in go</h1>

<p><img src="hashsets-in-go_hashset.png"/></p>

<p>tl;dr</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">hashSet</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kd">struct</span><span class="p">{</span><span class="p">}</span>
</span></span></code></pre>
<h2>Introduction</h2>

<p>The term HashSet is a data structure from the <a href="https://docs.oracle.com/javase/8/docs/api/java/util/HashSet.html">Java universe</a> describing a value-less HashMap<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>. It is perfect when uniqueness is needed but avoids the overhead of a value.
Using golang they can be constructed using an ordinary map and an empty struct:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">hashSet</span> <span class="kd">map</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="kd">struct</span><span class="p">{</span><span class="p">}</span>
</span></span></code></pre>
<h2>Use Cases</h2>

<p>The key can be any <a href="https://go.dev/ref/spec#MapType">supported type</a>. Interestingly, next to the primitive ones (<code>int</code>, <code>string</code>,&hellip;), struct types are also supported. This comes quite handy when making custom cache keys.</p>

<h3>Visited nodes</h3>

<p>When searching through a grid or a graph, a HashSet can be used to avoid loops by caching already seen points:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Point</span> <span class="kd">struct</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">x</span><span class="p">,</span><span class="nx">y</span> <span class="kt">int</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">visited</span> <span class="kd">map</span><span class="p">[</span><span class="nx">Point</span><span class="p">]</span><span class="kd">struct</span><span class="p">{</span><span class="p">}</span>
</span></span></code></pre>
<h3>Uniqueness</h3>

<p>Another use-case would be to ensure uniqueness over a dataset. E.g. the bash command <code>uniq</code> reads a stream from stdin and only prints every line once to stdout:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s">&#34;bufio&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="s">&#34;fmt&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="s">&#34;os&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">set</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kd">struct</span><span class="p">{</span><span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">scanner</span> <span class="o">:=</span> <span class="nx">bufio</span><span class="p">.</span><span class="nf">NewScanner</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stdin</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="nx">scanner</span><span class="p">.</span><span class="nf">Scan</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">found</span> <span class="o">:=</span> <span class="nx">set</span><span class="p">[</span><span class="nx">scanner</span><span class="p">.</span><span class="nf">Text</span><span class="p">(</span><span class="p">)</span><span class="p">]</span><span class="p">;</span> <span class="p">!</span><span class="nx">found</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nx">set</span><span class="p">[</span><span class="nx">scanner</span><span class="p">.</span><span class="nf">Text</span><span class="p">(</span><span class="p">)</span><span class="p">]</span> <span class="p">=</span> <span class="kd">struct</span><span class="p">{</span><span class="p">}</span><span class="p">{</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">scanner</span><span class="p">.</span><span class="nf">Text</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>Turning&hellip;</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"> I&#39;ve experiments to run.
</span></span><span class="line"><span class="cl"> There is research to be done.
</span></span><span class="line"><span class="cl"> On the people who are
</span></span><span class="line"><span class="cl"> still alive.
</span></span><span class="line"><span class="cl"> And believe me I am
</span></span><span class="line"><span class="cl"> still alive.
</span></span><span class="line"><span class="cl"> I&#39;m doing science and I&#39;m
</span></span><span class="line"><span class="cl"> still alive.
</span></span><span class="line"><span class="cl"> I feel fantastic and I&#39;m
</span></span><span class="line"><span class="cl"> still alive.
</span></span><span class="line"><span class="cl"> While you&#39;re dying I&#39;ll be
</span></span><span class="line"><span class="cl"> still alive.
</span></span><span class="line"><span class="cl"> And when you&#39;re dead I will be
</span></span><span class="line"><span class="cl"> still alive.
</span></span></code></pre>
<p>&hellip;via <code>cat lyrics| go run unique.go</code> to&hellip;</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">I&#39;ve experiments to run.
</span></span><span class="line"><span class="cl">There is research to be done.
</span></span><span class="line"><span class="cl">On the people who are
</span></span><span class="line"><span class="cl">still alive.
</span></span><span class="line"><span class="cl">And believe me I am
</span></span><span class="line"><span class="cl">I&#39;m doing science and I&#39;m
</span></span><span class="line"><span class="cl">I feel fantastic and I&#39;m
</span></span><span class="line"><span class="cl">While you&#39;re dying I&#39;ll be
</span></span><span class="line"><span class="cl">And when you&#39;re dead I will be
</span></span></code></pre>
<h2>References</h2>

<ul>
<li><a href="https://github.com/RaphaelPour/aoc2023/blob/main/days/10/part.go#L138">example</a></li>
<li>Hashicorp go-package for more sophisticated HashSet usages: <a href="https://pkg.go.dev/github.com/hashicorp/go-set">go-set</a></li>
</ul>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">Same as <code>map</code> in <a href="https://go.dev/blog/maps">golang</a>, <code>dict</code> in <a href="https://docs.python.org/3/tutorial/datastructures.html#dictionaries">python</a>, associative arrays in <a href="https://www.php.net/manual/en/language.types.array.php">php</a></li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Thu, 14 Dec 2023 14:15:50 +0100</pubDate>
    </item>
    <item>
      <title>how to rename files without specifying the path twice</title>
      <link>https://evilcookie.de/how-to-rename-files-without-specifying-the-path-twice.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>How to rename files without specifying the path twice</h1>

<p><img src="how-to-rename-files-without-specifying-the-path-twice_schweini.jpg"/></p>

<p>How to avoid <code>mv /this/is/a/long/path/to/my/guinea/pig/trfel.pig /this/is/a/long/path/to/my/guinea/pig/trueffel.pig</code> and just do something like <code>&lt;cmd&gt; /this/is/a/long/path/to/my/guinea/pig/trfel.file trueffel.pig</code>?</p>

<p>Maybe I&rsquo;m totally off today<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>, or this naive question hasn&rsquo;t a navie answer. Anyway, I couldn&rsquo;t come up
with a straight-forward solution within my bash<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>.</p>

<p>I&rsquo;d like to have an easy memorable solution without pattern matching or syntax.</p>

<h2>DIY</h2>

<p>I came up with my own renaming tool, just wrapping the <code>os.Rename</code> call with the right parameters:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;fmt&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;os&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;path/filepath&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Args</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">3</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;usage: r &lt;path&gt; &lt;new_filename&gt;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">newPath</span> <span class="o">:=</span> <span class="nx">filepath</span><span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="nx">filepath</span><span class="p">.</span><span class="nf">Dir</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Args</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="p">)</span><span class="p">,</span> <span class="nx">os</span><span class="p">.</span><span class="nx">Args</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">os</span><span class="p">.</span><span class="nf">Rename</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Args</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="p">,</span> <span class="nx">newPath</span><span class="p">)</span><span class="p">;</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;error renaming %s to %s: %s\n&#34;</span><span class="p">,</span> <span class="nx">os</span><span class="p">.</span><span class="nx">Args</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="p">,</span> <span class="nx">newPath</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%s -&gt; %s\n&#34;</span><span class="p">,</span> <span class="nx">os</span><span class="p">.</span><span class="nx">Args</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="p">,</span> <span class="nx">newPath</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>Which works like:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">&gt; r /home/jane/dev/r/main.c main.go
</span></span><span class="line"><span class="cl">/home/jane/dev/r/main.c -&gt; /home/jane/dev/r/main.go
</span></span></code></pre>
<h2>SO solutions</h2>

<p>I found this <a href="https://unix.stackexchange.com/questions/132235/quickest-way-to-rename-files-without-retyping-directory-path">SO Post</a> afterwards, but wasn&rsquo;t satisfied. The <a href="https://unix.stackexchange.com/a/132237">acknowledged answer</a> using <code>mv</code> and brace-expansion only works if the suffix need to be renamed. The <a href="https://unix.stackexchange.com/a/132241">next answer</a> with <code>rename</code> is imo not intuitive. I just want to rename without any generic/pattern/expansion stuff.</p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">Like my guinea pig <em>Trüffel</em> (see feature image) who&rsquo;s waiting for the next kohlrabi feeding.</li>

<li id="fn:2">Please prove me wrong and show me an easy way feedback@evilcookie.de</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Wed, 15 Nov 2023 18:26:47 +0100</pubDate>
    </item>
    <item>
      <title>measure downtime durations via icmp</title>
      <link>https://evilcookie.de/measure-downtime-durations-via-icmp.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>measure downtime durations via icmp</h1>

<p><img src="measure-downtime-durations-via-icmp_downtime.jpg"/></p>

<p>How long does it take for the failover mechanism to fail-over? How long does it take for my server to be up again?</p>

<p>I recently had the challenge of measuring downtime durations. <a href="https://linux.die.net/man/8/ping">ping</a> on the one hand &ldquo;makes me see&rdquo; when paket loss occurs and vanishes but lacks in aggregation. <a href="https://linux.die.net/man/8/mtr">mtr</a> on the other side aggregates the replies, but not for the metric I was looking for.</p>

<p>So I made up my own tool namely <a href="https://github.com/RaphaelPour/downtime"><code>downtime</code></a>. Aside the plain measurement logic, I tried a few new things like <em>external lib interfaces</em> and <em>mocks</em> which will shortly be addressed in the end.</p>

<ul>
<li><a href="#how-it-works">How it works</a></li>
<li><a href="#example">Example</a></li>
<li><a href="#design">Implementation design</a>

<ul>
<li><a href="#interface">External lib interface</a></li>
<li><a href="#mocks">Mocks</a></li>
<li><a href="#extensibility">Extensibility</a></li>
</ul></li>
</ul>

<h2>How it works<a id='how-it-works'/></h2>

<p>Ping the host via icmp using a customized timeout and a small interval to pinpoint the start and end timestamp of the downtime. This can then be used to calculate the duration.</p>

<p>The timeout should be as low as possible. The RTT of my service was not higher than 25ms, so 50ms timeout should be good to go. It should also tolerate some spikes that might appear randomly without falsifying our measurements. The interval should be pretty low and defines the error of the downtime.</p>

<p>The icmp logic is based on my colleagues <a href="https://github.com/tonobo/mtr">mtr</a> go-rewrite providing me <a href="https://github.com/tonobo/mtr/blob/master/pkg/icmp/icmp.go#L38">the most high-level icmp interface</a> I could find. This enables me to use raw icmp pakets without caring about the low level stuff like encoding the PID into the request body to fish out the corresponding replies from the ocean of icmp traffic.</p>

<h2>Example<a id='example'/></h2>

<p>To answer the second of the two initial questions &ldquo;How long does it take for my server to be up again after?&rdquo;:</p>

<ol>
<li>start downtime with server ip</li>
<li>restart server</li>
<li>wait until server is up again and downtime terminated</li>
</ol>

<p>For my cloud server with no further setup this took 17s:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ downtime --target 23.88.32.x
</span></span><span class="line"><span class="cl">start: 2023-09-22 12:27:31.751644064 +0200 CEST m=+11.151409405
</span></span><span class="line"><span class="cl">end: 2023-09-22 12:27:49.278929522 +0200 CEST m=+28.678694794
</span></span><span class="line"><span class="cl">duration: 17.527285389s
</span></span></code></pre>
<h2>Implementation design<a id='design'/></h2>

<p>Aside from the measurement logic, I tried a few things I&rsquo;ve learned over the years to improve extensibility and maintainability.</p>

<h3>External lib interface<a id='interface'/></h3>

<p>Define an interface for an external lib only containing needed functions. E.g. <a href="https://github.com/RaphaelPour/downtime/blob/main/icmp.go">icmp.go</a> for my dependency to <a href="https://github.com/tonobo/mtr/blob/master/pkg/icmp/icmp.go#L38">tonobo&rsquo;s SendICMP</a>. While beeing a bit verbose in the first place, it has two advantages:</p>

<ol>
<li>The dependency to the external lib is documented at one place. Usually you&rsquo;d need to scan the whole code base for the external lib to check whcih functions are in use.</li>
<li>Testing of complex external functions gets a lot easier. E.g. my unit test don&rsquo;t need to do real icmp stuff using mocks.</li>
</ol>

<h3>Mocks<a id='mocks'/></h3>

<p>Interfaces can easily be mocked using a lib like <a href="https://vektra.github.io/mockery/latest/">mockery</a>. E.g. <a href="https://github.com/RaphaelPour/downtime/blob/main/mocks/ICMP.go">icmp mock</a> for my <a href="https://github.com/RaphaelPour/downtime/blob/main/icmp.go">icmp interface</a>. As mentioned previously the mock can be used to test the lib without calling the external library. The goal of testing should be to test the <em>own</em> and not the <em>external</em> code.</p>

<h3>Extensibility<a id='extensibility'/></h3>

<p>I&rsquo;ve decided to provide the package as both: lib and binary. The only quirk is that the install url ends with <code>downtime/cmd/downtime</code>, but hence all people would copy the go install command from my readme anyway, it doesn&rsquo;t really matter.</p>

<p>In the end, the binary is just a specialized implementation of the watcher and reply checker. The watcher gets called two times: first time blocking until the first reply times out and the second time blocking until the first reply succeeds again. User of the lib can bend this my making they&rsquo;re own checker.</p>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Fri, 22 Sep 2023 17:24:32 +0200</pubDate>
    </item>
    <item>
      <title>Godot Wild Jam 60</title>
      <link>https://evilcookie.de/godot-wild-jam-60.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Godot Wild Jam 60</h1>

<p><img src="godot-wild-jam-60_overview.png"/></p>

<p>We<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> participated at the <a href="https://itch.io/jam/godot-wild-jam-60">Godot Wild Jam #60</a> with the theme <em>malfunction</em> and submitted <a href="https://itch.io/jam/godot-wild-jam-60/rate/2225903">Rebot Roboot</a>: <em>Repair your robotic companion after a failed firmware update.</em></p>

<ul>
<li><a href="https://itch.io/jam/godot-wild-jam-60/rate/2225903">jam submission</a></li>
<li><a href="https://evilc00kie.itch.io/rebot-roboot">game</a></li>
<li><a href="https://github.com/Glow-Project/gwj-60">source</a></li>
<li>soundtrack: <a href="https://soundcloud.com/beathoevn/mandarin-marshmallow">Mandarin Marshmallow</a></li>
<li>one wildcard implemented:  <em>Mobius loop</em> Your game starts and ends at the same point.</li>
</ul>

<h3>Contents</h3>

<ul>
<li><a href="#idea">Idea</a></li>
<li><a href="#mechanics">Minigame mechanics</a>

<ul>
<li><a href="#wires">Wires</a></li>
<li><a href="#gates">Logic gates</a></li>
<li><a href="#optics">Optics</a></li>
<li><a href="#brain">Brain</a></li>
</ul></li>
<li><a href="#summary">Summary</a></li>
</ul>

<h2>Idea<a id='idea'/></h2>

<p>Your robotic companion has malfunctions after a failed firmware update and needs to be repaired. Each of the four malfunctions corresponds to one minigame that needs to be resolved in order to make the robot fully functional again.</p>

<p><img src="godot-wild-jam-60_lab.png"/></p>

<p>The main scene is a lab with monitors to toggle music and the boot sequence and a table with icons to all minigames. We decided to not immediately show the success of a mini game to increase the tension. The player can press reboot on the right monitor which triggers a test suite validating all minigames sequentially. If one validation fails, an error message is printed for a few seconds and all minigames were reset. Each minigame has its own validation function.</p>

<h2>Minigame mechanics <a id='mechanics'/></h2>

<h3>Wires <a id='wires'/></h3>

<p>Connect all the jacks pair-wise having the same color by drag-and-dropping wires.</p>

<p><img src="godot-wild-jam-60_wires.png"/></p>

<p>Each jack has a color and is instanciated within Godot. They get randomly positioned <a href="https://github.com/Glow-Project/gwj-60/blob/master/levels/wires/wires.gd#L23C1-L43C10">on startup</a> within the jack boundary aligned<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> to a grid via modulo (so they look more circuit alike):</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="c1"># Called when the node enters the scene tree for the first time.</span>
</span></span><span class="line"><span class="cl"><span class="n">func</span> <span class="n">_ready</span><span class="p">(</span><span class="p">)</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">  <span class="n">var</span> <span class="n">taken</span> <span class="p">:</span><span class="n">Array</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="err">$</span><span class="n">Jacks</span><span class="o">.</span><span class="n">get_children</span><span class="p">(</span><span class="p">)</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">node</span> <span class="o">=</span> <span class="n">node</span> <span class="k">as</span> <span class="n">Jack</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">while</span> <span class="n">true</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="n">var</span> <span class="n">x_offset</span> <span class="o">=</span> <span class="n">randi_range</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="err">$</span><span class="n">JackBoundary</span><span class="o">.</span><span class="n">position</span><span class="o">.</span><span class="n">x</span> <span class="o">-</span> <span class="err">$</span><span class="n">JackBoundary</span><span class="o">.</span><span class="n">shape</span><span class="o">.</span><span class="n">get_rect</span><span class="p">(</span><span class="p">)</span><span class="o">.</span><span class="n">size</span><span class="o">.</span><span class="n">x</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="err">$</span><span class="n">JackBoundary</span><span class="o">.</span><span class="n">position</span><span class="o">.</span><span class="n">x</span> <span class="o">+</span> <span class="err">$</span><span class="n">JackBoundary</span><span class="o">.</span><span class="n">shape</span><span class="o">.</span><span class="n">get_rect</span><span class="p">(</span><span class="p">)</span><span class="o">.</span><span class="n">size</span><span class="o">.</span><span class="n">x</span><span class="o">/</span><span class="mi">2</span>
</span></span><span class="line"><span class="cl">      <span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="n">var</span> <span class="n">y_offset</span> <span class="o">=</span> <span class="n">randi_range</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="err">$</span><span class="n">JackBoundary</span><span class="o">.</span><span class="n">position</span><span class="o">.</span><span class="n">y</span> <span class="o">-</span> <span class="err">$</span><span class="n">JackBoundary</span><span class="o">.</span><span class="n">shape</span><span class="o">.</span><span class="n">get_rect</span><span class="p">(</span><span class="p">)</span><span class="o">.</span><span class="n">size</span><span class="o">.</span><span class="n">y</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="err">$</span><span class="n">JackBoundary</span><span class="o">.</span><span class="n">position</span><span class="o">.</span><span class="n">y</span> <span class="o">+</span> <span class="err">$</span><span class="n">JackBoundary</span><span class="o">.</span><span class="n">shape</span><span class="o">.</span><span class="n">get_rect</span><span class="p">(</span><span class="p">)</span><span class="o">.</span><span class="n">size</span><span class="o">.</span><span class="n">y</span><span class="o">/</span><span class="mi">2</span>
</span></span><span class="line"><span class="cl">      <span class="p">)</span>
</span></span><span class="line"><span class="cl">      
</span></span><span class="line"><span class="cl">      <span class="n">var</span> <span class="n">new_position</span> <span class="o">=</span> <span class="n">Vector2</span><span class="p">(</span><span class="n">x_offset</span> <span class="o">-</span> <span class="n">x_offset</span> <span class="o">%</span> <span class="mi">20</span><span class="p">,</span><span class="n">y_offset</span> <span class="o">-</span> <span class="n">y_offset</span> <span class="o">%</span> <span class="mi">20</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="ow">not</span> <span class="n">new_position</span> <span class="ow">in</span> <span class="n">taken</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">node</span><span class="o">.</span><span class="n">position</span> <span class="o">=</span> <span class="n">new_position</span>
</span></span><span class="line"><span class="cl">        <span class="n">taken</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">new_position</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">break</span>
</span></span></code></pre>
<p>On clicking on a jack to start connecting two jacks, a new <a href="https://github.com/Glow-Project/gwj-60/blob/master/components/wires/Cable.gd"><code>Cable</code></a> node gets added to the cables list. Those cable is basically a <code>Line2D</code> which also preserves the start and end jack such as validator.
The fiddly part was the drag-and-drop logic within the <a href="https://github.com/Glow-Project/gwj-60/blob/master/levels/wires/wires.gd#L45">mouse event handler</a>:</p>

<ul>
<li>focus tracking: each jack is tracking its focus on its own using a collision shape and <code>Area2D</code>&rsquo;s <code>mouse_entered</code> and <code>mouse_exited</code> events</li>
<li>disconnect previous cables: if the player wants to start a new cable on a jack that is already connected, the previous cables get removed</li>
<li>jack sound: after clicking on a jack a randomly chosen &ldquo;plug-in&rdquo; sound gets played<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup></li>
<li>movement: as the mouse moves while having a cable connected to a starting jack, the end position of the cable is just set to the mouse cursor ones</li>
</ul>

<h4>Validation</h4>

<p>The <a href="https://github.com/Glow-Project/gwj-60/blob/master/levels/wires/wires.gd#L120">validator</a> for the wires minigame checks if there are enough cables connected (count of jacks/2) such as if the start and end <a href="https://github.com/Glow-Project/gwj-60/blob/master/components/wires/jack.gd"><code>Jack</code></a> of every cable has the same color:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">func</span> <span class="n">validate</span><span class="p">(</span><span class="p">)</span> <span class="o">-</span><span class="o">&gt;</span> <span class="n">String</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">  <span class="n">var</span> <span class="n">children</span> <span class="o">:=</span> <span class="err">$</span><span class="n">Cables</span><span class="o">.</span><span class="n">get_children</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">children</span><span class="p">)</span> <span class="o">!=</span> <span class="err">$</span><span class="n">Jacks</span><span class="o">.</span><span class="n">get_child_count</span><span class="p">(</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="sa"></span><span class="s2">&#34;</span><span class="s2">cables not connected</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="n">cable</span> <span class="ow">in</span> <span class="n">children</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">cable</span><span class="o">.</span><span class="n">source</span><span class="o">.</span><span class="n">modulate</span> <span class="o">!=</span> <span class="n">cable</span><span class="o">.</span><span class="n">destination</span><span class="o">.</span><span class="n">modulate</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="sa"></span><span class="s2">&#34;</span><span class="s2">wrong connection</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="sa"></span><span class="s2">&#34;</span><span class="s2">&#34;</span>
</span></span></code></pre>
<h3>Logic gates <a id='gates'/></h3>

<p>Flip the input bits so the output big becomes</p>

<p><img src="godot-wild-jam-60_gates2.png"/>
<img src="godot-wild-jam-60_gates.png"/></p>

<p>The logical circuit is a graph with <a href="https://github.com/Glow-Project/gwj-60/blob/master/components/logicgates/gate.gd"><code>Gate</code></a> nodes as nodes and <a href="https://github.com/Glow-Project/gwj-60/blob/master/components/logicgates/gateconnection.gd"><code>GateConnection</code></a> as edges. Both is instantiated within the Godot scene graph while the Gates can be placed within the scene and the GateConnections are automatically drawn on run-time. The graph is built using export variables of both Gates and GateConnections. Both nodes have an <code>output</code> function basically &ldquo;pulling&rdquo; the signal recursively from sink to source<sup class="footnote-ref" id="fnref:4"><a href="#fn:4">4</a></sup>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="c1"># Gate.gd</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">func</span> <span class="n">output</span><span class="p">(</span><span class="p">)</span> <span class="o">-</span><span class="o">&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">  <span class="n">match</span> <span class="nb">type</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">GateTypeEnum</span><span class="o">.</span><span class="n">ZERO</span><span class="p">:</span> <span class="k">return</span> <span class="n">false</span>
</span></span><span class="line"><span class="cl">    <span class="n">GateTypeEnum</span><span class="o">.</span><span class="n">ONE</span><span class="p">:</span> <span class="k">return</span> <span class="n">true</span>
</span></span><span class="line"><span class="cl">    <span class="n">GateTypeEnum</span><span class="o">.</span><span class="n">AND</span><span class="p">:</span> 
</span></span><span class="line"><span class="cl">      <span class="c1"># grab both inputs before doing the check</span>
</span></span><span class="line"><span class="cl">      <span class="c1"># in order to update both paths</span>
</span></span><span class="line"><span class="cl">      <span class="n">var</span> <span class="n">a</span> <span class="o">=</span> <span class="n">input1</span><span class="o">.</span><span class="n">output</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="n">var</span> <span class="n">b</span> <span class="o">=</span> <span class="n">input2</span><span class="o">.</span><span class="n">output</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="n">a</span> <span class="ow">and</span> <span class="n">b</span>
</span></span><span class="line"><span class="cl">    <span class="n">GateTypeEnum</span><span class="o">.</span><span class="n">OR</span><span class="p">:</span> 
</span></span><span class="line"><span class="cl">      <span class="n">var</span> <span class="n">a</span> <span class="o">=</span> <span class="n">input1</span><span class="o">.</span><span class="n">output</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="n">var</span> <span class="n">b</span> <span class="o">=</span> <span class="n">input2</span><span class="o">.</span><span class="n">output</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="n">a</span> <span class="ow">or</span> <span class="n">b</span>
</span></span><span class="line"><span class="cl">    <span class="n">GateTypeEnum</span><span class="o">.</span><span class="n">NOT</span><span class="p">:</span> <span class="k">return</span> <span class="err">!</span><span class="n">input1</span><span class="o">.</span><span class="n">output</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">GateTypeEnum</span><span class="o">.</span><span class="n">OUT</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="n">var</span> <span class="n">out</span> <span class="o">=</span> <span class="n">input1</span><span class="o">.</span><span class="n">output</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="err">!</span><span class="n">out</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">out_audio_played</span> <span class="o">=</span> <span class="n">false</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="err">!</span><span class="n">out_audio_played</span> <span class="ow">and</span> <span class="n">out</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">out_audio_played</span> <span class="o">=</span> <span class="n">true</span>
</span></span><span class="line"><span class="cl">        <span class="err">$</span><span class="n">OutAudio</span><span class="o">.</span><span class="n">play</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="n">update_texture</span><span class="p">(</span><span class="n">out</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="n">out</span>
</span></span><span class="line"><span class="cl">    <span class="n">GateTypeEnum</span><span class="o">.</span><span class="n">IN</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="n">update_texture</span><span class="p">(</span><span class="n">input_value</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="n">input_value</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="n">false</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># GateConnection.gd</span>
</span></span><span class="line"><span class="cl"><span class="n">func</span> <span class="n">output</span><span class="p">(</span><span class="p">)</span> <span class="o">-</span><span class="o">&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">  <span class="n">cached_out</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">output</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="n">cached_out</span>
</span></span></code></pre>
<ul>
<li>prefetching inputs: the inputs for <code>AND</code> and <code>OR</code> need to be fetched before evaluation to avoid <a href="https://en.wikipedia.org/wiki/Short-circuit_evaluation">short-circuit evaluation</a> where the second argument doesn&rsquo;t get evaluated if the first doesn&rsquo;t satisfy the expression.</li>
<li>signal caching: the GateConnection caches the output value, so its <code>process</code> can use it for coloring the cable</li>
<li>recursive updates: the output <a href="https://github.com/Glow-Project/gwj-60/blob/master/components/logicgates/gate.gd"><code>Gate</code></a> calls <code>output</code> periodically within its <code>process</code> to update all Gates and GateConnections</li>
</ul>

<h4>Validation</h4>

<p>It just needs to be checked if the output gate is set to 1.</p>

<h3>Optics<a id='optics'/></h3>

<p>Reflect the laser beam with the mirrors so the output block gets lit.</p>

<p><img src="godot-wild-jam-60_optics.png"/></p>

<p>The mirrors are essentially rotatable collision shapes. The path of the laser beam is continuously recalculated within the <a href="https://github.com/Glow-Project/gwj-60/blob/master/levels/optics/optics.gd#L14">minigame&rsquo;s <code>process</code></a> using a <a href="https://docs.godotengine.org/en/stable/classes/class_raycast2d.html"><code>RayCast2D</code></a>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">func</span> <span class="n">_process</span><span class="p">(</span><span class="n">delta</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># clear the laser beam</span>
</span></span><span class="line"><span class="cl">  <span class="err">$</span><span class="n">LaserBeam</span><span class="o">.</span><span class="n">clear_points</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># let the lazer beam start at the position of the emitter</span>
</span></span><span class="line"><span class="cl">  <span class="err">$</span><span class="n">LaserBeam</span><span class="o">.</span><span class="n">add_point</span><span class="p">(</span><span class="err">$</span><span class="n">Emitter</span><span class="o">.</span><span class="n">global_position</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="c1"># position the ray cast initially to the emitters position</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># pointing to the right towards the first mirror</span>
</span></span><span class="line"><span class="cl">  <span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">global_position</span> <span class="o">=</span> <span class="err">$</span><span class="n">Emitter</span><span class="o">.</span><span class="n">global_position</span>
</span></span><span class="line"><span class="cl">  <span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">target_position</span> <span class="o">=</span> <span class="n">Vector2</span><span class="p">(</span><span class="mi">300</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="n">var</span> <span class="n">reflect_target</span><span class="p">:</span> <span class="n">Vector2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># loop as long as the raycast hits a mirror</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># and break if it collides with the output block or with nothing at all</span>
</span></span><span class="line"><span class="cl">  <span class="k">while</span> <span class="n">true</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">    <span class="c1"># force the ray cast to walk from the global position towards the target</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># finding the first collision (or none if there is nothing to collide with)</span>
</span></span><span class="line"><span class="cl">    <span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">force_raycast_update</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># if ray cast points beyond the minigame window bounds, no collission will happen</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="err">!</span><span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">is_colliding</span><span class="p">(</span><span class="p">)</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="err">$</span><span class="n">LightSink</span><span class="o">.</span><span class="n">unhighlight</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="err">$</span><span class="n">LaserBeam</span><span class="o">.</span><span class="n">add_point</span><span class="p">(</span><span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">global_position</span> <span class="o">+</span> <span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">target_position</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="k">break</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># we know that we&#39;ve collided with something, so add the point to the</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># laser beam</span>
</span></span><span class="line"><span class="cl">    <span class="err">$</span><span class="n">LaserBeam</span><span class="o">.</span><span class="n">add_point</span><span class="p">(</span><span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">get_collision_point</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">get_collider</span><span class="p">(</span><span class="p">)</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="sa"></span><span class="s2">&#34;</span><span class="s2">WallArea</span><span class="s2">&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="k">break</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">    <span class="c1"># the output block has been reached!</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">get_collider</span><span class="p">(</span><span class="p">)</span> <span class="o">==</span> <span class="err">$</span><span class="n">LightSink</span><span class="o">/</span><span class="n">Area2D</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="err">$</span><span class="n">LightSink</span><span class="o">.</span><span class="n">highlight</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="k">break</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># let the laser beam bounce of the mirror inspired by</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># https://github.com/Remysaurus/GodotReflectingLaser3D/blob/main/addons/laserGit/laser.gd#L75</span>
</span></span><span class="line"><span class="cl">    <span class="n">reflect_target</span> <span class="o">=</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">get_collision_point</span><span class="p">(</span><span class="p">)</span> <span class="o">-</span> <span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">global_position</span>
</span></span><span class="line"><span class="cl">      <span class="p">)</span><span class="o">.</span><span class="n">bounce</span><span class="p">(</span><span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">get_collision_normal</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># place the ray cast to collission point so the next iteration can find the next collision</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># add a small offset towards the target, otherwise the raycast will immediately collide</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># with the previous mirror</span>
</span></span><span class="line"><span class="cl">    <span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">global_position</span> <span class="o">=</span> <span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">get_collision_point</span><span class="p">(</span><span class="p">)</span> <span class="o">+</span> <span class="n">reflect_target</span><span class="o">.</span><span class="n">normalized</span><span class="p">(</span><span class="p">)</span><span class="o">*</span><span class="mi">2</span>
</span></span><span class="line"><span class="cl">    <span class="err">$</span><span class="n">RayCast</span><span class="o">.</span><span class="n">target_position</span> <span class="o">=</span> <span class="n">reflect_target</span><span class="o">.</span><span class="n">normalized</span><span class="p">(</span><span class="p">)</span><span class="o">*</span><span class="mi">300</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="err">$</span><span class="n">LaserSoundPlayer</span><span class="o">.</span><span class="n">pitch_scale</span> <span class="o">=</span> <span class="n">log</span><span class="p">(</span><span class="err">$</span><span class="n">LaserBeam</span><span class="o">.</span><span class="n">points</span><span class="o">.</span><span class="n">size</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="o">*</span><span class="mi">2</span>
</span></span></code></pre>
<p>Additionally the last line increases the pitch of the &ldquo;laser sound&rdquo; for each mirror which got hit by the laser.</p>

<h4>Validation</h4>

<p>The validate just need to look if the output block (aka light sink) is lit:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">func</span> <span class="n">validate</span><span class="p">(</span><span class="p">)</span> <span class="o">-</span><span class="o">&gt;</span> <span class="n">String</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="sa"></span><span class="s2">&#34;</span><span class="s2">&#34;</span> <span class="k">if</span> <span class="err">$</span><span class="n">LightSink</span><span class="o">.</span><span class="n">highlighted</span> <span class="k">else</span> <span class="sa"></span><span class="s2">&#34;</span><span class="s2">target did not receive laser beam</span><span class="s2">&#34;</span>
</span></span></code></pre>
<h3>Brain<a id='brain'/></h3>

<p>Dial the knobs so that the robot redraws the house. The brain aka visual cortex memes an image-detection program that tries to redraw the seen image as accurate as possible.</p>

<p><img src="godot-wild-jam-60_brain2.gif"/>
<img src="godot-wild-jam-60_brain.png"/></p>

<p>The house is manually drawn within godot using a <code>Line2D</code>, called <code>GoalLine</code>. The <code>RobotLine</code> consists of all points from <code>GoalLine</code> but transformed using values from the dial:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">update_robot_line</span><span class="p">(</span><span class="p">)</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">  <span class="err">$</span><span class="n">RobotLine</span><span class="o">.</span><span class="n">clear_points</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="n">var</span> <span class="n">index</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="n">point</span> <span class="ow">in</span> <span class="err">$</span><span class="n">GoalLine</span><span class="o">.</span><span class="n">points</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">point</span> <span class="o">=</span> <span class="n">point</span> <span class="k">as</span> <span class="n">Vector2</span>
</span></span><span class="line"><span class="cl">    <span class="n">var</span> <span class="n">robotPoint</span> <span class="o">=</span> <span class="n">point</span><span class="o">.</span><span class="n">rotated</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="nb">float</span><span class="p">(</span> <span class="err">$</span><span class="n">KnobA</span><span class="o">.</span><span class="n">value</span><span class="p">(</span><span class="p">)</span><span class="p">)</span> <span class="o">/</span> <span class="mi">50</span>
</span></span><span class="line"><span class="cl">      <span class="p">)</span> <span class="o">*</span> <span class="mf">0.5</span> <span class="o">*</span> <span class="nb">float</span><span class="p">(</span><span class="err">$</span><span class="n">KnobB</span><span class="o">.</span><span class="n">value</span><span class="p">(</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">index</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="n">robotPoint</span> <span class="o">+</span><span class="o">=</span> <span class="n">Vector2</span><span class="p">(</span><span class="err">$</span><span class="n">KnobC</span><span class="o">.</span><span class="n">value</span><span class="p">(</span><span class="p">)</span> <span class="o">+</span> <span class="mf">0.3</span><span class="p">,</span> <span class="err">$</span><span class="n">KnobC</span><span class="o">.</span><span class="n">value</span><span class="p">(</span><span class="p">)</span> <span class="o">+</span> <span class="mf">0.2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="n">robotPoint</span> <span class="o">-</span><span class="o">=</span> <span class="n">Vector2</span><span class="p">(</span><span class="err">$</span><span class="n">KnobC</span><span class="o">.</span><span class="n">value</span><span class="p">(</span><span class="p">)</span> <span class="o">-</span> <span class="mf">0.3</span><span class="p">,</span> <span class="err">$</span><span class="n">KnobC</span><span class="o">.</span><span class="n">value</span><span class="p">(</span><span class="p">)</span> <span class="o">-</span> <span class="mf">0.2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="err">$</span><span class="n">RobotLine</span><span class="o">.</span><span class="n">add_point</span><span class="p">(</span><span class="n">robotPoint</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">index</span> <span class="o">+</span><span class="o">=</span> <span class="mi">1</span>
</span></span></code></pre>
<p>While the transformations of translating, scaling and rotating was intended, we needed to guess the coefficients to keep the transformation mostly within the viewport.
Within the <a href="https://github.com/Glow-Project/gwj-60/blob/master/levels/brain/brain.gd#L27">minigames <code>process</code></a>, the <code>RobotLine</code> gets transformed to the <code>ShowLine</code> which is the red &ldquo;cathode ray tube&rdquo;-alike Line2D that is actually shown to the player:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">func</span> <span class="n">_process</span><span class="p">(</span><span class="n">delta</span><span class="p">)</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="n">last_update</span> <span class="o">+</span> <span class="n">delta</span> <span class="o">&lt;</span> <span class="mf">0.1</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">last_update</span> <span class="o">+</span><span class="o">=</span> <span class="n">delta</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="n">last_update</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="n">point_index</span> <span class="o">&gt;</span><span class="o">=</span> <span class="err">$</span><span class="n">RobotLine</span><span class="o">.</span><span class="n">points</span><span class="o">.</span><span class="n">size</span><span class="p">(</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">point_index</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="err">$</span><span class="n">RobotLine</span><span class="o">.</span><span class="n">get_point_count</span><span class="p">(</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="err">$</span><span class="n">ShowLine</span><span class="o">.</span><span class="n">add_point</span><span class="p">(</span><span class="err">$</span><span class="n">RobotLine</span><span class="o">.</span><span class="n">get_point_position</span><span class="p">(</span><span class="n">point_index</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="err">$</span><span class="n">ShowLine</span><span class="o">.</span><span class="n">add_point</span><span class="p">(</span><span class="err">$</span><span class="n">RobotLine</span><span class="o">.</span><span class="n">get_point_position</span><span class="p">(</span><span class="n">point_index</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="err">$</span><span class="n">ShowLine</span><span class="o">.</span><span class="n">points</span><span class="o">.</span><span class="n">size</span><span class="p">(</span><span class="p">)</span><span class="o">-</span><span class="mi">5</span><span class="p">)</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="err">$</span><span class="n">ShowLine</span><span class="o">.</span><span class="n">remove_point</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="n">point_index</span> <span class="o">+</span><span class="o">=</span> <span class="mi">1</span>
</span></span></code></pre>
<ul>
<li>speed control: to avoid stroboscopic effects and keep a constant speed the process is only executed every 100ms by tracking the last update</li>
<li>show only three points: this could&rsquo;ve been implemented easier but a globally tracked <code>point_index</code> is used to add only three points starting from the the index. The index gets incremented so the next iteration will proceed within the Line2D.</li>
</ul>

<h4>Validation</h4>

<p>This is the trickiest validation, as it is hard to exactly match the given line as dialing the knobs is a bit difficult. In order to keep the player&rsquo;s frustration rate low, the transformed points should match within a given error.</p>

<p>Since the order of the original and the transformed points is preserved, we know that ideally both lines should exactly match. To ease the process, we <a href="https://github.com/Glow-Project/gwj-60/blob/master/levels/brain/brain.gd#L77">calculate a pair-wise distance</a> and check if it is lower than a predefined tolerance:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">func</span> <span class="n">validate</span><span class="p">(</span><span class="p">)</span> <span class="o">-</span><span class="o">&gt;</span> <span class="n">String</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">  <span class="n">const</span> <span class="n">TOLERANCE</span> <span class="o">=</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl">  <span class="n">var</span> <span class="n">player</span><span class="p">:</span> <span class="n">Line2D</span> <span class="o">=</span> <span class="err">$</span><span class="n">RobotLine</span>
</span></span><span class="line"><span class="cl">  <span class="n">var</span> <span class="n">goal</span><span class="p">:</span> <span class="n">Line2D</span> <span class="o">=</span> <span class="err">$</span><span class="n">GoalLine</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">player</span><span class="o">.</span><span class="n">get_point_count</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">var</span> <span class="n">p_pos</span> <span class="o">:=</span> <span class="n">player</span><span class="o">.</span><span class="n">get_point_position</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">var</span> <span class="n">g_pos</span> <span class="o">:=</span> <span class="n">goal</span><span class="o">.</span><span class="n">get_point_position</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">p_pos</span><span class="o">.</span><span class="n">distance_to</span><span class="p">(</span><span class="n">g_pos</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">TOLERANCE</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="sa"></span><span class="s2">&#34;</span><span class="s2">image not aligned</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="sa"></span><span class="s2">&#34;</span><span class="s2">&#34;</span>
</span></span></code></pre>
<h2>Summary<a id='summary'/></h2>

<p>It was great fun doing different minigames within one week. They had all different challenges which solutions I now can add to my Godot skills:</p>

<ul>
<li>wires: drag and drop</li>
<li>logic gates: implementing graphs and recursive evaluation</li>
<li>optics: ray casting</li>
<li>brain: connecting dials with a transformation matrix and animate a &ldquo;slow cathode ray tube&rdquo;</li>
</ul>

<p>The logic gates could be more simple by moving the connection into the gate. The Gates could just track where they get their input/s from and draw the connection <code>Line2D</code> by themselves.</p>

<p>Developing the optics minigame was most enjoyable since could finally get my hands dirty with ray tracing and also got the most positive feedback from friends and <a href="https://itch.io/jam/godot-wild-jam-60/rate/2225903">itch.io</a>.</p>

<p>Finally it was a pleasure to make all the textures and music by our own together with Johannes. I&rsquo;m looking forward for upcoming Pour Entertainment ssubmissions!</p>

<p>At the very end I&rsquo;ll give you some insight about our manual review issue tracking:</p>

<p><img src="godot-wild-jam-60_manual_issue_tracking.png"/></p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1"><a href="https://github.com/Tch1b0">Johannes</a> and I</li>

<li id="fn:2">Well, they also have a non-deterministic while loop preventing overlapping jacks.</li>

<li id="fn:3">I recorded them while pluging some eurorack cables in and out.</li>

<li id="fn:4">While writing this it remembers me a little bit of ray tracing.</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Thu, 24 Aug 2023 15:26:01 +0200</pubDate>
    </item>
    <item>
      <title>linux file observability</title>
      <link>https://evilcookie.de/linux-file-observability.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>linux file observability</h1>

<p><img src="linux-file-observability_observability.png"/></p>

<p>In linux,&ldquo;everything&rdquo; is a file<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>. Regardless if its a regular file, directory, socket or even a device.
Know how to observe open files, attached to a process, can become quite handy for debugging a linux host.</p>

<ul>
<li><a href="#files-and-file-descriptors">Files and file descriptors</a></li>
<li><a href="#observe">Observe</a>

<ul>
<li><a href="#which-process">Wich process opened the file?</a></li>
<li><a href="#which-files">Which files do a process holding?</a><sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup></li>
<li><a href="#incoming-connections">Is my server already listening for incoming connections?</a></li>
<li><a href="#deleted-files">Does my process still hold fds to deleted files?</a></li>
</ul></li>
</ul>

<p>The first theoretical part will introduce file descriptors while the second part will give some practical examples.</p>

<h2>Files and file descriptors<a id="files-and-file-descriptors"/></h2>

<p>Whenever a program opens a file via a syscall from the <a href="https://man7.org/linux/man-pages/man2/open.2.html">open()</a> family,
the kernel returns a reference number that is unique for that process. This number is bettern known as file descriptor or fd for short. The program can act on that file (read, write, close,&hellip;) by using the fd from the open call.</p>

<p>Imagine a program like this:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="c1">// gcc example.c -o example
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;fcntl.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">arc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[</span><span class="p">]</span><span class="p">)</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">open</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">example.c</span><span class="s">&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="p">{</span><span class="n">sleep</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span><span class="p">;</span><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>This program will open a file (itself for simplicity) and goes into an infinite loop in order to stay alive for observability.</p>

<p>On <code>open</code> the system creates a procfs entry under <code>/proc/&lt;pid&gt;/fds/&lt;fd&gt;</code> . Listing the proc dir for our process<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup> looks something like this:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ ls -la /proc/1234/fd
</span></span><span class="line"><span class="cl">total <span class="m">0</span>
</span></span><span class="line"><span class="cl">dr-x------ <span class="m">2</span> raphael raphael  <span class="m">0</span> Jun <span class="m">29</span> 21:11 .
</span></span><span class="line"><span class="cl">dr-xr-xr-x <span class="m">9</span> raphael raphael  <span class="m">0</span> Jun <span class="m">29</span> 21:11 ..
</span></span><span class="line"><span class="cl">lrwx------ <span class="m">1</span> raphael raphael <span class="m">64</span> Jun <span class="m">29</span> 21:11 <span class="m">0</span> -&gt; /dev/pts/0
</span></span><span class="line"><span class="cl">lrwx------ <span class="m">1</span> raphael raphael <span class="m">64</span> Jun <span class="m">29</span> 21:11 <span class="m">1</span> -&gt; /dev/pts/0
</span></span><span class="line"><span class="cl">lrwx------ <span class="m">1</span> raphael raphael <span class="m">64</span> Jun <span class="m">29</span> 21:11 <span class="m">2</span> -&gt; /dev/pts/0
</span></span><span class="line"><span class="cl">lr-x------ <span class="m">1</span> raphael raphael <span class="m">64</span> Jun <span class="m">29</span> 21:11 <span class="m">3</span> -&gt; /tmp/example.c
</span></span></code></pre>
<h2>Observe</h2>

<h3>Wich process opened the file?<a id='which-process'/></h3>

<p><a href="https://linux.die.net/man/8/lsof"><code>lsof</code></a> got you covered:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ lsof /tmp/example
</span></span><span class="line"><span class="cl">COMMAND PID  USER  FD   TYPE DEVICE SIZE/OFF     NODE NAME
</span></span><span class="line"><span class="cl">example 444 raphael txt    REG   0,40    23656 26759037 /tmp/example
</span></span></code></pre>
<h3>Which files do a process holding?<a id='which-files'/></h3>

<p>It&rsquo;s <code>lsof</code> again. The opened <code>example.c</code> can be seen at last with fd 3 linking to the original file. The other three fd&rsquo;s 0 , 1  and 2  are the three <a href="https://man7.org/linux/man-pages/man4/pts.4.html">pts</a> devices for stdin, stdout stderr that get automatically created by the OS for any new process.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ lsof -p <span class="m">444</span>
</span></span><span class="line"><span class="cl">COMMAND PID    USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
</span></span><span class="line"><span class="cl">example <span class="m">444</span> raphael  cwd    DIR   8,32     <span class="m">4096</span> <span class="m">267422</span> /tmp/
</span></span><span class="line"><span class="cl">example <span class="m">444</span> raphael  rtd    DIR   8,32     <span class="m">4096</span>      <span class="m">2</span> /
</span></span><span class="line"><span class="cl">example <span class="m">444</span> raphael  txt    REG   8,32    <span class="m">16088</span>  <span class="m">46778</span> /tmp/example
</span></span><span class="line"><span class="cl">example <span class="m">444</span> raphael  mem    REG   8,32  <span class="m">2029592</span> <span class="m">142704</span> /usr/lib/...
</span></span><span class="line"><span class="cl">example <span class="m">444</span> raphael  mem    REG   8,32   <span class="m">191504</span> <span class="m">142576</span> /usr/lib/...
</span></span><span class="line"><span class="cl">example <span class="m">444</span> raphael    0u   CHR  136,0      0t0      <span class="m">3</span> /dev/pts/0
</span></span><span class="line"><span class="cl">example <span class="m">444</span> raphael    1u   CHR  136,0      0t0      <span class="m">3</span> /dev/pts/0
</span></span><span class="line"><span class="cl">example <span class="m">444</span> raphael    2u   CHR  136,0      0t0      <span class="m">3</span> /dev/pts/0
</span></span><span class="line"><span class="cl">example <span class="m">444</span> raphael    3r   REG   8,32      <span class="m">196</span>  <span class="m">46772</span> /tmp/example.c
</span></span></code></pre>
<h3>Is my server already listening for incoming connections?<a id='incoming-connections'/></h3>

<p>Let&rsquo;s spin up a tcp server waiting for incoming connections using <a href="https://www.man7.org/linux/man-pages/man1/ncat.1.html"><code>ncat</code></a>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ ncat -l <span class="m">8080</span>
</span></span></code></pre>
<p>Using <code>lsof</code> again, we can observe that <code>ncat</code> is even doing dual-stack waiting for incoming ipv4 and ipv6 connections, as one can see in the forelast entries.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ lsof -p <span class="m">532581</span>
</span></span><span class="line"><span class="cl">COMMAND    PID  USER   FD   TYPE             DEVICE SIZE/OFF     NODE NAME
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael  cwd    DIR               0,40      <span class="m">450</span> <span class="m">27369190</span> /tmp/example
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael  rtd    DIR               0,38      <span class="m">206</span>      <span class="m">256</span> /
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael  txt    REG               0,38   <span class="m">435520</span>  <span class="m">9123417</span> /usr/bin/ncat
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael  mem    REG               0,36           <span class="m">9123417</span> /usr/bin/ncat <span class="o">(</span>path <span class="nv">dev</span><span class="o">=</span>0,38<span class="o">)</span>
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael  mem    REG               0,36           <span class="m">9000771</span> /usr/lib64/...
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael    0u   CHR              136,1      0t0        <span class="m">4</span> /dev/pts/1
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael    1u   CHR              136,1      0t0        <span class="m">4</span> /dev/pts/1
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael    2u   CHR              136,1      0t0        <span class="m">4</span> /dev/pts/1
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael    3u  IPv6            <span class="m">9561146</span>      0t0      TCP *:webcache <span class="o">(</span>LISTEN<span class="o">)</span>
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael    4u  IPv4            <span class="m">9561147</span>      0t0      TCP *:webcache <span class="o">(</span>LISTEN<span class="o">)</span>
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael    6u  unix 0x0000000014cd383f      0t0    <span class="m">31426</span> <span class="nv">type</span><span class="o">=</span>STREAM <span class="o">(</span>CONNECTED<span class="o">)</span>
</span></span></code></pre>
<p>Let&rsquo;s go one step further and establish a connection to <code>ncat</code> by browsing to <code>localhost:8080</code>. We can see that <code>ncat</code>
closed the unused listener and from which address+port the connection is coming from:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ lsof -p <span class="m">532581</span>
</span></span><span class="line"><span class="cl">COMMAND    PID  USER   FD   TYPE             DEVICE SIZE/OFF     NODE NAME
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael  cwd    DIR               0,40      <span class="m">450</span> <span class="m">27369190</span> /tmp/example
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael  rtd    DIR               0,38      <span class="m">206</span>      <span class="m">256</span> /
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael  txt    REG               0,38   <span class="m">435520</span>  <span class="m">9123417</span> /usr/bin/ncat
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael  mem    REG               0,36           <span class="m">9123417</span> /usr/bin/ncat <span class="o">(</span>path <span class="nv">dev</span><span class="o">=</span>0,38<span class="o">)</span>
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael  mem    REG               0,36           <span class="m">9000771</span> /usr/lib64/...
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael    0u   CHR              136,1      0t0        <span class="m">4</span> /dev/pts/1
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael    1u   CHR              136,1      0t0        <span class="m">4</span> /dev/pts/1
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael    2u   CHR              136,1      0t0        <span class="m">4</span> /dev/pts/1
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael    5u  IPv4            <span class="m">9557641</span>      0t0      TCP localhost:webcache-&gt;localhost:32886 <span class="o">(</span>ESTABLISHED<span class="o">)</span>
</span></span><span class="line"><span class="cl">ncat    <span class="m">532581</span> raphael    6u  unix 0x0000000014cd383f      0t0    <span class="m">31426</span> <span class="nv">type</span><span class="o">=</span>STREAM <span class="o">(</span>CONNECTED<span class="o">)</span>
</span></span></code></pre>
<h3>Does my process still hold fds to deleted files?<a id="deleted-files"/></h3>

<p>Let&rsquo;s create a file and immediately <a href="https://www.man7.org/linux/man-pages/man2/unlink.2.html"><code>unlink</code></a> it but keep it open:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="c1">// gcc ulink.c -o ulink
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;fcntl.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span> <span class="n">argv</span><span class="p">[</span><span class="p">]</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">open</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">test.log</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">O_CREAT</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">unlink</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">test.log</span><span class="s">&#34;</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="p">{</span><span class="n">sleep</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span><span class="p">;</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>The file is not existent, but can be observed via <code>lsof</code>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ lsof -p <span class="m">635</span>
</span></span><span class="line"><span class="cl">COMMAND PID    USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
</span></span><span class="line"><span class="cl">ulink   <span class="m">635</span> raphael  cwd    DIR   8,32     <span class="m">4096</span> <span class="m">267422</span> /tmp/example
</span></span><span class="line"><span class="cl">ulink   <span class="m">635</span> raphael  rtd    DIR   8,32     <span class="m">4096</span>      <span class="m">2</span> /
</span></span><span class="line"><span class="cl">ulink   <span class="m">635</span> raphael  txt    REG   8,32    <span class="m">16168</span>  <span class="m">50490</span> /tmp/example
</span></span><span class="line"><span class="cl">ulink   <span class="m">635</span> raphael  mem    REG   8,32  <span class="m">2029592</span> <span class="m">142704</span> /usr/lib/...
</span></span><span class="line"><span class="cl">ulink   <span class="m">635</span> raphael    0u   CHR  136,0      0t0      <span class="m">3</span> /dev/pts/0
</span></span><span class="line"><span class="cl">ulink   <span class="m">635</span> raphael    1u   CHR  136,0      0t0      <span class="m">3</span> /dev/pts/0
</span></span><span class="line"><span class="cl">ulink   <span class="m">635</span> raphael    2u   CHR  136,0      0t0      <span class="m">3</span> /dev/pts/0
</span></span><span class="line"><span class="cl">ulink   <span class="m">635</span> raphael    3r   REG   8,32        <span class="m">0</span>  <span class="m">40397</span> /tmp/test.log <span class="o">(</span>deleted<span class="o">)</span>
</span></span></code></pre>
<div class="footnotes">

<hr>

<ol>
<li id="fn:1">Rabbit hole warning! <a href="https://web.archive.org/web/20150110114929/http://ph7spot.com:80/musings/in-unix-everything-is-a-file">source based on wikipedia</a></li>

<li id="fn:2">Yes, I am looking at you <a href="https://stackoverflow.com/questions/8684609/where-can-i-find-php-ini">PHP</a>!</li>

<li id="fn:3">use &ldquo;prgrep -f example&rdquo; to get the pid</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Wed, 19 Jul 2023 12:30:00 +0200</pubDate>
    </item>
    <item>
      <title>blog update: customization</title>
      <link>https://evilcookie.de/blog-update-customization.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>blog update: customization</h1>

<p><img src="blog-update-customization_berlin.jpg"/></p>

<p>Make your own customized blog using blogctl!</p>

<p>With <a href="https://github.com/RaphaelPour/blogctl/releases/tag/v1.0.0">blogctl v1.0.0</a>, all personal hard coded information are now configurable.
They can be specified using the introduced <code>blog.json</code> in the root of the blog directory:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;version&#34;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;author&#34;</span><span class="p">:</span> <span class="s2">&#34;Raphael Pour&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;title&#34;</span><span class="p">:</span> <span class="s2">&#34;blog&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;domain&#34;</span><span class="p">:</span><span class="s2">&#34;evilcookie.de&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;Hi, I&#39;m Raphael. I write about my software developer journey...&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;footer&#34;</span><span class="p">:</span> <span class="s2">&#34;&lt;a href=&#39;rss.xml&#39;&gt;RSS&lt;/a&gt;|&lt;a href=&#39;impressum.html&#39;&gt;Impressum&lt;/a&gt;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<h2>text/template vs. html/template</h2>

<p>The index template gets now rendered using the <a href="https://pkg.go.dev/text/template">text/template</a> lib rather than <a href="https://pkg.go.dev/html/template">html/template</a> while the later escapes all
data parameters due to its <a href="https://pkg.go.dev/html/template#hdr-Security_Model">security model</a>. Escaping e.g. the RSS or impressum link would result in unusable ones.</p>

<p><code>text/html</code> doesn&rsquo;t care while template and arguments are trusted by default.</p>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Wed, 12 Jul 2023 12:32:54 +0200</pubDate>
    </item>
    <item>
      <title>manpage fulltext search</title>
      <link>https://evilcookie.de/manpage-fulltext-search.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>manpage fulltext search</h1>

<p><code>man -K &lt;term&gt;</code> got you covered<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"> -K, --global-apropos
</span></span><span class="line"><span class="cl">        Search for text in all manual pages.  This is a brute-
</span></span><span class="line"><span class="cl">        force search, and is likely to take some time; if you can,
</span></span><span class="line"><span class="cl">        you should specify a section to reduce the number of pages
</span></span><span class="line"><span class="cl">        that need to be searched.  Search terms may be simple
</span></span><span class="line"><span class="cl">        strings (the default), or regular expressions if the
</span></span><span class="line"><span class="cl">        --regex option is used.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        Note that this searches the sources of the manual pages,
</span></span><span class="line"><span class="cl">        not the rendered text, and so may include false positives
</span></span><span class="line"><span class="cl">        due to things like comments in source files.  Searching
</span></span><span class="line"><span class="cl">        the rendered text would be much slower.
</span></span></code></pre>
<p>some useful additions:</p>

<ul>
<li><code>--regex</code>: search via regular expression</li>
<li><code>-P less</code>: use always a pager, otherwise short manpages will get printed without pager making it difficult to search within the page</li>
<li><code>--html=firefox</code>: show pages in the browser</li>
</ul>

<p>some interesting searches via <code>man -P less -K &lt;term&gt;</code>:</p>

<ul>
<li><code>knuth</code>, <code>torvalds</code>, <code>ritchie</code>: take some history lessons</li>
<li><code>&lt;swear&gt;</code>: look for your favorite swear</li>
<li><code>1337</code>: reveal the elite</li>
<li><code>coffee</code>: shows that one shouldn&rsquo;t use <a href="https://linux.die.net/man/1/espdiff"><code>espdiff</code></a> <em>&ldquo;while sleep-walking, or before your first cup of coffee&rdquo;</em></li>
<li><code>love</code>: who spreads the most love</li>
</ul>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">as I ran into the problem that I needed a fulltext serarch over man pages, my first thought was to set up an opensearch cluster feeding it with <code>man -a</code>&hellip;</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Fri, 07 Jul 2023 12:58:07 +0200</pubDate>
    </item>
    <item>
      <title>let&#39;s boot</title>
      <link>https://evilcookie.de/lets-boot.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>let&rsquo;s boot</h1>

<p>Let&rsquo;s boot some x86 code with qemu.</p>

<p>I rediscovered <a href="https://.osdev.org">osdev.org</a> after 13 years of abstinence<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup><sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> and started off with the plain-assembly <a href="https://wiki.osdev.org/Babystep1">babystep</a>. Then I tried the C based <a href="https://wiki.osdev.org/Bare_Bones">bare-bones</a> kernel to have a bit more convenience.</p>

<ul>
<li><a href="#minimal">Minimal working example</a></li>
<li><a href="#babystep">Babystep - plain assembler</a></li>
<li><a href="#barebones">Bare-Bones - C</a></li>
<li><a href="#findings">Findings</a>

<ul>
<li><a href="environment">Environment</a></li>
<li><a href="memory-layout"> Memory Layout</a></li>
</ul></li>
<li><a href="resources">Resources</a></li>
<li><a href="vision">Vision</a></li>
</ul>

<h2>Minimal working example<a id="minimal"/></h2>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="err">[</span><span class="nf">ORG</span> <span class="mi">0x7c00</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nl">hang:</span>
</span></span><span class="line"><span class="cl">    <span class="nf">jmp</span> <span class="no">hang</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">times</span> <span class="mi">510</span><span class="p">-(</span><span class="no">$-$$</span><span class="p">)</span> <span class="no">db</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="nf">db</span> <span class="mi">0x55</span>
</span></span><span class="line"><span class="cl"><span class="nf">db</span> <span class="mi">0xAA</span>
</span></span></code></pre>
<p>This <a href="https://nasm.us/">nasm</a> code is all you need to make an infinite blinking cursor:</p>

<p><img src="lets-boot_minimal_valid.gif"/></p>

<p>What is going on?</p>

<ul>
<li><code>[ORG 0x7c00]</code>: select the right sector, where <a href="https://github.com/qemu/seabios/blob/master/src/boot.c#L881">the bios expects the bootloader</a></li>
<li><code>hang: jmp hang</code>: plain assembly instructing the CPU to infinitely loop by jumping to the jump instruction</li>
<li><code>times 510-($-$$) db 0</code>: Bootloader needs to be exactly 512 bytes large in size. This pads the bootloader up with zeroes.

<ul>
<li>pad 510 bytes instead of 512 to leave two bytes free for the magic number</li>
<li><code>$-$$</code> is a macro calculating <code>&lt;end of file&gt; - &lt;start of file&gt;</code> resulting in the size of the bootloader so far</li>
<li><code>db 0</code> is just a static byte set to zero</li>
</ul></li>
<li><code>0x55aa</code> is the magic number to <a href="https://github.com/qemu/seabios/blob/master/src/boot.c#L901">tell the bios that this is a valid bootloader</a></li>
</ul>

<h2>Babystep - plain assembler<a id="babystep"/></h2>

<p>After the minimal working example, I approached the plain-assembler <a href="https://github.com/RaphaelPour/letsboot/tree/main/tutorials/babystep">babystep bootloader</a>, to get a better insight what&rsquo;s going on.</p>

<p>Learnings:
  - basic memory alignment
  - enter protected mode: <a href="">code</a> <a href="">tutorial</a>
  - write to console without interrupt: <a href="https://github.com/RaphaelPour/letsboot/blob/main/tutorials/babystep/boot3.asm#L86">code</a> <a href="">tutorial</a></p>

<h2>Bare-Bones - C<a id="barebones"/></h2>

<p>It might be asked much operating at such a low level, but some convenience would be nice. C got you covered! At least a bit. The <a href="https://github.com/RaphaelPour/letsboot/tree/main/tutorials/bare-bones">bare-bones bootloader</a> contains has only as much assembler as necessary to load up C. Basically a stack must be allocated and <a href="https://github.com/RaphaelPour/letsboot/blob/main/tutorials/bare-bones/kernel.c">here we go</a>.</p>

<p>Learnings:
  - bridge between assembler and C
  - more sophisticated tty</p>

<h2>Findings<a id="findings"/></h2>

<h3>Environment<a id="environment"/></h3>

<p>Bootloaders aren&rsquo;t just usual<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup> assembler codes in a hosted environment where an OS is providing all kinds of neat stuff like a libc.
There is no such thing as <a href="https://www.man7.org/linux/man-pages/man5/elf.5.html">ELF</a> or <a href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format">PE</a>, just the bare-metal CPU which we must satisfy. This not only includes valid assembler code but stuff like:</p>

<ul>
<li>width: 8, 16 or 32 bit instruction width?</li>
<li>location: where needs the code to be placed to in order to get (not) executed. The cpu originally doesn&rsquo;t care whats data and code, it just jumps to a defined
address and interprets the corresponding bytes as instruction.</li>
</ul>

<h3>Memory Layout<a id="memory-layout"/></h3>

<p>In my understanding the assembler file not just contains code and needs to be aligned but is also almost the equivalent of the program that is actual in memory.
And because of this, some preprocessor stuff like <code>times 510-($-$$) db 0</code> has to be made at the end in order it is correctly loaded into the memory.</p>

<p>While researching online about x86 bootloader, two approaches emerged:</p>

<ul>
<li>manual alignment of the sections via labels, jumps</li>
<li>linker config with map which section goes where</li>
</ul>

<p>It looks like the later approach is mostly used for serious projects, where the former is just a quick n dirty workaround.</p>

<h2>Resources<a id="resources"/></h2>

<p>Additionally to <a href="https://wiki.osdev.org">osdev.org</a>, I also found a bunch of other interesting resources along the way.</p>

<p>General:</p>

<ul>
<li><a href="https://wiki.osdev.org/CPU_Registers_x86">Overview about the cpu registers</a></li>
<li><a href="https://en.wikipedia.org/wiki/BIOS_interrupt_call#Interrupt_table">BIOS interrupt table</a></li>
<li><a href="https://en.wikipedia.org/wiki/X86_instruction_listings">x86 instruction set</a></li>
<li><a href="https://www.felixcloutier.com/x86/index.html">Instructions</a></li>
</ul>

<p>Tutorials:</p>

<ul>
<li><a href="https://wiki.osdev.org/Babystep1">Babystep tutorial with pure assembler</a></li>
<li><a href="https://github.com/tanmayv25/x86-bootloader/tree/master">Example bootloader into c</a></li>
<li><a href="http://3zanders.co.uk/2017/10/13/writing-a-bootloader/">Bootloader tutorial</a></li>
<li><a href="https://cs.lmu.edu/~ray/notes/nasmtutorial/">NASM Tutorial</a></li>
<li><a href="https://blog.stefan-koch.name/2013/11/09/der-hello-world-bootloader">German tutorial</a></li>
</ul>

<p>Special:</p>

<ul>
<li><a href="https://0xax.gitbooks.io/linux-insides/content/">Linux inside handbook</a></li>
<li><a href="https://elixir.bootlin.com/linux/0.01/source">first linux</a></li>
<li><a href="https://review.coreboot.org/plugins/gitiles/seabios/+/refs/heads/master/src/x86.h">seabios boot</a> which qemu uses per default for booting</li>
</ul>

<h2>Vision<a id="vision"/></h2>

<ul>
<li>practice assembly using <a href="https://exercism.org/tracks/x86-64-assembly">exercism</a></li>
<li>implement a basic shell as entry point for various sub programs</li>
</ul>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">Credits to <a href="https://github.com/Manawyrm">Manawyrm</a> for the inspiration</li>

<li id="fn:2">I already <a href="https://www.tutorials.de/resources/ein-eigenes-kleines-betriebssystem.84/">tossed some bits</a> (sorry, german only) 13 years ago but I felt too gatekept and didn&rsquo;t knew linux.</li>

<li id="fn:3">I couldn&rsquo;t write that without a laugh. As there would be something like usual assembler&hellip;</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Mon, 12 Jun 2023 12:29:46 +0200</pubDate>
    </item>
    <item>
      <title>Godot Wild Jam 55</title>
      <link>https://evilcookie.de/godot-wild-jam-55.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Godot Wild Jam 55 - zzZ</h1>

<p><img src="godot-wild-jam-55_zzz_intro.png"/></p>

<p>I did my first solo submission at the <a href="https://itch.io/jam/godot-wild-jam-55">godot wild jam 55</a> about the theme <em>dreams</em> and reached rank 29!
It&rsquo;s called <a href="https://itch.io/jam/godot-wild-jam-55/rate/1976329">zzZ</a> where the player catches sheep <em>to catch some z&rsquo;s</em><sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>.</p>

<p>Some more facts:</p>

<ul>
<li><a href="https://itch.io/jam/godot-wild-jam-55/rate/1976329">jam submission</a></li>
<li><a href="https://evilc00kie.itch.io/zzz">game</a></li>
<li><a href="https://github.com/Glow-Project/gwj-55">source code</a></li>
<li>two wildcards implemented:

<ul>
<li><em>A fork in the road</em>: four endings</li>
<li><em>Kabom!</em>: missed sheep explode</li>
</ul></li>
</ul>

<h3>Contents</h3>

<ul>
<li><a href="#idea">Idea</a></li>
<li><a href="#mechanics">Mechanics</a>

<ul>
<li><a href="#sheep spawner">Sheep spawner</a></li>
<li><a href="#basket">Basket</a></li>
<li><a href="#sunclock">Sunclock</a></li>
<li><a href="#tacho">Tacho (speedometer)</a></li>
<li><a href="#game-loop">Game loop</a></li>
<li><a href="#instantiated-scenes">Instantiated scenes</a></li>
</ul></li>
<li><a href="#audio">Audio</a>

<ul>
<li><a href="#background-music">Background music</a></li>
<li><a href="#audio-sheep">Sheep</a></li>
<li><a href="#music-box">Music box - intro + dreaming-end sound</a></li>
</ul></li>
<li><a href="#summary">Summary</a></li>
</ul>

<h2>Idea<a name='idea'/></h2>

<p><a href="https://github.com/Tch1b0">Johannes</a> had the idea of <em>falling sheeps that must get catched</em> but &ldquo;gifted&rdquo; it to me, since he couldn&rsquo;t do it himself due to lack of time.
The core mechanic was quite simple, but still fun to play for a few minutes. I was not hyped about it and that was actually my jam driver:</p>

<ul>
<li>simplicity: implement solid game mechanic with low innovation which makes it easy to <a href="https://idioms.thefreedictionary.com/kills+your+darlings"><em>kill my darlings</em></a>.</li>
<li>full stack: instead of delegating tasks/picking the ones I&rsquo;m good at, everything must be concepted and implemented by myself</li>
<li>own assets:

<ul>
<li>mspaint graphic: simple, sketchy, bare minimum that just works</li>
<li>ableton/dawless audio: game jams are a good opportunity to get passive feedback about my side quest &lsquo;music production&rsquo;</li>
</ul></li>
<li>focus within godot: <em>Does it add value to the player?</em>, avoid early optimization/polishing</li>
</ul>

<h2>Mechanics<a name='mechanics'/></h2>

<h3>Sheep spawner<a name='sheep spawner'/></h3>

<p><a href="https://github.com/Glow-Project/gwj-55/blob/main/sheep.gd">Sheep</a> are the essential entity of the game. They fall from the sky into the abyss unless the player catches them with the basket.</p>

<p><img src="godot-wild-jam-55_sheep.png"/></p>

<p><a href="https://github.com/Glow-Project/gwj-55/blob/main/spawner.gd">The spawner</a> is a scene on its own deciding where and when to generate sheep such as registering the abyss event, that a sheep emits once it fell into the abyss. To know where the abyss is, the spawner awaits the position of it.
Sheep get spawned once a second with random size, initial speed and position For choosing a random position, the spawner awaits another two points aka <code>Marker2D</code>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nd">@export</span> <span class="n">var</span> <span class="n">left_point</span><span class="p">:</span><span class="n">Marker2D</span>
</span></span><span class="line"><span class="cl"><span class="nd">@export</span> <span class="n">var</span> <span class="n">right_point</span><span class="p">:</span><span class="n">Marker2D</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">func</span> <span class="n">_on_timer_timeout</span><span class="p">(</span><span class="p">)</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">	<span class="n">var</span> <span class="n">sheep</span><span class="p">:</span><span class="n">Sheep</span> <span class="o">=</span> <span class="n">sheep_scene</span><span class="o">.</span><span class="n">instantiate</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="c1"># ...some more initalization...</span>
</span></span><span class="line"><span class="cl">	<span class="n">sheep</span><span class="o">.</span><span class="n">global_position</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="n">randf_range</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">		<span class="n">left_point</span><span class="o">.</span><span class="n">global_position</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">		<span class="n">right_point</span><span class="o">.</span><span class="n">global_position</span><span class="o">.</span><span class="n">x</span>
</span></span><span class="line"><span class="cl">		<span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="n">sheep</span><span class="o">.</span><span class="n">global_position</span><span class="o">.</span><span class="n">y</span> <span class="o">=</span> <span class="n">left_point</span><span class="o">.</span><span class="n">position</span><span class="o">.</span><span class="n">y</span>
</span></span></code></pre>
<p>Those points are visually placed above the game scene:</p>

<p><img src="godot-wild-jam-55_spawner.png"/></p>

<p>About every 10th sheep is special having one of the three complement colors cyan, magenta or yellow such as a smaller random size and a higher random initial speed. They&rsquo;re worth double on collecting and triple on not collecting them.</p>

<h3>Basket<a name='basket'/></h3>

<p><a href="https://github.com/Glow-Project/gwj-55/blob/main/basket.gd">The basket</a> emits an event for every sheep it collides with. Godot 4 makes it easy to automate collision shape generation from a sprite with complex shape:</p>

<p><img src="godot-wild-jam-55_basket.png"/></p>

<p>The basket&rsquo;s x-axis can be controlled via mouse which is hidden (via <a href="https://github.com/Glow-Project/gwj-55/blob/main/game.gd">game scene&rsquo;s</a> <code>Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN)</code>):</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">extends</span> <span class="n">Area2D</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">signal</span> <span class="n">item_collected</span><span class="p">(</span><span class="n">body</span><span class="p">:</span><span class="n">Node2D</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">func</span> <span class="n">_input</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="o">-</span><span class="o">&gt;</span> <span class="n">void</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="n">event</span> <span class="ow">is</span> <span class="n">InputEventMouseMotion</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="n">global_position</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">position</span><span class="o">.</span><span class="n">x</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">func</span> <span class="n">_on_body_entered</span><span class="p">(</span><span class="n">body</span><span class="p">)</span> <span class="o">-</span><span class="o">&gt;</span> <span class="n">void</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">	<span class="n">emit_signal</span><span class="p">(</span><span class="sa"></span><span class="s2">&#34;</span><span class="s2">item_collected</span><span class="s2">&#34;</span><span class="p">,</span> <span class="n">body</span><span class="p">)</span>
</span></span></code></pre>
<h3>Sunclock<a name='sunclock'/></h3>

<p><a href="https://github.com/Glow-Project/gwj-55/blob/main/sunclock.gd">The sunclock</a> is the timer of the game, visually similar to the one in <a href="https://minecraft.fandom.com/wiki/Clock">minecraft</a>. It consists of two
sprite layers. The bottom &ldquo;clock&rdquo;-layer gets rotated one revolution in a specified amount of time.</p>

<p><img src="godot-wild-jam-55_sunclock.png"/></p>

<p>This can be implemented via tween:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">extends</span> <span class="n">Node2D</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">signal</span> <span class="n">sunrise</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nd">@export</span> <span class="n">var</span> <span class="n">duration</span><span class="p">:</span><span class="nb">int</span> <span class="o">=</span> <span class="mi">30</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">func</span> <span class="n">_ready</span><span class="p">(</span><span class="p">)</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">	<span class="n">var</span> <span class="n">tween</span> <span class="o">=</span> <span class="n">create_tween</span><span class="p">(</span><span class="p">)</span><span class="o">.</span><span class="n">set_parallel</span><span class="p">(</span><span class="n">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	
</span></span><span class="line"><span class="cl">	<span class="n">tween</span><span class="o">.</span><span class="n">tween_property</span><span class="p">(</span><span class="err">$</span><span class="n">Clock</span><span class="p">,</span> <span class="sa"></span><span class="s2">&#34;</span><span class="s2">rotation_degrees</span><span class="s2">&#34;</span><span class="p">,</span> <span class="mi">180</span><span class="p">,</span> <span class="n">duration</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="n">tween</span><span class="o">.</span><span class="n">tween_property</span><span class="p">(</span><span class="err">$</span><span class="n">ClockSound</span><span class="p">,</span> <span class="sa"></span><span class="s2">&#34;</span><span class="s2">volume_db</span><span class="s2">&#34;</span><span class="p">,</span> <span class="o">-</span><span class="mi">10</span><span class="p">,</span> <span class="n">duration</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="k">await</span> <span class="n">tween</span><span class="o">.</span><span class="n">finished</span>
</span></span><span class="line"><span class="cl">	<span class="n">emit_signal</span><span class="p">(</span><span class="sa"></span><span class="s2">&#34;</span><span class="s2">sunrise</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span></code></pre>
<ul>
<li><code>set_parallel(true)</code> is needed, so multiple properties can be controlled with the same tween simultaneously</li>
<li>Additionally a ticking clock gets louder the more the clock approaches the end/next morning. Since the tween increases volume linearly but dB is logarithmic, the sound is barely hearable until the last few seconds, which is a nice side effect.</li>
<li><code>await tween.finished</code> is <a href="https://github.com/godotengine/godot/pull/41794">new in Godot 4</a> and replaces the <code>yield</code></li>
<li>the sunrise event gets emitted after the tween is finished/the time is over</li>
</ul>

<h3>Tacho (speedometer)<a name='tacho'/></h3>

<p><a href="https://github.com/Glow-Project/gwj-55/blob/main/tacho.gd">The tacho</a> shows a half circle on which a needle indicates the state of sleepiness:</p>

<ul>
<li>left: fully awake, emit event</li>
<li>middle: half asleep, game starts there</li>
<li>right: fully asleep, emit event</li>
</ul>

<p>There are three animated faces that should transport the meaning of the tacho:</p>

<p><img src="godot-wild-jam-55_face.png"/></p>

<p>The score is spread evenly across the 180° range. The code is quite messy but I don&rsquo;t want to hide anything:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">extends</span> <span class="n">Node2D</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">signal</span> <span class="n">fallen_asleep</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">signal</span> <span class="n">woken_up</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nd">@export</span> <span class="n">var</span> <span class="n">total</span><span class="p">:</span><span class="nb">int</span> <span class="o">=</span> <span class="mi">30</span>
</span></span><span class="line"><span class="cl"><span class="nd">@onready</span> <span class="n">var</span> <span class="n">score</span><span class="p">:</span><span class="nb">int</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">var</span> <span class="n">event_emitted</span><span class="p">:</span><span class="nb">bool</span> <span class="o">=</span> <span class="n">false</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">func</span> <span class="n">_ready</span><span class="p">(</span><span class="p">)</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">	<span class="err">$</span><span class="n">Emoji</span><span class="o">.</span><span class="n">play</span><span class="p">(</span><span class="sa"></span><span class="s2">&#34;</span><span class="s2">half_sleeping</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Called every frame. &#39;delta&#39; is the elapsed time since the previous frame.</span>
</span></span><span class="line"><span class="cl"><span class="n">func</span> <span class="n">_process</span><span class="p">(</span><span class="n">delta</span><span class="p">)</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">	<span class="err">$</span><span class="n">Needle</span><span class="o">.</span><span class="n">global_rotation_degrees</span> <span class="o">=</span> <span class="n">clamp</span><span class="p">(</span><span class="mi">180</span><span class="o">/</span><span class="n">total</span><span class="o">*</span><span class="n">score</span> <span class="o">+</span> <span class="mf">90.0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">180</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	
</span></span><span class="line"><span class="cl">	<span class="n">var</span> <span class="n">animation</span> <span class="o">=</span> <span class="sa"></span><span class="s2">&#34;</span><span class="s2">half_sleeping</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="n">score</span> <span class="o">&gt;</span><span class="o">=</span> <span class="n">total</span><span class="o">/</span><span class="mi">4</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="n">animation</span> <span class="o">=</span> <span class="sa"></span><span class="s2">&#34;</span><span class="s2">asleep</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="k">elif</span> <span class="n">score</span> <span class="o">&lt;</span><span class="o">=</span> <span class="o">-</span><span class="n">total</span><span class="o">/</span><span class="mi">4</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="n">animation</span> <span class="o">=</span> <span class="sa"></span><span class="s2">&#34;</span><span class="s2">awake</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">	
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="err">$</span><span class="n">Emoji</span><span class="o">.</span><span class="n">animation</span> <span class="o">!=</span> <span class="n">animation</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="err">$</span><span class="n">Emoji</span><span class="o">.</span><span class="n">play</span><span class="p">(</span><span class="n">animation</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">func</span> <span class="n">inc</span><span class="p">(</span><span class="n">val</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span><span class="o">-</span><span class="o">&gt;</span><span class="n">void</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">	<span class="n">score</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">score</span><span class="o">+</span><span class="n">val</span><span class="p">,</span> <span class="n">total</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="n">score</span> <span class="o">==</span> <span class="n">total</span> <span class="ow">and</span> <span class="err">!</span><span class="n">event_emitted</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="n">emit_signal</span><span class="p">(</span><span class="sa"></span><span class="s2">&#34;</span><span class="s2">fallen_asleep</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="n">event_emitted</span> <span class="o">=</span> <span class="n">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">func</span> <span class="n">dec</span><span class="p">(</span><span class="n">val</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span><span class="o">-</span><span class="o">&gt;</span><span class="n">void</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">	<span class="n">score</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">score</span><span class="o">-</span><span class="n">val</span><span class="p">,</span> <span class="o">-</span><span class="n">total</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="n">score</span> <span class="o">==</span> <span class="n">total</span> <span class="ow">and</span> <span class="err">!</span><span class="n">event_emitted</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="n">emit_signal</span><span class="p">(</span><span class="sa"></span><span class="s2">&#34;</span><span class="s2">woken_up</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="n">event_emitted</span> <span class="o">=</span> <span class="n">true</span>
</span></span></code></pre>
<p><code>event_emitted</code> debounces the event, so it gets only emitted once even if the player collectes more sheeps while the event wasn&rsquo;t consumed quickly enough by the game scene.</p>

<h3>Game loop<a name='game-loop'/></h3>

<p><a href="https://github.com/Glow-Project/gwj-55/blob/main/game.gd">The game scene</a> holds everything together while only waiting for three different events:</p>

<ul>
<li>sheep got collected: increment tacho, play sheep sound, free sheep node</li>
<li>sheep felt into the byss: decrement tacho, play explosion animation+sound, free sheep node</li>
<li>timer is over/ sunrise emitted by sunclock: change to game over scene</li>
</ul>

<p>All three events check if an end has been reached and if so, set the globals correctly, make the mouse visible again and change to the game over scene.
This is where the wildcard <em>A fork in the road</em> is implemented. Additionally the timeout event can decide between two ends depending if the player is more awake (score is negative, needle is on the left) or more sleepy (score is positive, needle is on the right or in the middle).</p>

<p>Retrospectively looking at the code: There is too much responsibility shared between game&lt;-&gt;tacho and game&lt;-&gt;game over. If I&rsquo;d invest more time into the game, I&rsquo;d refactor this inconsistency. The game itself shouldn&rsquo;t need to provide any content to game over. Also the game shouldn&rsquo;t need to know how to use the tacho&rsquo;s score for deciding if and which end has been reached.</p>

<h3>Intro<a name='intro'/></h3>

<p><a href="https://github.com/Glow-Project/gwj-55/blob/main/intro.gd">The intro</a> is basically an animation player blending in all the logos synced with the music box. In order to make the synchronization more reliable, the three main parts of the intro sound are split and played after each other. In theory, if the CPU is too slow, the break between the notes are higher, but that is totally fine.</p>

<p><img src="godot-wild-jam-55_intro_animation.png"/></p>

<h3>Godot - instantiated scenes<a name='instantiated-scenes'/></h3>

<p>In some cases it might be handy to change to a scene with some context. E.g. tell the game over screen which end has been reached. Sadly I couldn&rsquo;t find an idiomatic solution to create such instantiated scenes. If you instantiate a scene with parameters, you can&rsquo;t change to it. It is only possible to add it as a child or <a href="https://godotengine.org/qa/24773/how-to-load-and-change-scenes">use a hacky alternative</a>.</p>

<p>I added a plain auto load script <code>Globals.gd</code> and stored the state there. I dislike this approach while everyone could read/write the state.</p>

<h2>Audio<a name='audio'/></h2>

<p>Since my <a href="https://soundcloud.com/noise-taeter">alter ego</a> loves to produce and play around with audio, I couldn&rsquo;t resist to invest some time into music and sound effect production.</p>

<h3>Background music<a name='background-music'/></h3>

<p>Describing the creative process of making music isn&rsquo;t that reasonable than e.g. programming where the problem-solution relation can be argued quite rational.
I&rsquo;ll try to describe it either way.</p>

<p>The first auditive association of dreamy game music for me was the <a href="https://www.youtube.com/watch?v=RRfHbyCQDCo">Super Mario 64 Dire Dire Docks theme</a>.
Old consoles often use <a href="https://www.youtube.com/watch?v=vvBl3YUBUyY">FM synthesis</a> to generate complex instruments with a low memory footprint<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>. I decided to just play around with some c major chords (because this scale is the easiest one to play), with my dawless<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup> setup consisting of a MIDI Keyboard connected to the Korg FM2 which gets recorded by my digital recorder. The FM8 comes close to the Nintendo64 music engine while it also implements fm synthesis. I pressed record and played around with some chords and presets. I layered two chord progression takes but unfortunately haven&rsquo;t saved the project file&hellip; So the first layer is the first and loud chord progression and the second layer is the more quite progression that can be heard in between to given some kind of &ldquo;response&rdquo; if the first layer gave a &ldquo;call&rdquo;.</p>

<p><img src="godot-wild-jam-55_dawless.png"/></p>

<h3>Sheep<a name='audio-sheep'/></h3>

<p>I sliced a few different sheep sounds from <a href="https://freesound.org/people/milkotz/sounds/618865/">milkotz&rsquo;s recording</a> and pre loaded them, so playing them back has a low latency:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">var</span> <span class="n">sheeps</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">	<span class="n">preload</span><span class="p">(</span><span class="sa"></span><span class="s2">&#34;</span><span class="s2">res://milkotz_sheep1.mp3</span><span class="s2">&#34;</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">preload</span><span class="p">(</span><span class="sa"></span><span class="s2">&#34;</span><span class="s2">res://milkotz_sheep2.mp3</span><span class="s2">&#34;</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">preload</span><span class="p">(</span><span class="sa"></span><span class="s2">&#34;</span><span class="s2">res://milkotz_sheep3.mp3</span><span class="s2">&#34;</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">preload</span><span class="p">(</span><span class="sa"></span><span class="s2">&#34;</span><span class="s2">res://milkotz_sheep4.mp3</span><span class="s2">&#34;</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span></code></pre>
<p>Since there are small and big sheep, why not pitching the sample in relation to the size? Quickly a formula <code>pitch = 1 - (size-0.9)</code> was crafted with educated guessing such as trial-and-error. The pitch&rsquo;s default is set to 1. Basically it maps the range of the sheep scale factor within the range <code>[0.1,1]</code><sup class="footnote-ref" id="fnref:4"><a href="#fn:4">4</a></sup> onto the pitch range <code>[0.9, 1.8]</code> in reverse, because smaller sheep have higher pitches and vice versa. This means the smallest sheep with a size of <code>0.1</code> has a pitch of <code>1-(0.1-0.9) = 1.8</code> where the biggest sheep has a pitch of <code>1-(1-0.9) = 0.9</code><sup class="footnote-ref" id="fnref:5"><a href="#fn:5">5</a></sup>.</p>

<p>To have limitless parallel sheep sounds, an audio player get initialized for each collected sheep:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">func</span> <span class="n">_on_basket_item_collected</span><span class="p">(</span><span class="n">body</span><span class="p">:</span><span class="n">Sheep</span><span class="p">)</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">	<span class="n">var</span> <span class="n">sheep_player</span> <span class="o">=</span> <span class="n">AudioStreamPlayer</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="n">sheep_player</span><span class="o">.</span><span class="n">stream</span> <span class="o">=</span> <span class="n">sheeps</span><span class="p">[</span><span class="n">randi_range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="nb">len</span><span class="p">(</span><span class="n">sheeps</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">	<span class="n">sheep_player</span><span class="o">.</span><span class="n">set_bus</span><span class="p">(</span><span class="sa"></span><span class="s2">&#34;</span><span class="s2">SheepFX</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="n">sheep_player</span><span class="o">.</span><span class="n">pitch_scale</span> <span class="o">-</span><span class="o">=</span> <span class="p">(</span><span class="n">body</span><span class="o">.</span><span class="n">size</span><span class="o">-</span><span class="mf">0.9</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="n">add_child</span><span class="p">(</span><span class="n">sheep_player</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="n">sheep_player</span><span class="o">.</span><span class="n">play</span><span class="p">(</span><span class="p">)</span>
</span></span></code></pre>
<h3>Music box - intro + dreaming-end sound<a name='music-box'/></h3>

<p>The intro such as the dreaming-end have a music box to add a bit coziness/sleepiness to the scene.</p>

<h4>Instrument</h4>

<p>The instrument was made with a preset such as a few effects:</p>

<p><img src="godot-wild-jam-55_musicbox_effect_chain.png"/></p>

<ul>
<li><a href="https://www.ableton.com/en/packs/collision/">Ableton&rsquo;s Collision</a> with preset &ldquo;Glockenspiel basic&rdquo;: a typical music box sound but a bit to high</li>
<li>Chorus: Add more vibrato/pitch modulation to sound more natural.</li>
<li>Cabinet: Dampen the sound to make it more like it was recorded in a room.</li>
<li>EQ:

<ul>
<li>Cut off the lows is always good if they&rsquo;re not needed to avoid dirty mixes/rumbling sound.</li>
<li>Make the highs a bit more quiet additionally to the cabinet.</li>
</ul></li>
<li>Compressor: Nothing special, just make the sound more louder. This may be obsolete since I export all my samples normalized.</li>
</ul>

<h4>Notes</h4>

<p>Although the <a href="https://www.youtube.com/watch?v=dRw8Z32ECKo">whole-tone-scale</a> is usually used for dream sequences, I wanted something more naive and chose the c major scale again.
I tried to mimic the &ldquo;ascending stairs&rdquo; music box melodies often have and added a little offset to some notes so it sounds more analog.</p>

<p>Intro notes:
<img src="godot-wild-jam-55_musicbox_notes_intro.png"/></p>

<p>Dreaming-end notes:
<img src="godot-wild-jam-55_musicbox_notes_dreaming.png"/></p>

<h2>Summary<a name='summary'/></h2>

<p>The initial driver remained throughout the week and I learned some new things about Godot 4. Each mechanic could be outsourced to its own independent scene and connected to each other via events, eliminating a classical game loop.</p>

<p>Although everything works pretty bug free, the game scene holds more state than it should making it&rsquo;s role inconsistent in relation to tacho and game over. I&rsquo;d refactor this one if I&rsquo;d invest more time into this game.</p>

<p>Keeping the graphics simple and just sketch them via mspaint within only a few minuted helped to focus on the overall progress in contrast to the other jams.</p>

<p>The submission took the 29th place:</p>

<p><img src="godot-wild-jam-55_ranking.png"/></p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">Thanks to <a href="https://itch.io/post/7510574">FGKeiji&rsquo;s comment</a> to teach me this phrase!</li>

<li id="fn:2">A preset can be described by a few coefficients along with the used algorithm.</li>

<li id="fn:3">No &lsquo;Digital Audio Workstation&rsquo; which is often helpful on focusing since it isn&rsquo;t flooded with features and possibilities.</li>

<li id="fn:4">The minimum and maximum of all random sizes define the absolute range of all possible sizes: <a href="https://github.com/Glow-Project/gwj-55/blob/main/sheep.gd#L25">https://github.com/Glow-Project/gwj-55/blob/main/sheep.gd#L25</a></li>

<li id="fn:5">You&rsquo;re jamming on your keyboard <em>&ldquo;I know easier approaches!&rdquo;</em>? -&gt; teachme@evilcookie.de</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Sat, 25 Mar 2023 18:55:30 +0100</pubDate>
    </item>
    <item>
      <title>Blogstage-static web server in rust</title>
      <link>https://evilcookie.de/blogstage-static-web-server-in-rust.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>blogstage - static web server in rust</h1>

<p><img src="blogstage-static-web-server-in-rust_blogstage_left_the_port.jpg"/></p>

<p>I was looking for a useful service-oriented Rust project where I can test my project standards<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> and dive deeper into the language.
I decided to replace the &ldquo;caddy file server&rdquo; that serves this blog. The result is called <a href="https://github.com/RaphaelPour/blogstage">blogstage</a>: <em>Simple web server providing my static blog to the world.</em></p>

<p>It can be used via <code>blogstage &lt;ip:port&gt; &lt;path&gt;</code> or just <code>blogstage 0.0.0.0:80 ./blog/</code>.</p>

<h3>Contents</h3>

<ul>
<li><a href="#requirements">Requirements</a></li>
<li><a href="#how-to-serve">How to serve</a>

<ul>
<li><a href="#argument-parser">Argument parser</a></li>
<li><a href="#file-cache">File cache</a><br>
</li>
<li><a href="#tcp">TCP</a></li>
<li><a href="#http">HTTP</a></li>
<li><a href="#parallel-request-handling">Parallel request handling</a></li>
<li><a href="#exit">Exit</a></li>
</ul></li>
<li><a href="#testing">Testing</a>

<ul>
<li><a href="#unit-test">Unit test</a></li>
<li><a href="#integration-test">Integration test</a></li>
</ul></li>
<li><a href="#benchmark">Benchmark</a></li>
<li><a href="#wrap-it-up">Wrap it up</a></li>
<li><a href="#vision">Vision</a></li>
</ul>

<h2>Requirements<a name="requirements"></h2>

<p>The requirements were fairly simple, because the blog is static consisting of a flat directory of rendered HTML files along with some images<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> and my
reverse-proxy is handling the TLS stuff:</p>

<ul>
<li>bind to given address+port</li>
<li>serve files from given directory (and prevent serving other directories e.g. via relative paths)</li>
<li>serve text and binary for HTML and images</li>
<li>not too easy to <em>dive deeper into rust</em></li>
</ul>

<h2>How to serve<a name="how-to-serve"></h2>

<p>Since the requirements weren&rsquo;t hard to fulfill, there are <a href="https://lib.rs/web-programming/http-server">tons of crates</a> that
can do the job. E.g. <a href="https://docs.rs/warp/0.3.3/warp/">warp</a> can do it in one line with something like <code>warp::serve(warp::fs::dir(&quot;./blog&quot;)).run(([127, 0, 0, 1], 8080))</code>. I decided against a ready-to-use crate, to make it a bit more difficult and educational.</p>

<p><a href="https://docs.rs/web_server/0.4.2/web_server">web_server</a> didn&rsquo;t worked with dynamic strings, since <a href="https://docs.rs/web_server/latest/web_server/struct.HttpServer.html#method.get">routes need to be added</a> with <code>&amp;'static str</code> where I couldn&rsquo;t figure out if and how this can be fixed<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup>.</p>

<p>The solution was surprisingly easy to find. There is a tutorial about <a href="https://doc.rust-lang.org/book/ch20-00-final-project-a-web-server.html">Building a Multithreaded Web Server</a> in the official rust docs. What a coincidence!</p>

<h3>Argument parser<a name="argument-parser"></h3>

<p>Just two mandatory positional arguments without a default to keep things simple and explicit:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="cm">/*</span><span class="cm"> parse arguments </span><span class="cm">*/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">let</span><span class="w"> </span><span class="n">uri</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">std</span>::<span class="n">env</span>::<span class="n">args</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">nth</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="nb">Some</span><span class="p">(</span><span class="n">uri</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">uri</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="nb">None</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;usage: blogstage &lt;URI&gt; &lt;PATH&gt;&#34;</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="k">return</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">let</span><span class="w"> </span><span class="n">path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">std</span>::<span class="n">env</span>::<span class="n">args</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">nth</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="nb">Some</span><span class="p">(</span><span class="n">path</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">path</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="nb">None</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;usage: blogstage &lt;URI&gt; &lt;PATH&gt;&#34;</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="k">return</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span></code></pre>
<h3>File cache<a name="file-cache"></h3>

<p>The blog is pretty small, and its container<sup class="footnote-ref" id="fnref:4"><a href="#fn:4">4</a></sup> gets rebuilt for any change. Therefore I decided to load
all the files non-recursively into a hash map with with <a href="https://en.wikipedia.org/wiki/Basename">basename</a>
as key and content as value.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="cm">/*</span><span class="cm"> load files </span><span class="cm">*/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">let</span><span class="w"> </span><span class="n">raw_entries</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">fs</span>::<span class="n">read_dir</span><span class="p">(</span><span class="n">path</span><span class="p">.</span><span class="n">clone</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="nb">Ok</span><span class="p">(</span><span class="n">entries</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">entries</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;error reading files from {}: {}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">path</span><span class="p">,</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="k">return</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">files</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HashMap</span>::<span class="n">new</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">for</span><span class="w"> </span><span class="n">entry</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">raw_entries</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="o">!</span><span class="n">entry</span><span class="p">.</span><span class="n">as_ref</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">path</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">is_file</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="k">continue</span><span class="w"></span><span class="nl"></span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="n">files</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="n">entry</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="p">.</span><span class="n">as_ref</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="p">.</span><span class="n">file_name</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="p">.</span><span class="n">into_string</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="p">.</span><span class="n">clone</span><span class="p">(</span><span class="p">)</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="n">fs</span>::<span class="n">read</span><span class="p">(</span><span class="n">entry</span><span class="p">.</span><span class="n">as_ref</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">path</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">clone</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<h3>TCP<a name="tcp"></h3>

<p>Although doing TCP by myself felt a bit too low-level in the first place, it was quite pleasant with rust using only <code>bind</code> and an <code>incoming</code> iterator:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="cm">/*</span><span class="cm"> start server </span><span class="cm">*/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">let</span><span class="w"> </span><span class="n">listener</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">TcpListener</span>::<span class="n">bind</span><span class="p">(</span><span class="n">uri</span><span class="p">.</span><span class="n">clone</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="cm">/*</span><span class="cm"> error handling </span><span class="cm">*/</span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">for</span><span class="w"> </span><span class="n">stream</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">listener</span><span class="p">.</span><span class="n">incoming</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">match</span><span class="w"> </span><span class="n">stream</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Ok</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">on_request</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span><span class="w"> </span><span class="n">fileHashMap</span><span class="p">)</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="cm">/*</span><span class="cm"> error handling </span><span class="cm">*/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<h3>HTTP<a name="http"></h3>

<p>The request handler has a TCP stream such as the hash map containing all the files:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">on_request</span><span class="p">(</span><span class="k">mut</span><span class="w"> </span><span class="n">stream</span>: <span class="nc">TCPStream</span><span class="p">,</span><span class="w"> </span><span class="n">files</span>: <span class="nc">HashMap</span><span class="o">&lt;</span><span class="nb">String</span><span class="p">,</span><span class="w"> </span><span class="nb">Vec</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;</span><span class="o">&gt;</span><span class="p">)</span><span class="w">
</span></span></span></code></pre>
<p>Then the request will get read until an empty line has been reached:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">reader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">BufReader</span>::<span class="n">new</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">stream</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">let</span><span class="w"> </span><span class="n">request</span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="n">_</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">reader</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">.</span><span class="n">lines</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="o">|</span><span class="n">result</span><span class="o">|</span><span class="w"> </span><span class="n">result</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">.</span><span class="n">take_while</span><span class="p">(</span><span class="o">|</span><span class="n">line</span><span class="o">|</span><span class="w"> </span><span class="o">!</span><span class="n">line</span><span class="p">.</span><span class="n">is_empty</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">.</span><span class="n">collect</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span></code></pre>
<p>Parse the requested file quick &lsquo;n&rsquo; dirty (see <a href="#vision">vision</a>). Additionally <code>index.html</code> if the requested filename is empty for convenience:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">target</span>: <span class="nb">String</span> <span class="o">=</span><span class="w"> </span><span class="n">request</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="sc">&#39; &#39;</span><span class="p">)</span><span class="p">.</span><span class="n">collect</span>::<span class="o">&lt;</span><span class="nb">Vec</span><span class="o">&lt;</span><span class="o">&amp;</span><span class="kt">str</span><span class="o">&gt;</span><span class="o">&gt;</span><span class="p">(</span><span class="p">)</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="p">[</span><span class="mi">1</span><span class="o">..</span><span class="p">]</span><span class="p">.</span><span class="n">to_string</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">if</span><span class="w"> </span><span class="n">target</span><span class="p">.</span><span class="n">is_empty</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">  </span><span class="n">target</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#34;index.html&#34;</span><span class="p">.</span><span class="n">into</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<p>In order to serve more complex files like images (and to be future ready if I add openscad or mp3 stuff), guess the mime type
via the crate&hellip;well&hellip;<a href="https://docs.rs/mime_guess/latest/mime_guess/">mime_guess</a>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">mime</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mime_guess</span>::<span class="n">from_path</span><span class="p">(</span><span class="n">target</span><span class="p">.</span><span class="n">clone</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">.</span><span class="n">first</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span></code></pre>
<p>If the requested file can be found in the hashmap, write its content along with a valid HTTP header to the stream.
Otherwise just write a HTTP header with status code <a href="https://http.cat/404">404</a>.
On any error, the response handler panics caused by the massive use of <code>unwrap</code>, and the thread just vanishes into the void (see <a href="#vision">vision</a>):</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">match</span><span class="w"> </span><span class="n">files</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="o">&amp;</span><span class="n">target</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">  </span><span class="nb">Some</span><span class="p">(</span><span class="n">body</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">body</span><span class="p">.</span><span class="n">len</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;200 {}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">target</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="n">stream</span><span class="p">.</span><span class="n">write_all</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">      </span><span class="fm">format!</span><span class="p">(</span><span class="s">&#34;HTTP/1.1 200 OK\r\nContent-Length: {length}\r\nContent-Type: {mime}\r\n\r\n&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">      </span><span class="p">.</span><span class="n">as_bytes</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="n">stream</span><span class="p">.</span><span class="n">write_all</span><span class="p">(</span><span class="n">body</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">  </span><span class="nb">None</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;404 {}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">target</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="n">stream</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">      </span><span class="p">.</span><span class="n">write_all</span><span class="p">(</span><span class="s">&#34;HTTP/1.1 404 NOT FOUND\r\n\r\n&#34;</span><span class="p">.</span><span class="n">as_bytes</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">      </span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span></code></pre>
<h3>Parallel request handling<a name="parallel-request-handling"></h3>

<p>Since I want to implement parallel request handling as simple as possible and don&rsquo;t need to limit the amount of requests<sup class="footnote-ref" id="fnref:5"><a href="#fn:5">5</a></sup>, <a href="https://doc.rust-lang.org/std/thread/"><code>thread::spawn</code></a> will do the trick:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">for</span><span class="w"> </span><span class="n">stream</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">listener</span><span class="p">.</span><span class="n">incoming</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">match</span><span class="w"> </span><span class="n">stream</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Ok</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">files</span><span class="p">.</span><span class="n">clone</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="n">thread</span>::<span class="n">spawn</span><span class="p">(</span><span class="k">move</span><span class="w"> </span><span class="o">|</span><span class="o">|</span><span class="w"> </span><span class="n">on_request</span><span class="p">(</span><span class="n">s</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;error accepting connection: {}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="k">continue</span><span class="w"></span><span class="nl"></span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<p>The file map must be cloned, so its ownership can be moved to the thread.</p>

<h3>Exit<a name="exit"></h3>

<p>It doesn&rsquo;t deserve the predicate <strong>graceful</strong>, but it provides some simple mechanism to simply abort the whole request handling via the crate <a href="https://docs.rs/ctrlc/3.1.9/ctrlc/">ctrlc</a>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">ctrlc</span>::<span class="n">set_handler</span><span class="p">(</span><span class="k">move</span><span class="w"> </span><span class="o">|</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">   </span><span class="n">std</span>::<span class="n">process</span>::<span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span></code></pre>
<h2>Testing<a name="testing"></h2>

<p>My testing goal was to cover the <code>on_request</code> method via unit- and the CLI via integration-tests.</p>

<h3>Unit test<a name="unit-test"></h3>

<p>To test the <code>on_request</code> method, the stream must be mocked. Looking closely what the function actually
does with the stream reveals that we actually only need to read from and write to it. <a href="https://rust-lang.github.io/async-book/09_example/03_tests.html#testing-the-tcp-server">As described in the tutorial</a>,
<code>TCPStream</code> can be replaced by allowing any type that implements the <code>Read</code> and <code>Write</code> trait using <code>impl Read+Write</code>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">on_request</span><span class="p">(</span><span class="k">mut</span><span class="w"> </span><span class="n">stream</span>: <span class="nc">impl</span><span class="w"> </span><span class="n">Read</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">Write</span><span class="p">,</span><span class="w"> </span><span class="n">files</span>: <span class="nc">HashMap</span><span class="o">&lt;</span><span class="nb">String</span><span class="p">,</span><span class="w"> </span><span class="nb">Vec</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;</span><span class="o">&gt;</span><span class="p">)</span><span class="w">
</span></span></span></code></pre>
<p>The mock implements all methods needed for properly read and write to it. I modified the tutorial&rsquo;s mock to be single-threaded as we don&rsquo;t use async:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">assert_cmd</span>::<span class="n">prelude</span>::<span class="o">*</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">predicates</span>::<span class="n">prelude</span>::<span class="o">*</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">cmp</span>::<span class="n">min</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">collections</span>::<span class="n">HashMap</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">io</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">io</span>::<span class="p">{</span><span class="n">Read</span><span class="p">,</span><span class="w"> </span><span class="n">Write</span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">process</span>::<span class="n">Command</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">struct</span> <span class="nc">MockTcpStream</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="n">read_data</span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="n">write_data</span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="c1">// https://doc.rust-lang.org/std/io/trait.Read.html
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">impl</span><span class="w"> </span><span class="n">Read</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">MockTcpStream</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">fn</span> <span class="nf">read</span><span class="p">(</span><span class="bp">self</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="bp">Self</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="p">[</span><span class="kt">u8</span><span class="p">]</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">io</span>::<span class="nb">Result</span><span class="o">&lt;</span><span class="kt">usize</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">size</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="n">min</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">read_data</span><span class="p">.</span><span class="n">len</span><span class="p">(</span><span class="p">)</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span><span class="p">.</span><span class="n">len</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="n">buf</span><span class="p">[</span><span class="o">..</span><span class="n">size</span><span class="p">]</span><span class="p">.</span><span class="n">copy_from_slice</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">read_data</span><span class="p">[</span><span class="o">..</span><span class="n">size</span><span class="p">]</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Ok</span><span class="p">(</span><span class="n">size</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="c1">// https://doc.rust-lang.org/std/io/trait.Write.html
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">impl</span><span class="w"> </span><span class="n">Write</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">MockTcpStream</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">fn</span> <span class="nf">write</span><span class="p">(</span><span class="bp">self</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="bp">Self</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span>: <span class="kp">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">]</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">io</span>::<span class="nb">Result</span><span class="o">&lt;</span><span class="kt">usize</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="bp">self</span><span class="p">.</span><span class="n">write_data</span><span class="p">.</span><span class="n">extend</span><span class="p">(</span><span class="n">buf</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">cloned</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Ok</span><span class="p">(</span><span class="n">buf</span><span class="p">.</span><span class="n">len</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">fn</span> <span class="nf">flush</span><span class="p">(</span><span class="bp">self</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="bp">Self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">io</span>::<span class="nb">Result</span><span class="o">&lt;</span><span class="p">(</span><span class="p">)</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Ok</span><span class="p">(</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<p>Then tests can simply be written as such:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="cp">#[</span><span class="cp">test</span><span class="cp">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">serve_not_found</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">input</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">b&#34;</span><span class="s">GET /test.html HTTP/1.1</span><span class="se">\r</span><span class="se">\n</span><span class="se">\r</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">contents</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">vec!</span><span class="p">[</span><span class="mi">0</span><span class="k">u8</span><span class="p">;</span><span class="w"> </span><span class="mi">1024</span><span class="p">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="n">contents</span><span class="p">[</span><span class="o">..</span><span class="n">input</span><span class="p">.</span><span class="n">len</span><span class="p">(</span><span class="p">)</span><span class="p">]</span><span class="p">.</span><span class="n">clone_from_slice</span><span class="p">(</span><span class="n">input</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">stream</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MockTcpStream</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="n">read_data</span>: <span class="nc">contents</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="n">write_data</span>: <span class="nb">Vec</span>::<span class="n">new</span><span class="p">(</span><span class="p">)</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">files</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HashMap</span>::<span class="n">new</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="n">blogstage</span>::<span class="n">on_request</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">stream</span><span class="p">,</span><span class="w"> </span><span class="n">files</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">expected_response</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">format!</span><span class="p">(</span><span class="s">&#34;HTTP/1.1 404 NOT FOUND\r\n\r\n&#34;</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="fm">assert!</span><span class="p">(</span><span class="n">stream</span><span class="p">.</span><span class="n">write_data</span><span class="p">.</span><span class="n">starts_with</span><span class="p">(</span><span class="n">expected_response</span><span class="p">.</span><span class="n">as_bytes</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<h3>Integration test<a name="integration-test"></h3>

<p>Each integration test case ensures that the binary behaves correctly with respect to the given environment and arguments. The following test checks if <code>blogstage</code> fails correctly when provided with no arguments:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="cp">#[</span><span class="cp">test</span><span class="cp">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">uri_is_missing</span><span class="p">(</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(</span><span class="p">)</span><span class="p">,</span><span class="w"> </span><span class="nb">Box</span><span class="o">&lt;</span><span class="k">dyn</span><span class="w"> </span><span class="n">std</span>::<span class="n">error</span>::<span class="n">Error</span><span class="o">&gt;</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">cmd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Command</span>::<span class="n">cargo_bin</span><span class="p">(</span><span class="s">&#34;blogstage&#34;</span><span class="p">)</span><span class="o">?</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="n">cmd</span><span class="p">.</span><span class="n">assert</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">.</span><span class="n">success</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">.</span><span class="n">stdout</span><span class="p">(</span><span class="n">predicate</span>::<span class="kt">str</span>::<span class="n">contains</span><span class="p">(</span><span class="s">&#34;usage: blogstage &lt;URI&gt; &lt;PATH&gt;\n&#34;</span><span class="p">)</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="nb">Ok</span><span class="p">(</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<ul>
<li>cases are based on the clip application test section from <a href="https://rust-cli.github.io/book/tutorial/testing.html#testing-cli-applications-by-running-them">the official docs</a></li>
<li>execution and asserting is done via the crate <a href="https://docs.rs/assert_cmd/latest/assert_cmd/">assert_cmd</a></li>
<li>the binary still exits with success, since I haven&rsquo;t added exit codes</li>
</ul>

<h3>Coverage report<a name="coverage-report"></h3>

<p>Coverage reports help to measure and observe how much of the code is actually covered. Based on those reports, it is easy
to tell for which branches tests need to be made.</p>

<p>The coverage profile can be enabled via environment variables, <a href="https://doc.rust-lang.org/rustc/instrument-coverage.html">as described in the docs</a></p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">RUSTFLAGS: <span class="s2">&#34;-C instrument-coverage&#34;</span> LLVM_PROFILE_FILE: <span class="s2">&#34;cargo-test-%p-%m.profraw&#34;</span> cargo <span class="nb">test</span>
</span></span></code></pre>
<p><sup class="footnote-ref" id="fnref:6"><a href="#fn:6">6</a></sup></p>

<p>The <a href="https://doc.rust-lang.org/rustc/instrument-coverage.html#installing-llvm-coverage-tools">llvm-coverage-tools</a> provide <code>rust-profdata</code> and <code>rust-cov</code> to process the generated raw coverage data. All those <code>*.profraw</code> files can be merged via <code>rust-profdata merge -sparse *.profraw -o coverage.profdata</code> and converted to html using <code>rust-cov show target/debug/blogstage -instr-profile=coverage.profdata --ignore-filename-regex=/.cargo --format=html --show-line-counts-or-regions &gt; coverage/index.html</code></p>

<p><img src="blogstage-static-web-server-in-rust_coverage.png"/></p>

<p>Unfortunately I didn&rsquo;t got the unittest covered, although they all passed. The integration tests on the other side worked out-of-the-box.</p>

<h2>Benchmark<a name="benchmark"></h2>

<p>If the files get cached in-memory and the service is tightly tailored around my use-case, you may ask <strong>Is it faster?</strong></p>

<p>Well, a tiny bit. I used <a href="https://github.com/mildsunrise/curl-benchmark">mildsunrise&rsquo;s curl-benchmark</a> with 100 requests and an insecure connection<sup class="footnote-ref" id="fnref:7"><a href="#fn:7">7</a></sup>:</p>

<p>caddy file serve:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">         DNS      TCP        SSL  Request           Content
</span></span><span class="line"><span class="cl">Code  lookup  connect  handshake     sent    TTFB  download
</span></span><span class="line"><span class="cl">min:     5.0     51.0       22.0     28.0    54.0       0.0
</span></span><span class="line"><span class="cl">avg:     5.7     55.6       35.8     32.2    60.1       1.1
</span></span><span class="line"><span class="cl">med:     5.0     55.0       36.0     32.0    60.0       1.0
</span></span><span class="line"><span class="cl">max:    15.0     67.0       45.0     41.0    86.0      10.0
</span></span><span class="line"><span class="cl">dev:   21.5%     5.5%      10.7%     8.1%    7.5%    106.1%
</span></span></code></pre>
<p>blogstage:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">         DNS      TCP        SSL  Request           Content
</span></span><span class="line"><span class="cl">Code  lookup  connect  handshake     sent    TTFB  download
</span></span><span class="line"><span class="cl">min:     5.0     51.0       26.0     28.0    58.0       0.0
</span></span><span class="line"><span class="cl">avg:     5.4     55.9       34.9     32.3    68.3       0.7
</span></span><span class="line"><span class="cl">med:     5.0     55.0       35.0     32.0    68.0       1.0
</span></span><span class="line"><span class="cl">max:     7.0     68.0       46.0     41.0    77.0       2.0
</span></span><span class="line"><span class="cl">dev:   12.3%     4.9%      11.2%     6.9%    5.9%     95.5%
</span></span></code></pre>
<h2>Wrap it up<a name="wrap-it-up"></h2>

<p><a href="https://github.com/RaphaelPour/blogstage/blob/980d84d096a0c9fe4b36186c71462f521c9ac848/src/main.rs"><code>src/main.rs</code></a>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">collections</span>::<span class="n">HashMap</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">fs</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">net</span>::<span class="n">TcpListener</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">thread</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">blogstage</span>::<span class="n">on_request</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="c1">// https://doc.rust-lang.org/book/ch20-01-single-threaded.html
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="cm">/*</span><span class="cm"> parse arguments </span><span class="cm">*/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">uri</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">std</span>::<span class="n">env</span>::<span class="n">args</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">nth</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Some</span><span class="p">(</span><span class="n">uri</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">uri</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">None</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;usage: blogstage &lt;URI&gt; &lt;PATH&gt;&#34;</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="k">return</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">std</span>::<span class="n">env</span>::<span class="n">args</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">nth</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Some</span><span class="p">(</span><span class="n">path</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">path</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">None</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;usage: blogstage &lt;URI&gt; &lt;PATH&gt;&#34;</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="k">return</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="cm">/*</span><span class="cm"> load files </span><span class="cm">*/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">raw_entries</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">fs</span>::<span class="n">read_dir</span><span class="p">(</span><span class="n">path</span><span class="p">.</span><span class="n">clone</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Ok</span><span class="p">(</span><span class="n">entries</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">entries</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;error reading files from {}: {}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">path</span><span class="p">,</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="k">return</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">files</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HashMap</span>::<span class="n">new</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">entry</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">raw_entries</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="o">!</span><span class="n">entry</span><span class="p">.</span><span class="n">as_ref</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">path</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">is_file</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="k">continue</span><span class="w"></span><span class="nl"></span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="n">files</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="n">entry</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="p">.</span><span class="n">as_ref</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="p">.</span><span class="n">file_name</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="p">.</span><span class="n">into_string</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="p">.</span><span class="n">clone</span><span class="p">(</span><span class="p">)</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="n">fs</span>::<span class="n">read</span><span class="p">(</span><span class="n">entry</span><span class="p">.</span><span class="n">as_ref</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">path</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">clone</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="cm">/*</span><span class="cm"> start server </span><span class="cm">*/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">listener</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">TcpListener</span>::<span class="n">bind</span><span class="p">(</span><span class="n">uri</span><span class="p">.</span><span class="n">clone</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Ok</span><span class="p">(</span><span class="n">l</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">l</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;error on binding to {}: {}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">uri</span><span class="p">,</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="k">return</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="c1">// react to Ctrl+C
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">    </span><span class="n">ctrlc</span>::<span class="n">set_handler</span><span class="p">(</span><span class="k">move</span><span class="w"> </span><span class="o">|</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="n">std</span>::<span class="n">process</span>::<span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">stream</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">listener</span><span class="p">.</span><span class="n">incoming</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="k">match</span><span class="w"> </span><span class="n">stream</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="nb">Ok</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="kd">let</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">files</span><span class="p">.</span><span class="n">clone</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="n">thread</span>::<span class="n">spawn</span><span class="p">(</span><span class="k">move</span><span class="w"> </span><span class="o">|</span><span class="o">|</span><span class="w"> </span><span class="n">on_request</span><span class="p">(</span><span class="n">s</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;error accepting connection: {}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="k">continue</span><span class="w"></span><span class="nl"></span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<p><a href="https://github.com/RaphaelPour/blogstage/blob/980d84d096a0c9fe4b36186c71462f521c9ac848/src/main.rs"><code>src/lib.rs</code></a>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">collections</span>::<span class="n">HashMap</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">io</span>::<span class="p">{</span><span class="n">prelude</span>::<span class="o">*</span><span class="p">,</span><span class="w"> </span><span class="n">BufReader</span><span class="p">,</span><span class="w"> </span><span class="n">Read</span><span class="p">,</span><span class="w"> </span><span class="n">Write</span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="c1">// We need to put everything out of main.rs what should be tested via integration tests:
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="c1">// https://doc.rust-lang.org/book/ch11-03-test-organization.html#integration-tests-for-binary-crates
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">on_request</span><span class="p">(</span><span class="k">mut</span><span class="w"> </span><span class="n">stream</span>: <span class="nc">impl</span><span class="w"> </span><span class="n">Read</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">Write</span><span class="p">,</span><span class="w"> </span><span class="n">files</span>: <span class="nc">HashMap</span><span class="o">&lt;</span><span class="nb">String</span><span class="p">,</span><span class="w"> </span><span class="nb">Vec</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">reader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">BufReader</span>::<span class="n">new</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">stream</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">request</span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="n">_</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">reader</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">.</span><span class="n">lines</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="o">|</span><span class="n">result</span><span class="o">|</span><span class="w"> </span><span class="n">result</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">.</span><span class="n">take_while</span><span class="p">(</span><span class="o">|</span><span class="n">line</span><span class="o">|</span><span class="w"> </span><span class="o">!</span><span class="n">line</span><span class="p">.</span><span class="n">is_empty</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">.</span><span class="n">collect</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">target</span>: <span class="nb">String</span> <span class="o">=</span><span class="w"> </span><span class="n">request</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="sc">&#39; &#39;</span><span class="p">)</span><span class="p">.</span><span class="n">collect</span>::<span class="o">&lt;</span><span class="nb">Vec</span><span class="o">&lt;</span><span class="o">&amp;</span><span class="kt">str</span><span class="o">&gt;</span><span class="o">&gt;</span><span class="p">(</span><span class="p">)</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="p">[</span><span class="mi">1</span><span class="o">..</span><span class="p">]</span><span class="p">.</span><span class="n">to_string</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">target</span><span class="p">.</span><span class="n">is_empty</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="n">target</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#34;index.html&#34;</span><span class="p">.</span><span class="n">into</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">mime</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mime_guess</span>::<span class="n">from_path</span><span class="p">(</span><span class="n">target</span><span class="p">.</span><span class="n">clone</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">.</span><span class="n">first</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">match</span><span class="w"> </span><span class="n">files</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="o">&amp;</span><span class="n">target</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Some</span><span class="p">(</span><span class="n">body</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">body</span><span class="p">.</span><span class="n">len</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;200 {}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">target</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="n">stream</span><span class="p">.</span><span class="n">write_all</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="fm">format!</span><span class="p">(</span><span class="s">&#34;HTTP/1.1 200 OK\r\nContent-Length: {length}\r\nContent-Type: {mime}\r\n\r\n&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="p">.</span><span class="n">as_bytes</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="n">stream</span><span class="p">.</span><span class="n">write_all</span><span class="p">(</span><span class="n">body</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">None</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;404 {}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">target</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="n">stream</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="p">.</span><span class="n">write_all</span><span class="p">(</span><span class="s">&#34;HTTP/1.1 404 NOT FOUND\r\n\r\n&#34;</span><span class="p">.</span><span class="n">as_bytes</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<h2>Vision<a name="vision"></h2>

<ul>
<li>compression: add additional gzip compression</li>
<li>refactor request parser: despite its bad readability, it e.g. fails if a filename contains spaces</li>
<li>eliminate unwraps: explicit error handling instead of &ldquo;resilience by accident&rdquo;</li>
</ul>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">like testing, coverage, release, ci,&hellip;</li>

<li id="fn:2">via <a href="https://github.com/RaphaelPour/blogctl">blogctl</a></li>

<li id="fn:3">see <a href="https://github.com/RaphaelPour/blogstage/commit/70a9c21e91e82dc86fb8c985931e06f5da53b3d8">70a9c21e</a></li>

<li id="fn:4">For simplifying the operation effort, I build a container containing the whole blog. I replaced the <a href="https://registry.hub.docker.com/_/caddy">caddy container</a> with an <a href="https://registry.hub.docker.com/_/alpine">alpine</a> one.</li>

<li id="fn:5">in comparison to the <a href="https://docs.rs/threadpool/latest/threadpool/">ThreadPool</a> approach of the <a href="https://doc.rust-lang.org/book/ch20-02-multithreaded.html">Multithreaded Server tutorial</a></li>

<li id="fn:6">Those environment variables can also be used for <code>cargo build</code> to generate a coverage binary.</li>

<li id="fn:7">python curl-benchmark.py &ndash; -L -k evilcookie.de`, somehow the SSL handshake didn&rsquo;t work&hellip;</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Wed, 08 Mar 2023 12:41:10 +0100</pubDate>
    </item>
    <item>
      <title>Finish rustlings</title>
      <link>https://evilcookie.de/finish-rustlings.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Finish rustlings</h1>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">+----------------------------------------------------+
</span></span><span class="line"><span class="cl">|          You made it to the Fe-nish line!          |
</span></span><span class="line"><span class="cl">+--------------------------  ------------------------+
</span></span><span class="line"><span class="cl">                          \\/
</span></span><span class="line"><span class="cl">     ▒▒          ▒▒▒▒▒▒▒▒      ▒▒▒▒▒▒▒▒          ▒▒
</span></span><span class="line"><span class="cl">   ▒▒▒▒  ▒▒    ▒▒        ▒▒  ▒▒        ▒▒    ▒▒  ▒▒▒▒
</span></span><span class="line"><span class="cl">   ▒▒▒▒  ▒▒  ▒▒            ▒▒            ▒▒  ▒▒  ▒▒▒▒
</span></span><span class="line"><span class="cl"> ░░▒▒▒▒░░▒▒  ▒▒            ▒▒            ▒▒  ▒▒░░▒▒▒▒
</span></span><span class="line"><span class="cl">   ▓▓▓▓▓▓▓▓  ▓▓      ▓▓██  ▓▓  ▓▓██      ▓▓  ▓▓▓▓▓▓▓▓
</span></span><span class="line"><span class="cl">     ▒▒▒▒    ▒▒      ████  ▒▒  ████      ▒▒░░  ▒▒▒▒
</span></span><span class="line"><span class="cl">       ▒▒  ▒▒▒▒▒▒        ▒▒▒▒▒▒        ▒▒▒▒▒▒  ▒▒
</span></span><span class="line"><span class="cl">         ▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▒▒▒▒▒▒▒▒▓▓▒▒▓▓▒▒▒▒▒▒▒▒
</span></span><span class="line"><span class="cl">           ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
</span></span><span class="line"><span class="cl">             ▒▒▒▒▒▒▒▒▒▒██▒▒▒▒▒▒██▒▒▒▒▒▒▒▒▒▒
</span></span><span class="line"><span class="cl">           ▒▒  ▒▒▒▒▒▒▒▒▒▒██████▒▒▒▒▒▒▒▒▒▒  ▒▒
</span></span><span class="line"><span class="cl">         ▒▒    ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒    ▒▒
</span></span><span class="line"><span class="cl">       ▒▒    ▒▒    ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒    ▒▒    ▒▒
</span></span><span class="line"><span class="cl">       ▒▒  ▒▒    ▒▒                  ▒▒    ▒▒  ▒▒
</span></span><span class="line"><span class="cl">           ▒▒  ▒▒                      ▒▒  ▒▒
</span></span></code></pre>
<p>I just finished <a href="https://github.com/rust-lang/rustlings">rustlings</a>.</p>

<p>Some data:</p>

<ul>
<li>94 exercises about the rust language and standard library</li>
<li><a href="https://github.com/RaphaelPour/rustlings/">my solutions</a><sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup></li>
<li>from 13/01/2023 to 07/02/2023</li>
<li>15 commits</li>
<li>top three commits ranked by solved exercises:

<ul>
<li><a href="https://github.com/RaphaelPour/rustlings/commit/7053c4d9e284cfebca97cfc45e278e770503c294">21</a></li>
<li><a href="https://github.com/RaphaelPour/rustlings/commit/c9c35e8c8f1c8d97a104337756e064e7533e8c3f">15</a></li>
<li><a href="https://github.com/RaphaelPour/rustlings/commit/5191a228ee00f1fc88b99d5b034c2d8a9abc1c7e">14</a></li>
</ul></li>
</ul>

<h2>Rustlings</h2>

<p><img src="finish-rustlings_rustlings.png"/></p>

<p>I like the approach of rustlings in comparissons to other language learning &ldquo;platforms&rdquo; like <a href="exercism.io/">exercism</a> or <a href="https://adventofcode.com/">aoc</a><sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>.
There is a binary <code>rustlings</code> that is executed with the <code>watch</code> command showing a screen with the current progress such as the compiler output
of the current exercise. The output refreshes after each file change. An exercise consists of code that doesn&rsquo;t compile and/or has unsatisfied tests.</p>

<p>Due to the refreshing output and my two window setup (see image above; <code>rustlings watch</code> on the left, vim on the right), the feedback loop was very tight. Every exercise was mostly implemented but lacked
in some key lines that needed to be tweaked/added. This helped learning to read actual rust code and focus on the current lesson. Since rust has a bunch of
sophisticated concepts, it is good to not get overwhelmed by all the other stuff around the lesson.</p>

<h2>Rust impressions</h2>

<p>I read in <a href="https://doc.rust-lang.org/book/">the book</a>, used the <code>hint</code> commmand, guessed with trial-and-error and just applied the suggestions of the linter <a href="https://doc.rust-lang.org/stable/clippy/index.html">clippy</a>.</p>

<p>Rust is tough with all rich syntax and my main thought after this is: You are the garbabe collector. Since rust gurantees memory safety but has no garbage collector, the developer needs to tell the compiler that everything is
valid by e.g. <a href="https://doc.rust-lang.org/beta/rust-by-example/scope/borrow.html">borrowing</a> variables or defining <a href="https://doc.rust-lang.org/beta/rust-by-example/scope/lifetime.html">lifetimes</a>.</p>

<p>Thoughts despite <a href="hello-rust.html#thoughts">the ones of my first rust post</a>:</p>

<ul>
<li><a href="https://doc.rust-lang.org/rust-by-example/flow_control/match.html"><code>match</code></a> is not only a sophisticated switch case but it can also <a href="https://doc.rust-lang.org/rust-by-example/flow_control/match/destructuring/destructure_tuple.html">deconstruct</a> and <a href="https://doc.rust-lang.org/rust-by-example/flow_control/match/binding.html">bind</a></li>
<li><a href="https://doc.rust-lang.org/rust-by-example/custom_types/enum.html"><code>Enums</code></a> are not only &ldquo;symbols&rdquo; but can be all kinds of handy type with a struct. Together with <code>match</code>, <a href="https://doc.rust-lang.org/rust-by-example/flow_control/match/guard.html">this looks</a> promissing.</li>
</ul>

<p>Altough I want to do a few more rust projects to checkout the language with real use-cases, I can&rsquo;t imaging using it in my current every day life. As a gopher, the lack of runtime is not worth doing the garbage collection stuff.</p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1"><p>Yes, I could&rsquo;ve forked it. But after naively cloning it I always refocused on rustlings
  than moving to a fork. Well, even right now I&rsquo;m writing this post instead of fixing it&hellip;</p></li>

<li id="fn:2">While it is not exactly a learning platform, I like to use it as such.</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Tue, 07 Feb 2023 23:33:11 +0100</pubDate>
    </item>
    <item>
      <title>Thinking tools aka fidget toys</title>
      <link>https://evilcookie.de/thinking-tools-aka-fidget-toys.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Thinking tools aka fidget toys</h1>

<p>As my mind often needs something to do, I stumpled across fidget toys<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> as an alternative of chewing finger nails and excessive chewing gum usage<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>.</p>

<p>Anyway, I want to share my mostly self-printed thinking tools.</p>

<p><img src="thinking-tools-aka-fidget-toys_thinking_tools.jpg"/></p>

<p>My current ranking:</p>

<ol>
<li><a href="https://www.printables.com/model/928-yet-another-fidget-infinity-cube-v2">infinite fidget cube</a>: very satisfying to fold the cube infinitely many times</li>
<li><a href="https://www.printables.com/model/276901-joy-fidget">joy fidget</a>: reminds me of <a href="https://en.wikipedia.org/wiki/Nintendo_64">good old N64 times</a> while the stick&rsquo;s spring has a good feel</li>
<li>headless skrew with nut<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup>: best if both hands need to do something</li>
<li>mini fascia roll<sup class="footnote-ref" id="fnref:4"><a href="#fn:4">4</a></sup>: good for muscle relaxation, it&rsquo;s the more sporty fidget toy</li>
<li>rubber duck: while it can be compressed quite satisfying, the sound is annyoing</li>
<li>classic fidget cube: the universal and classical cube you get when searching for those stuff, it&rsquo;s a bit too small for my hands</li>
<li><a href="https://www.printables.com/model/359925-approve-brick">approve brick</a>: this solid body is ok to keep hands busy but rather than that has no additional function</li>
</ol>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">probably best known for <a href="https://en.wikipedia.org/wiki/Fidget_spinner">fidget spinners</a></li>

<li id="fn:2">kind of a subconsious thing which is especially hard to control when brainstorming or concentrating</li>

<li id="fn:3">the remaining parts of my 3d-printed broken microphone stand</li>

<li id="fn:4">no advertisment here, just look for &lsquo;mini faszia roll&rsquo; using the search engine of your choice</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Wed, 18 Jan 2023 12:34:35 +0100</pubDate>
    </item>
    <item>
      <title>Hello rust</title>
      <link>https://evilcookie.de/hello-rust.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Hello rust</h1>

<p>I finally checked out <a href="https://www.rust-lang.org/">Rust</a> and solved <a href="https://adventofcode.com/2022/day/1">day one</a> of last year&rsquo;s advent of code.</p>

<p>tl;dr:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">fs</span>::<span class="n">File</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">io</span>::<span class="p">{</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">prelude</span>::<span class="o">*</span><span class="p">,</span><span class="w"> </span><span class="n">BufReader</span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="c1">// https://stackoverflow.com/a/45882510
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">io</span>::<span class="nb">Result</span><span class="o">&lt;</span><span class="p">(</span><span class="p">)</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="c1">// https://doc.rust-lang.org/std/vec/struct.Vec.html
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">calories</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Vec</span>::<span class="n">new</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">sum</span>: <span class="kt">i32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="c1">// https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#propagating-errors
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">File</span>::<span class="n">open</span><span class="p">(</span><span class="s">&#34;input&#34;</span><span class="p">)</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Ok</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">file</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="k">in</span><span class="w">  </span><span class="n">BufReader</span>::<span class="n">new</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="p">.</span><span class="n">lines</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="nb">Ok</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">data</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="o">=</span><span class="o">=</span><span class="w"> </span><span class="s">&#34;&#34;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="n">calories</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="n">sum</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="k">continue</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nl"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="c1">// https://doc.rust-lang.org/std/primitive.str.html#method.parse
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">        </span><span class="n">sum</span><span class="w"> </span><span class="o">+</span><span class="o">=</span><span class="w"> </span><span class="n">data</span><span class="p">.</span><span class="n">parse</span>::<span class="o">&lt;</span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">calories</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="n">calories</span><span class="p">.</span><span class="n">sort</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;part1: {}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">calories</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">rev</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">take</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="p">.</span><span class="n">sum</span>::<span class="o">&lt;</span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;part2: {}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">calories</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">rev</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">take</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span><span class="p">.</span><span class="n">sum</span>::<span class="o">&lt;</span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nb">Ok</span><span class="p">(</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<p>Contents:</p>

<ul>
<li><a href="#motivation">Motivation</a></li>
<li><a href="#starting-over">Starting over</a></li>
<li><a href="#so-vs-official-docs">SO vs. official docs</a></li>
<li><a href="#investigate">Investigate</a>

<ul>
<li><a href="#immutable-first">Immutable first</a></li>
<li><a href="#error-handling">Error-handling</a></li>
<li><a href="#string-to-int">String to int</a></li>
</ul></li>
<li><a href="#expand-the-shortcuts">Expand the shortcuts</a></li>
<li><a href="#reaching-for-the-second-star">Reaching for the second star</a></li>
<li><a href="#thoughts">Thoughts</a></li>
</ul>

<h2>Motivation<a name="motivation"/></h2>

<p>As a C fanboy, I&rsquo;m interested in languages that have a similar low level scope. Since 2019, <a href="https://go.dev/">Go</a> is my language of choice where I made myself comfortable.</p>

<p>The claims and news brought me to Rust and today my curiousity about them took over:</p>

<ul>
<li><a href="https://lwn.net/Articles/910762/">linux kernel support</a></li>
<li><a href="https://prev.rust-lang.org/en-US/faq.html#does-rust-have-a-runtime">no runtime</a></li>
<li><a href="https://prev.rust-lang.org/en-US/faq.html#is-rust-garbage-collected">no garbage collector</a></li>
</ul>

<h2>Starting over<a name="starting-over"/></h2>

<p>To dive right into the language, I skipped all tutorials and exampls and started with day 1 of the last year&rsquo;s advent of code right away. Rust is already installed, so I started over by asking the internet for <a href="https://doc.rust-lang.org/stable/rust-by-example/std_misc/file/read_lines.html"><em>Rust line by line</em></a> and <a href="https://doc.rust-lang.org/std/cmp/fn.max.html"><em>Rust max value</em></a>, and here you are:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">fs</span>::<span class="n">File</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">io</span>::<span class="p">{</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">BufRead</span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">path</span>::<span class="n">Path</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">cmp</span><span class="p">;</span><span class="w"> 
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="c1">// based on https://doc.rust-lang.org/stable/rust-by-example/std_misc/file/read_lines.html
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">max</span>: <span class="kt">i32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">sum</span>: <span class="kt">i32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">lines</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">read_lines</span><span class="p">(</span><span class="s">&#34;input&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">lines</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="k">if</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="o">=</span><span class="o">=</span><span class="w"> </span><span class="s">&#34;&#34;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                    </span><span class="n">max</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cmp</span>::<span class="n">max</span><span class="p">(</span><span class="n">max</span><span class="p">,</span><span class="w"> </span><span class="n">sum</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                    </span><span class="n">sum</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                    </span><span class="k">continue</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nl"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="n">sum</span><span class="w"> </span><span class="o">+</span><span class="o">=</span><span class="w"> </span><span class="n">data</span><span class="p">.</span><span class="n">parse</span>::<span class="o">&lt;</span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="n">max</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cmp</span>::<span class="n">max</span><span class="p">(</span><span class="n">max</span><span class="p">,</span><span class="w"> </span><span class="n">sum</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;{}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">max</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">read_lines</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;</span><span class="p">(</span><span class="n">filename</span>: <span class="nc">P</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">io</span>::<span class="nb">Result</span><span class="o">&lt;</span><span class="n">io</span>::<span class="n">Lines</span><span class="o">&lt;</span><span class="n">io</span>::<span class="n">BufReader</span><span class="o">&lt;</span><span class="n">File</span><span class="o">&gt;</span><span class="o">&gt;</span><span class="o">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">where</span><span class="w"> </span><span class="n">P</span>: <span class="nb">AsRef</span><span class="o">&lt;</span><span class="n">Path</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">File</span>::<span class="n">open</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span><span class="o">?</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="nb">Ok</span><span class="p">(</span><span class="n">io</span>::<span class="n">BufReader</span>::<span class="n">new</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="p">.</span><span class="n">lines</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<p>Looking more closely over the copy-pasta code, some constructs are standing out<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>:</p>

<ul>
<li><code>let mut max: i32 = 0;</code></li>
<li><code>if let Ok(lines) = read_lines(&quot;input&quot;) {</code></li>
<li><code>data.parse::&lt;i32&gt;().unwrap()</code></li>
<li><code>println!(&quot;{}, max)</code></li>
</ul>

<p>Don&rsquo;t forget the elephant <del>in the room</del> at the end. The last block seemed too complicated for simply reading a file line-by-line. Let&rsquo;s address this one first, as it&rsquo;s the greatest question mark for me.</p>

<h2>SO vs. official docs<a name="so-vs-official-docs"/></h2>

<p>Well, rather than addressing it, I asked the internet again as the code from the codes looked too optimized. <a href="https://stackoverflow.com/a/45882510">This SO post</a> was more reasonable than the <code>read_lines</code> section from the official documentation:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">fs</span>::<span class="n">File</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">io</span>::<span class="p">{</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">prelude</span>::<span class="o">*</span><span class="p">,</span><span class="w"> </span><span class="n">BufReader</span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">cmp</span><span class="p">;</span><span class="w"> 
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="c1">// based on https://doc.rust-lang.org/stable/rust-by-example/std_misc/file/read_lines.html
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">io</span>::<span class="nb">Result</span><span class="o">&lt;</span><span class="p">(</span><span class="p">)</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">max</span>: <span class="kt">i32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">sum</span>: <span class="kt">i32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">File</span>::<span class="n">open</span><span class="p">(</span><span class="s">&#34;input&#34;</span><span class="p">)</span><span class="o">?</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">reader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">BufReader</span>::<span class="n">new</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">reader</span><span class="p">.</span><span class="n">lines</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="o">=</span><span class="o">=</span><span class="w"> </span><span class="s">&#34;&#34;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="n">max</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cmp</span>::<span class="n">max</span><span class="p">(</span><span class="n">max</span><span class="p">,</span><span class="w"> </span><span class="n">sum</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="n">sum</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">                </span><span class="k">continue</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nl"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="n">sum</span><span class="w"> </span><span class="o">+</span><span class="o">=</span><span class="w"> </span><span class="n">data</span><span class="p">.</span><span class="n">parse</span>::<span class="o">&lt;</span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">max</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cmp</span>::<span class="n">max</span><span class="p">(</span><span class="n">max</span><span class="p">,</span><span class="w"> </span><span class="n">sum</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;{}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">max</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="nb">Ok</span><span class="p">(</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<h2>Investigate<a name="investigate"/></h2>

<p>Let&rsquo;s get into all the remaining findings from <a href="#starting-over">starting over</a>.</p>

<h3>Immutable first<a name="immutable-first"/></h3>

<p>Variables are immutable/constant by default. A classical variables needs to be declared with <code>mut</code> for beeing mutable:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">max</span>: <span class="kt">i32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span></code></pre>
<h3>Error handling<a name="error-handling"/></h3>

<p>Error handling works by using <a href="https://doc.rust-lang.org/std/result/"><code>Results</code></a> containing the wanted data on success or an error. They can be assumed via <code>Ok</code> and <code>Err</code>, providing the wanted variable if it applies. In case of an error, the condition is false and never enters the branch:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">lines</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">read_lines</span><span class="p">(</span><span class="s">&#34;input&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span></code></pre>
<p>Alternatively by using <code>?</code> aka the <a href="https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator">question mark operator</a>, the error can implicitly be returned from
the current function:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">File</span>::<span class="n">open</span><span class="p">(</span><span class="s">&#34;input&#34;</span><span class="p">)</span><span class="o">?</span><span class="p">;</span><span class="w">
</span></span></span></code></pre>
<p>This can be converted into a more explicit approach using <a href="https://doc.rust-lang.org/reference/expressions/match-expr.html"><code>match</code></a> where the success and failure case has its own arm.
An arm is kind of a lambda <code>&lt;pattern&gt; =&gt; &lt;expression&gt;</code>. The first pattern match gets selected and the corresponding expression executed. The <code>Err</code> and <code>Ok</code> do some kind of type-assertion including declaration of variables <code>e</code> and <code>file</code>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">File</span>::<span class="n">open</span><span class="p">(</span><span class="s">&#34;input&#34;</span><span class="p">)</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="nb">Ok</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">file</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span></code></pre>
<h3>String to int<a name="string-to-int"/></h3>

<p>Converting a string into an integer needs some parsing. The <code>::&lt;&gt;</code> aka <a href="https://doc.rust-lang.org/book/appendix-02-operators.html?highlight=turbofish#non-operator-symbols">turbofish operator</a> is used to tell <code>parse</code> about the target type:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">data</span><span class="p">.</span><span class="n">parse</span>::<span class="o">&lt;</span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="w">
</span></span></span></code></pre>
<h2>Expand the shortcuts<a name="expand-the-shortcuts"/></h2>

<p>After expanding the error handling shortcuts, the code gets more transparent:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">fs</span>::<span class="n">File</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">io</span>::<span class="p">{</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">prelude</span>::<span class="o">*</span><span class="p">,</span><span class="w"> </span><span class="n">BufReader</span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">cmp</span><span class="p">;</span><span class="w"> 
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="c1">// https://stackoverflow.com/a/45882510
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">io</span>::<span class="nb">Result</span><span class="o">&lt;</span><span class="p">(</span><span class="p">)</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">max</span>: <span class="kt">i32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">sum</span>: <span class="kt">i32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="c1">// https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#propagating-errors
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">File</span>::<span class="n">open</span><span class="p">(</span><span class="s">&#34;input&#34;</span><span class="p">)</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Ok</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">file</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">reader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">BufReader</span>::<span class="n">new</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">reader</span><span class="p">.</span><span class="n">lines</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="nb">Ok</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">data</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="o">=</span><span class="o">=</span><span class="w"> </span><span class="s">&#34;&#34;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="n">max</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cmp</span>::<span class="n">max</span><span class="p">(</span><span class="n">max</span><span class="p">,</span><span class="w"> </span><span class="n">sum</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="n">sum</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="k">continue</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nl"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="c1">// https://doc.rust-lang.org/std/primitive.str.html#method.parse
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">        </span><span class="n">sum</span><span class="w"> </span><span class="o">+</span><span class="o">=</span><span class="w"> </span><span class="n">data</span><span class="p">.</span><span class="n">parse</span>::<span class="o">&lt;</span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">max</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cmp</span>::<span class="n">max</span><span class="p">(</span><span class="n">max</span><span class="p">,</span><span class="w"> </span><span class="n">sum</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;{}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">max</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="nb">Ok</span><span class="p">(</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<h2>Reaching for the second star<a name="reaching-for-the-second-star"/></h2>

<p>Finally I used a vector to solve the second aoc part:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">fs</span>::<span class="n">File</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">io</span>::<span class="p">{</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">prelude</span>::<span class="o">*</span><span class="p">,</span><span class="w"> </span><span class="n">BufReader</span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="c1">// https://stackoverflow.com/a/45882510
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">io</span>::<span class="nb">Result</span><span class="o">&lt;</span><span class="p">(</span><span class="p">)</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="c1">// https://doc.rust-lang.org/std/vec/struct.Vec.html
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">calories</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Vec</span>::<span class="n">new</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">sum</span>: <span class="kt">i32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="c1">// https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#propagating-errors
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">File</span>::<span class="n">open</span><span class="p">(</span><span class="s">&#34;input&#34;</span><span class="p">)</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="nb">Ok</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">file</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="k">in</span><span class="w">  </span><span class="n">BufReader</span>::<span class="n">new</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="p">.</span><span class="n">lines</span><span class="p">(</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="nb">Ok</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">data</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="p">}</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="o">=</span><span class="o">=</span><span class="w"> </span><span class="s">&#34;&#34;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="n">calories</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="n">sum</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">            </span><span class="k">continue</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nl"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">        </span><span class="c1">// https://doc.rust-lang.org/std/primitive.str.html#method.parse
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">        </span><span class="n">sum</span><span class="w"> </span><span class="o">+</span><span class="o">=</span><span class="w"> </span><span class="n">data</span><span class="p">.</span><span class="n">parse</span>::<span class="o">&lt;</span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">calories</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">sum</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="n">calories</span><span class="p">.</span><span class="n">sort</span><span class="p">(</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;part1: {}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">calories</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">rev</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">take</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="p">.</span><span class="n">sum</span>::<span class="o">&lt;</span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;part2: {}&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">calories</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">rev</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">take</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span><span class="p">.</span><span class="n">sum</span>::<span class="o">&lt;</span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="w">    
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nb">Ok</span><span class="p">(</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre>
<p>While the error handling takes a few lines, summing up the n-th last items of the vector are pretty ruby-alike short:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">calories</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">rev</span><span class="p">(</span><span class="p">)</span><span class="p">.</span><span class="n">take</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="p">.</span><span class="n">sum</span>::<span class="o">&lt;</span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">(</span><span class="p">)</span><span class="p">)</span><span class="p">;</span><span class="w">
</span></span></span></code></pre>
<h2>Thoughts<a name="thoughts"/></h2>

<p>It was refreshing to checkout a new language including its resources and toolchain. The error handling with the <code>Ok</code> and <code>Err</code> construct is a mixture of the two error handling concepts I saw in other languages so far: try-catch and error value.
Although this looks promising for writing readable and maintainable code, I&rsquo;m far from judging.</p>

<p>The rustc compiler is colorful and includes some hints which supports my learning-by-doing approach.</p>

<p>Finally I&rsquo;m hyped and want to learn more about the language. Let&rsquo;s do some more days!</p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">In context to Golang and C.</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Tue, 03 Jan 2023 16:21:58 +0100</pubDate>
    </item>
    <item>
      <title>Femto retrospective</title>
      <link>https://evilcookie.de/femto-retrospective.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>femto - project showcase</h1>

<p><a href="https://github.com/RaphaelPour/femto">Femto</a> is a minimal CLI text editor made
in C with zero dependencies inspired by <a href="https://github.com/antirez/kilo">Antirez&rsquo;s kilo
editor</a>. This retrospective contains all
noteworthy progress made within this project starting from the idea until the &lsquo;end&rsquo;.</p>

<p>I&rsquo;ve created this post about a year ago, but never published it due to missing content/relevant information. Coming back a year later I see this from a different perspective. This is a good rough overview
before diving into the C source. The testing framework <em>cilicon</em> might be a good inspiration for unit-testing with C, too.</p>

<ul>
<li><a href="#general-information">General information</a></li>
<li><a href="#motivation">Motivation</a></li>
<li><a href="#internal-structure">Internal structure</a>

<ul>
<li><a href="#session">Session</a></li>
<li><a href="#screen">Screen</a></li>
<li><a href="#buffer">Buffer</a></li>
<li><a href="#terminal">Terminal</a></li>
<li><a href="#fileio">FileIO</a></li>
<li><a href="#ui">UI</a></li>
<li><a href="#helper">Helper</a></li>
</ul></li>
<li><a href="#cilicon">cilicon - unit test library</a>

<ul>
<li><a href="#thoughts">Thoughts</a></li>
</ul></li>
</ul>

<h2>General information<a name='general-information'/></h2>

<p>Features:</p>

<ul>
<li>open, create, save text files</li>
<li>navigation</li>
<li>edition</li>
</ul>

<p>Bugs:</p>

<ul>
<li>bad line wrapping</li>
<li>unknown escape sequences were printed to screen (e.g. Shift+Arrow key)</li>
<li>rare unhandeld glitches while editing</li>
</ul>

<p>Personal project outcome:</p>

<ul>
<li>deal with terminal&rsquo;s raw mode

<ul>
<li>use terminal as framebuffer</li>
<li>CLI dialogs</li>
</ul></li>
<li><a href="https://travis-ci.com/github/RaphaelPour/femto">CI testing</a> a C project</li>
<li>develop C unit testing lib <em>Cilicon</em></li>
<li>improve gdb skills to find and fix memory leaks</li>
</ul>

<h2>Motivation<a name='motivation'/></h2>

<ul>
<li>active C project to gain more experience</li>
<li>zero dependencies</li>
<li>text editors have a lot of feature potential (highlighting, tabs,
views, macros,&hellip;)</li>
<li>coping with the terminal&rsquo;s raw mode can be handy for further projects</li>
</ul>

<h2>Internal structure<a name='internal-structure'/></h2>

<p>Femto consists of seven components:</p>

<ul>
<li><a href="https://github.com/RaphaelPour/femto/blob/master/include/session.h">Session</a>:

<ul>
<li>provides abstract editor API</li>
<li>navigation</li>
<li>edition</li>
</ul></li>
<li><a href="https://github.com/RaphaelPour/femto/blob/master/include/screen.h">Screen</a>:

<ul>
<li>render framebuffer</li>
<li>update status bar</li>
<li>set cursors</li>
</ul></li>
<li><a href="https://github.com/RaphaelPour/femto/blob/master/include/buffer.h">Buffer</a>:

<ul>
<li>data+length structure</li>
<li>used as framebuffer</li>
</ul></li>
<li><a href="https://github.com/RaphaelPour/femto/blob/master/include/terminal.h">Terminal</a>:

<ul>
<li>control raw mode</li>
<li>provide user input, size and cursor position</li>
</ul></li>
<li><a href="https://github.com/RaphaelPour/femto/blob/master/include/fileio.h">FileIO</a>:

<ul>
<li>load file to internal representation</li>
<li>save file from internal representation</li>
</ul></li>
<li><a href="https://github.com/RaphaelPour/femto/blob/master/include/ui.h">UI</a>: Dialogs for user interaction</li>
<li><a href="https://github.com/RaphaelPour/femto/blob/master/include/helper.h">Helper</a>

<ul>
<li>logger</li>
<li>math functions (min,max,clamp, poor man&rsquo;s log10)</li>
</ul></li>
</ul>

<h3>Session<a name='session'/></h3>

<p>The <a href="https://github.com/RaphaelPour/femto/blob/master/include/session.h#L33">session type</a> contains the state of the running application:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="cm">/* Name of the read file */</span>
</span></span><span class="line"><span class="cl">    <span class="kt">char</span> <span class="o">*</span><span class="n">filename</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/* Dimensions of the terminal */</span>
</span></span><span class="line"><span class="cl">    <span class="n">TerminalSize</span> <span class="n">terminal_size</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/* Position on the screen */</span>
</span></span><span class="line"><span class="cl">    <span class="n">TerminalPosition</span> <span class="n">cursor_position</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/* Offset between file content and screen */</span>
</span></span><span class="line"><span class="cl">    <span class="n">TerminalPosition</span> <span class="n">offset</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/* Array of lines which hold the content */</span>
</span></span><span class="line"><span class="cl">    <span class="n">Line</span> <span class="o">*</span><span class="n">lines</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">size_t</span> <span class="n">line_count</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/* Total length of all line lengths combined */</span>
</span></span><span class="line"><span class="cl">    <span class="n">size_t</span> <span class="n">content_length</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/* Dirty flag */</span>
</span></span><span class="line"><span class="cl">    <span class="kt">bool</span> <span class="n">dirty</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="n">Session</span><span class="p">;</span>
</span></span></code></pre>
<p>Any action a user makes affects this state.</p>

<ul>
<li><em>navigation</em> updates <code>cursor_position</code> and <code>offset</code></li>
<li><em>edition</em> updates the same as navigation plus <code>lines</code>,<code>line_count</code>, <code>content_length</code> and <code>dirty</code>.</li>
<li><em>save/load file</em> updates <code>filename</code> and <code>dirty</code></li>
</ul>

<h3>Screen<a name='screen'/></h3>

<ul>
<li>update output on terminal</li>
<li>generate status bar</li>
</ul>

<h3>Buffer<a name='buffer'/></h3>

<p>A simple data+length structure with functions to write more convenient to the data:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">typedef</span> <span class="k">struct</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">char</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">unsigned</span> <span class="n">length</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="n">Buffer</span><span class="p">;</span>
</span></span></code></pre>
<p>This struture is currently only used by the screen module as framebuffer.</p>

<h3>Terminal<a name='terminal'/></h3>

<ul>
<li>enable/Disable Raw mode</li>
<li>determine terminal resolution</li>
<li>determine cursor position</li>
<li>get user input and replace it with a pseudo key if compound</li>
</ul>

<p>It&rsquo;s purpose overlaps with the screen module. Both are somehow manipulating the terminal&rsquo;s behaviour.</p>

<h3>FileIO<a name='fileio'/></h3>

<p>FileIO uses the filename given in the session object and stores the file&rsquo;s content into it.</p>

<h3>UI<a name='ui'/></h3>

<p>Handle dialogs including getting the users input, generating the right status bar and trigger a refresh.
It comes with two dialogs:</p>

<ul>
<li>safe file</li>
<li>quit (<em>do you really discard unsaved changes?</em>)</li>
</ul>

<p>Internally it has a generic dialog function which could be used to add more.</p>

<h3>Helper<a name='helper'/></h3>

<p>The helper has two major responisibilities:</p>

<ul>
<li>logging</li>
<li>provide shortcuts for often used mathematical functions</li>
</ul>

<p>The logger has a <code>printf</code> alike formatter function which automatically includes the module name and line number where the logger gets called.
This is accomplished by hiding the real formatter function behind a preprocessor directive which adds the module name and line number in place.</p>

<h2>cilicon - unit test library<a name='cilicon'/></h2>

<p>Cilicon is a <em>syntactic sugar library</em> which &lsquo;frames&rsquo; a unit test using concepts
like &lsquo;it&rsquo;, &lsquo;suite&rsquo; and &lsquo;expect_&hellip;&rsquo; inspired by ruby&rsquo;s rspec.</p>

<p>Each C module has it&rsquo;s own test suite represented in an extra test file. For
example the module <code>buffer</code> has it&rsquo;s own <code>test_suite_buffer</code> with the file
<code>buffer_test.c</code>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">test_create_buffer</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">TEST_IT_NAME</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">creates a buffer</span><span class="s">&#34;</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">Buffer</span> <span class="o">*</span><span class="n">buf</span> <span class="o">=</span> <span class="n">fe_create_buffer</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span><span class="p">(</span> <span class="o">!</span> <span class="n">expect_not_null</span><span class="p">(</span> <span class="n">buf</span> <span class="p">)</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">fe_free_buffer</span><span class="p">(</span><span class="n">buf</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">TEST_OK</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">test_append_to_buffer</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">TEST_IT_NAME</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">appends to a buffer</span><span class="s">&#34;</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">test_string</span> <span class="o">=</span> <span class="sa"></span><span class="s">&#34;</span><span class="s">const char *test_string</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">Buffer</span> <span class="o">*</span><span class="n">buf</span> <span class="o">=</span> <span class="n">fe_create_buffer</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">if</span><span class="p">(</span> <span class="o">!</span> <span class="n">expect_not_null</span><span class="p">(</span> <span class="n">buf</span> <span class="p">)</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">fe_append_to_buffer</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="n">test_string</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span><span class="n">test_string</span><span class="p">)</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">if</span><span class="p">(</span> <span class="o">!</span> <span class="n">expect_b_eq</span><span class="p">(</span> <span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)</span> <span class="n">test_string</span><span class="p">,</span> <span class="n">buf</span><span class="o">-</span><span class="o">&gt;</span><span class="n">data</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span> <span class="n">test_string</span> <span class="p">)</span><span class="p">,</span> <span class="n">buf</span><span class="o">-</span><span class="o">&gt;</span><span class="n">length</span>  <span class="p">)</span><span class="p">)</span> <span class="k">goto</span> <span class="n">cleanup</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">TEST_OK</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nl">cleanup</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">fe_free_buffer</span><span class="p">(</span><span class="n">buf</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">test_suite_buffer</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">TEST_SUITE_NAME</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">Buffer</span><span class="s">&#34;</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">test_create_buffer</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">test_append_to_buffer</span><span class="p">(</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>Which outputs the following on success:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">---- Buffer ----
</span></span><span class="line"><span class="cl">it creates a buffer                      OK
</span></span><span class="line"><span class="cl">it appends to a buffer                   OK
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ALL PASSED
</span></span></code></pre>
<p>And on failure:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">---- Buffer ----
</span></span><span class="line"><span class="cl">it creates a buffer                      OK
</span></span><span class="line"><span class="cl">it appends to a buffer                   FAIL
</span></span><span class="line"><span class="cl">Expected equal buffers, got unequal.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">1 of 2 expects failed.
</span></span><span class="line"><span class="cl">FATALITY
</span></span></code></pre>
<h3>Thoughts<a name='thoughts'/></h3>

<ul>
<li>Having some convenience features on writing tests is key for C since there is nothing one can build from with zero dependencies.</li>
<li><code>Goto</code> is bad. <a href="https://koblents.com/Ches/Links/Month-Mar-2013/20-Using-Goto-in-Linux-Kernel-Code/">Isn&rsquo;t it?</a> But there are cases where <code>goto</code> is better than for example <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">wet</a> code. Big C projects like the <a href="https://github.com/torvalds/linux">linux kernel</a> or <a href="https://github.com/qemu/qemu">qemu</a> use <code>goto</code> for implementing clean ups. For example qemu&rsquo;s <a href="https://github.com/qemu/qemu/blob/1f7c02797fa189ce4b34382020bbce63262a5758/qemu-img.c#L515">img_create</a>.</li>
<li>A year later, I&rsquo;m not using femto at all. I though about using it for commit messages or at least when administrating my servers to let new use-cases and valuable feature ideas evolve, but nope. But that is ok.</li>
</ul>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Mon, 02 Jan 2023 16:20:40 +0100</pubDate>
    </item>
    <item>
      <title>Parametric eurorack blank plate with OpenSCAD</title>
      <link>https://evilcookie.de/parametric-eurorack-blank-plate-with-openscad.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Parametric eurorack blank plate with OpenSCAD</h1>

<p>I&rsquo;ve designed a 3d-printable parametric eurorack blank plate including my artist name with <a href="https://openscad.org/">OpenSCAD</a>.</p>

<p><img src="parametric-eurorack-blank-plate-with-openscad_impression_parametric_eurorack_blank_plate.jpg"/></p>

<h2>Motivation</h2>

<p>After arranging the eurorack modules in a case there may be a bunch of gaps that can be filled using  blank plates.
Since eurorack is already a cost-intensive hobby<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>, I though about printing it myself with the advantage of choosing the design.</p>

<p>OpenSCAD makes it easy to parameterize a modell<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> and make it more or less transparent, depending on the code quality.</p>

<p>Some data (and ads):</p>

<ul>
<li><a href="https://prusaverse-s3-production-eu-central-1.s3.eu-central-1.amazonaws.com/media/prints/349859/stls/2973491_27f4c842-cfcd-4d28-b1a0-5465c1c251a3/eurorack_plate_noisetaeter.scad">openscad file</a></li>
<li><a href="https://www.printables.com/model/349859-parametric-eurorack-8hp-plate-noisetater">model on printables</a></li>
<li><a href="https://www.modulargrid.net/e/racks/view/1828783">current eurorack</a></li>
<li><a href="https://soundcloud.com/noise-taeter">soundcloud profile</a></li>
</ul>

<h2>Parameters</h2>

<ul>
<li><code>$HPUnits</code>: count of HP units for the width of the base plate</li>
<li>label: text on the base plate which is optimized for 8HP</li>
</ul>

<h2>Base plate</h2>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="cm">/* 
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Eurorack format is 128.5mm high (3xU) and consists of
</span></span></span><span class="line"><span class="cl"><span class="cm"> * a width with a multiple of 5.08mm (1xHP). M3 bolts 
</span></span></span><span class="line"><span class="cl"><span class="cm"> * are used
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$U3</span> <span class="o">=</span> <span class="mf">128.5</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nv">$HP1</span> <span class="o">=</span> <span class="mf">5.08</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nv">$M3r</span> <span class="o">=</span> <span class="mi">3</span><span class="o">/</span><span class="mi">2</span><span class="o">+</span><span class="mf">0.15</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$holeXPadding</span> <span class="o">=</span> <span class="mf">1.4</span><span class="o">+</span><span class="nv">$M3r</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nv">$holeYPadding</span> <span class="o">=</span> <span class="mf">1.5</span><span class="o">+</span><span class="nv">$M3r</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$HPUnits</span> <span class="o">=</span> <span class="mi">8</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nv">$depth</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nv">$width</span> <span class="o">=</span> <span class="nv">$HPUnits</span> <span class="o">*</span> <span class="nv">$HP1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$font</span><span class="o">=</span><span class="s2">&#34;</span><span class="s2">DejaVu Sans:style=Book</span><span class="s2">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm"> * base plate
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">difference</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="cm">/* plate */</span>
</span></span><span class="line"><span class="cl"><span class="nx">cube</span><span class="p">([</span><span class="nv">$width</span><span class="p">,</span><span class="nv">$U3</span><span class="p">,</span><span class="nv">$depth</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="cm">/* bolt holes */</span>
</span></span><span class="line"><span class="cl"><span class="nx">translate</span><span class="p">([</span><span class="nv">$holeXPadding</span><span class="p">,</span><span class="nv">$holeYPadding</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="nx">cylinder</span><span class="p">(</span><span class="nx">r</span><span class="o">=</span><span class="nv">$M3r</span><span class="p">,</span> <span class="nx">h</span><span class="o">=</span><span class="nv">$depth</span><span class="o">+</span><span class="mi">2</span><span class="p">,</span> <span class="nv">$fn</span><span class="o">=</span><span class="mi">40</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="nx">translate</span><span class="p">([</span><span class="nv">$width</span><span class="o">-</span><span class="p">(</span><span class="mf">5.6</span><span class="o">+</span><span class="nv">$M3r</span><span class="p">),</span><span class="nv">$holeYPadding</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="nx">cylinder</span><span class="p">(</span><span class="nx">r</span><span class="o">=</span><span class="nv">$M3r</span><span class="p">,</span> <span class="nx">h</span><span class="o">=</span><span class="nv">$depth</span><span class="o">+</span><span class="mi">2</span><span class="p">,</span> <span class="nv">$fn</span><span class="o">=</span><span class="mi">40</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="nx">translate</span><span class="p">([</span><span class="nv">$width</span><span class="o">-</span><span class="p">(</span><span class="mf">5.6</span><span class="o">+</span><span class="nv">$M3r</span><span class="p">),</span><span class="nv">$U3</span><span class="o">-</span><span class="nv">$holeYPadding</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="nx">cylinder</span><span class="p">(</span><span class="nx">r</span><span class="o">=</span><span class="nv">$M3r</span><span class="p">,</span> <span class="nx">h</span><span class="o">=</span><span class="nv">$depth</span><span class="o">+</span><span class="mi">2</span><span class="p">,</span> <span class="nv">$fn</span><span class="o">=</span><span class="mi">40</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="nx">translate</span><span class="p">([</span><span class="nv">$holeXPadding</span><span class="p">,</span><span class="nv">$U3</span><span class="o">-</span><span class="nv">$holeYPadding</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="nx">cylinder</span><span class="p">(</span><span class="nx">r</span><span class="o">=</span><span class="nv">$M3r</span><span class="p">,</span> <span class="nx">h</span><span class="o">=</span><span class="nv">$depth</span><span class="o">+</span><span class="mi">2</span><span class="p">,</span> <span class="nv">$fn</span><span class="o">=</span><span class="mi">40</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<h2>Label</h2>

<p>To make an appealing design with my artist name, I repeated it a few time horizontally and make it overlapping. As a detail, the german umlaut &lsquo;Ä&rsquo; is only repeated once and mirrored at the dots.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nx">translate</span><span class="p">([</span><span class="nv">$width</span><span class="o">-</span><span class="nv">$holeYPadding</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="nv">$depth</span><span class="o">/</span><span class="mf">1.5</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="nx">rotate</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">90</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="nx">linear_extrude</span><span class="p">(</span><span class="mf">1.5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nx">scale</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="nx">text</span><span class="p">(</span> <span class="s2">&#34;</span><span class="s2">             Ä   </span><span class="s2">&#34;</span> <span class="p">,</span><span class="nx">font</span><span class="o">=</span><span class="nv">$font</span><span class="p">,</span> <span class="nx">size</span><span class="o">=</span><span class="mf">12.25</span><span class="p">,</span> <span class="nx">direction</span><span class="o">=</span><span class="s2">&#34;</span><span class="s2">ltr</span><span class="s2">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">translate</span><span class="p">([</span><span class="nv">$holeYPadding</span><span class="o">+</span><span class="mi">2</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="nv">$depth</span><span class="o">/</span><span class="mf">1.5</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="nx">rotate</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">90</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="nx">linear_extrude</span><span class="p">(</span><span class="mf">1.5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nx">scale</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="nx">text</span><span class="p">(</span> <span class="s2">&#34;</span><span class="s2">             Ä   </span><span class="s2">&#34;</span> <span class="p">,</span><span class="nx">font</span><span class="o">=</span><span class="nv">$font</span><span class="p">,</span> <span class="nx">size</span><span class="o">=</span><span class="mf">12.25</span><span class="p">,</span> <span class="nx">direction</span><span class="o">=</span><span class="s2">&#34;</span><span class="s2">ltr</span><span class="s2">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="p">(</span><span class="nx">xOffset</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="o">:</span><span class="mi">2</span><span class="o">:</span><span class="mi">8</span><span class="p">]){</span>
</span></span><span class="line"><span class="cl">    <span class="nx">translate</span><span class="p">([</span><span class="nv">$width</span><span class="o">-</span><span class="nv">$holeYPadding</span><span class="o">*</span><span class="nx">xOffset</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="nv">$depth</span><span class="o">/</span><span class="mf">1.5</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="nx">rotate</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">90</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="nx">linear_extrude</span><span class="p">(</span><span class="mf">1.5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nx">scale</span><span class="p">([</span><span class="mf">1.125</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="nx">text</span><span class="p">(</span> <span class="s2">&#34;</span><span class="s2">NOISET  TER</span><span class="s2">&#34;</span> <span class="p">,</span><span class="nx">font</span><span class="o">=</span><span class="nv">$font</span><span class="p">,</span> <span class="nx">size</span><span class="o">=</span><span class="mi">12</span><span class="p">,</span> <span class="nx">direction</span><span class="o">=</span><span class="s2">&#34;</span><span class="s2">ltr</span><span class="s2">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<div class="footnotes">

<hr>

<ol>
<li id="fn:1"><a href="https://www.thomann.de/intl/doepfer_a_100_b8.htm">Doepfer A-100 B8</a> costs about 4.20EUR (excl. shipping) as of 31.12.2022.</li>

<li id="fn:2">I noticed, that traditional WYSIWYG-CAD-Modeller (like <a href="https://www.freecadweb.org/">FreeCAD</a> or <a href="https://www.autodesk.com/products/fusion-360/overview">Fusion 360</a>), can provide parameterization, too.</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Wed, 28 Dec 2022 07:58:20 +0100</pubDate>
    </item>
    <item>
      <title>aoc2022-5 - generic stack</title>
      <link>https://evilcookie.de/aoc2022-5---generic-stack.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>aoc2022-5 - generic stack</h1>

<p>This puzzle can be solved straight forward by implementing a stack and process the move instructions properly.
Since it is past august 2022<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>, let&rsquo;s implement it with generics to make it type-independent:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Stack</span><span class="p">[</span><span class="nx">T</span> <span class="nx">any</span><span class="p">]</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">items</span> <span class="p">[</span><span class="p">]</span><span class="nx">T</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>The first array element of <code>item</code> is the bottom of the stack, while the last item represents the top. For completeness, during initialization,
the items are read in reverse order, so a <code>PushAhead</code> function is needed which adds an item at the beginning of the array.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><span class="nx">Stack</span><span class="p">[</span><span class="nx">T</span><span class="p">]</span><span class="p">)</span> <span class="nf">PushAhead</span><span class="p">(</span><span class="nx">item</span> <span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">s</span><span class="p">.</span><span class="nx">items</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="p">[</span><span class="p">]</span><span class="nx">T</span><span class="p">{</span><span class="nx">item</span><span class="p">}</span><span class="p">,</span> <span class="nx">s</span><span class="p">.</span><span class="nx">items</span><span class="o">...</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<h2>star 1 - business as usual</h2>

<p><em>Problem</em>: The first star requires to move each item separately between the stacks.</p>

<p><em>Solution</em>: Iteratively <code>pop</code> each item from the source stack and <code>push</code> it onto the destination one.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><span class="nx">Stack</span><span class="p">[</span><span class="nx">T</span><span class="p">]</span><span class="p">)</span> <span class="nf">Push</span><span class="p">(</span><span class="nx">item</span> <span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">s</span><span class="p">.</span><span class="nx">items</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">items</span><span class="p">,</span> <span class="nx">item</span><span class="p">)</span> 
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><span class="nx">Stack</span><span class="p">[</span><span class="nx">T</span><span class="p">]</span><span class="p">)</span> <span class="nf">Pop</span><span class="p">(</span><span class="p">)</span> <span class="nx">T</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">item</span> <span class="o">:=</span> <span class="nx">s</span><span class="p">.</span><span class="nx">items</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">items</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="nx">s</span><span class="p">.</span><span class="nx">items</span> <span class="p">=</span> <span class="nx">s</span><span class="p">.</span><span class="nx">items</span><span class="p">[</span><span class="p">:</span><span class="nb">len</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">items</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">item</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<h2>star 2 - chain the supplies</h2>

<p><em>Problem</em>: All items contained in an move instruction should be pushed at once (chained) to the destination stack, remaining in the same order.</p>

<p><em>Solution</em>: <code>Pop</code> and <code>Push</code> multiple items at once via <code>PushN</code> and <code>PopN</code>.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><span class="nx">Stack</span><span class="p">[</span><span class="nx">T</span><span class="p">]</span><span class="p">)</span> <span class="nf">PushN</span><span class="p">(</span><span class="nx">items</span> <span class="p">[</span><span class="p">]</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">s</span><span class="p">.</span><span class="nx">items</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">items</span><span class="p">,</span> <span class="nx">items</span><span class="o">...</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><span class="nx">Stack</span><span class="p">[</span><span class="nx">T</span><span class="p">]</span><span class="p">)</span> <span class="nf">PopN</span><span class="p">(</span><span class="nx">l</span> <span class="kt">int</span><span class="p">)</span> <span class="p">[</span><span class="p">]</span><span class="nx">T</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">items</span> <span class="o">:=</span> <span class="nb">append</span><span class="p">(</span><span class="p">[</span><span class="p">]</span><span class="nx">T</span><span class="p">{</span><span class="p">}</span><span class="p">,</span><span class="nx">s</span><span class="p">.</span><span class="nx">items</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">items</span><span class="p">)</span><span class="o">-</span><span class="nx">l</span><span class="p">:</span><span class="p">]</span><span class="o">...</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="nx">s</span><span class="p">.</span><span class="nx">items</span> <span class="p">=</span> <span class="nx">s</span><span class="p">.</span><span class="nx">items</span><span class="p">[</span><span class="p">:</span><span class="nb">len</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">items</span><span class="p">)</span><span class="o">-</span><span class="nx">l</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">items</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<div class="footnotes">

<hr>

<ol>
<li id="fn:1">Generics got finally introduced with <a href="https://go.dev/blog/go1.19">go 1.19</a>.</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Tue, 06 Dec 2022 17:08:13 +0100</pubDate>
    </item>
    <item>
      <title>aoc2022 - reaching for the stars (again)</title>
      <link>https://evilcookie.de/aoc2022---reaching-for-the-stars-again.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>aoc22-1 - reaching for the stars (again)</h1>

<p><a href="https://adventofcode.com/2022/day/1">This year&rsquo;s AoC</a> starts right in the rain forest with a nutrition puzzle.</p>

<p><em>Problem</em>: Find the elves (one for part 1 and three for part 2) carrying the most calories.</p>

<p><em>Solution</em>:</p>

<ul>
<li>Part 1: Find the maximum sum.</li>
<li>Part 2: Store all sums sorted in an array and sum the highest three.</li>
</ul>

<h2>Stellar</h2>

<p>I created a utility lib for reoccurring problems: <a href="https://github.com/RaphaelPour/stellar">Stellar</a>. While the puzzle such as pretty trivial, extracting and generalizing the &lsquo;find-max-n-values&rsquo; approach was more interesting.</p>

<p><a href="https://github.com/RaphaelPour/aoc2022/blame/08859e206ce553f832a266ccf8a06099dc5a0175/days/01/part.go#L27">Original solution</a>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">part2</span><span class="p">(</span><span class="nx">data</span> <span class="p">[</span><span class="p">]</span><span class="kt">string</span><span class="p">)</span> <span class="kt">int</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">calories</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="p">[</span><span class="p">]</span><span class="kt">int</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// ...add all sums to the calories array 
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">  <span class="nx">sort</span><span class="p">.</span><span class="nf">Ints</span><span class="p">(</span><span class="nx">calories</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="nx">l</span> <span class="o">:=</span> <span class="nb">len</span><span class="p">(</span><span class="nx">calories</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">calories</span><span class="p">[</span><span class="nx">l</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="nx">calories</span><span class="p">[</span><span class="nx">l</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="nx">calories</span><span class="p">[</span><span class="nx">l</span><span class="o">-</span><span class="mi">3</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p><a href="https://github.com/RaphaelPour/stellar/blob/156793ae3fc65ebcba139babf0a6e8b021215f79/math/math.go#L71">Generic max-n solution for Stellar</a>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nx">MaxN</span><span class="p">[</span><span class="nx">T</span> <span class="nx">Number</span><span class="p">]</span><span class="p">(</span><span class="nx">nums</span> <span class="p">[</span><span class="p">]</span><span class="nx">T</span><span class="p">,</span> <span class="nx">n</span> <span class="kt">int</span><span class="p">)</span> <span class="p">[</span><span class="p">]</span><span class="nx">T</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="nx">nums</span><span class="p">)</span> <span class="p">&lt;</span> <span class="nx">n</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="kc">nil</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">sort</span><span class="p">.</span><span class="nf">Slice</span><span class="p">(</span><span class="nx">nums</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">nums</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="p">&gt;</span> <span class="nx">nums</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="nx">n</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p><a href="https://github.com/RaphaelPour/aoc2022/blob/0eb2f3f7a2a5dbde69f4ece62841c3c788e3983b/days/01/part.go#L11">Solution using MaxN</a>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">maxCalories</span><span class="p">(</span><span class="nx">data</span> <span class="p">[</span><span class="p">]</span><span class="kt">string</span><span class="p">,</span> <span class="nx">n</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">int</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">calories</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="p">[</span><span class="p">]</span><span class="kt">int</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="nx">currentCalories</span> <span class="o">:=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">row</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">data</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="nx">row</span> <span class="o">!=</span> <span class="s">&#34;&#34;</span> <span class="o">&amp;&amp;</span> <span class="nx">i</span> <span class="p">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">currentCalories</span> <span class="o">+=</span> <span class="nx">strings</span><span class="p">.</span><span class="nf">ToInt</span><span class="p">(</span><span class="nx">row</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="k">continue</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">calories</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">calories</span><span class="p">,</span> <span class="nx">currentCalories</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nx">currentCalories</span> <span class="p">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">math</span><span class="p">.</span><span class="nf">Sum</span><span class="p">(</span><span class="nx">math</span><span class="p">.</span><span class="nf">MaxN</span><span class="p">(</span><span class="nx">calories</span><span class="p">,</span> <span class="nx">n</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>For completeness, I also added <a href="https://github.com/RaphaelPour/stellar/blob/main/math/math.go#L80">MinN</a> by inverting the sort comparison:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nx">MinN</span><span class="p">[</span><span class="nx">T</span> <span class="nx">Number</span><span class="p">]</span><span class="p">(</span><span class="nx">nums</span> <span class="p">[</span><span class="p">]</span><span class="nx">T</span><span class="p">,</span> <span class="nx">n</span> <span class="kt">int</span><span class="p">)</span> <span class="p">[</span><span class="p">]</span><span class="nx">T</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="nx">nums</span><span class="p">)</span> <span class="p">&lt;</span> <span class="nx">n</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="kc">nil</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">sort</span><span class="p">.</span><span class="nf">Slice</span><span class="p">(</span><span class="nx">nums</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">nums</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="p">&lt;</span> <span class="nx">nums</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="nx">n</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Thu, 01 Dec 2022 08:50:49 +0100</pubDate>
    </item>
    <item>
      <title>rework of verbose</title>
      <link>https://evilcookie.de/rework-of-verbose.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Rework of verbose</h1>

<p><a href="verbose.raphaelpour.de">Verbose</a> is my vocabulary web service to memorize and look up new and interesting english words. Since I&rsquo;m continuously containerize my services , I stumpled across this service depending on nginx, php and mysql. Verbose was intended to be a non-fancy and simple project, so I rather thought about
the requirements and reworked a proper docker-native solution than running a bunch of containers.</p>

<p><img src="rework-of-verbose_verbose.png"/></p>

<h2>History</h2>

<p>I started to read english books<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> to improve my language skills. But as the amount of new words grew, it felt like reading progress slowed down continously due to repeated look ups and high amount of new words to learn.</p>

<p>At first I cached all the lookups in a text file, then only added interesting, elegant or notable words to lower the total amount. Later I built a web service that simply provides an form to add new words and showed a list of all words so far. A text file could&rsquo;ve been enough, but you know, having a project with a real use-case gives a developer computer science student the feeling of doing something that matters rather than just implementing demos or theoretical/fictional use-cases.</p>

<p>There were tons of features that could be nice for the service. But the goal of this project was to focus on the main use-case and avoid <a href="https://buttondown.email/hillelwayne/archive/edge-case-poisoning/">edge case posoning</a>. I had literally thousand of software projects in my developer life but only a hand full grew to something noteworthy or actually useful. Although it was hard to give up (or let&rsquo;s say postpone) all the exciting ideas and just implement an <a href="https://en.wikipedia.org/wiki/Minimum_viable_product">MVP</a>, the long-term experience of having a useful tool where <code>time of use &gt;&gt; time of development</code> was great.</p>

<p>There were only two optional features added: word-of-the-pageload and count of words at the bottom.</p>

<h2>Original setup</h2>

<p>The <a href="verbose.raphaelpour.de">web site</a> was built with <a href="https://getbootstrap.com/">bootstrap</a> to quickly create an appealing look without investing too much time with CSS. The backend was made with PHP providing the translations from the <a href="https://mariadb.org/">MariaDB</a> database to the frontend and storing new once from the form secured with <a href="https://en.wikipedia.org/wiki/.htaccess">htaccess</a>.</p>

<p>The backend only had two routes:</p>

<ul>
<li><code>GET /</code>: view web site with all translations</li>
<li><code>POST add.php</code>: add a new translation</li>
</ul>

<p>The database schema was fairly simple:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">CREATE</span><span class="w"> </span><span class="k">TABLE</span><span class="w"> </span><span class="o">`</span><span class="n">vocabulary</span><span class="o">`</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="o">`</span><span class="n">id</span><span class="o">`</span><span class="w"> </span><span class="nb">int</span><span class="p">(</span><span class="mi">11</span><span class="p">)</span><span class="w"> </span><span class="k">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="w"> </span><span class="n">AUTO_INCREMENT</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="o">`</span><span class="n">de</span><span class="o">`</span><span class="w"> </span><span class="nb">varchar</span><span class="p">(</span><span class="mi">255</span><span class="p">)</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="o">`</span><span class="n">en</span><span class="o">`</span><span class="w"> </span><span class="nb">varchar</span><span class="p">(</span><span class="mi">255</span><span class="p">)</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="o">`</span><span class="n">added</span><span class="o">`</span><span class="w"> </span><span class="k">timestamp</span><span class="w"> </span><span class="k">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="k">CURRENT_TIMESTAMP</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="o">`</span><span class="n">id</span><span class="o">`</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="w"> </span><span class="n">ENGINE</span><span class="o">=</span><span class="n">InnoDB</span><span class="w"> </span><span class="n">AUTO_INCREMENT</span><span class="o">=</span><span class="mi">0</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="n">CHARSET</span><span class="o">=</span><span class="n">utf8</span><span class="p">;</span><span class="w">
</span></span></span></code></pre>
<p>The old setup can be found <a href="https://github.com/RaphaelPour/verbose/tree/e17213823080527b3b3f1527f98099d93cba9b04">here</a>.</p>

<h2>Reworked setup</h2>

<p>The frontend remained the same. The backend was completely replaced with a containerized go binary providing the web site plus a REST-API for using the translations programatically. The relational database table was replaced with a simple data structure which is un-/marshalled<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> to JSON and stored within a docker volume. Generally it is not a good idea to use a file-based storage backend for a public available web service when implemented naively. I/O is very time consuming compared by having the data in-memory or requesting a service that has it in-memory. But on average I view it once a day and add only one word per month. Reading the file only on start up and writing it only on adding a new word to get rid of a database server was a fair compromise.</p>

<p>Data structure:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Translation</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Words</span> <span class="p">[</span><span class="p">]</span><span class="kt">string</span> <span class="s">`</span><span class="s">json:&#34;words&#34;</span><span class="s">`</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Vocabulary</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Entries</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="nx">Translation</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>Snipptet from the JSON file:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;Fun&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;words&#34;</span><span class="p">:</span> <span class="p">[</span> <span class="s2">&#34;Spaß&#34;</span> <span class="p">]</span> <span class="p">}</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;adorable&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;words&#34;</span><span class="p">:</span> <span class="p">[</span> <span class="s2">&#34;bezaubernd&#34;</span><span class="p">,</span> <span class="s2">&#34;liebenswert&#34;</span> <span class="p">]</span> <span class="p">}</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;done&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;words&#34;</span><span class="p">:</span> <span class="p">[</span> <span class="s2">&#34;fertig&#34;</span> <span class="p">]</span> <span class="p">}</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;verbose&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;words&#34;</span><span class="p">:</span> <span class="p">[</span> <span class="s2">&#34;quasseln&#34;</span> <span class="p">]</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>Routes:</p>

<ul>
<li>Web site:

<ul>
<li><code>GET /</code>: view web site with all translations</li>
<li><code>POST /new</code>: add new translation</li>
</ul></li>
<li>REST-API:

<ul>
<li><code>GET /api/v1/words</code>: get all words</li>
<li><code>GET /api/v1/words/&lt;en word</code>: get a translation for a given english word</li>
<li><code>POST /api/v1/words/&lt;en word&gt;</code>: add new translation</li>
</ul></li>
</ul>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1"><a href="https://www.goodreads.com/book/show/13.The_Ultimate_Hitchhiker_s_Guide_to_the_Galaxy">Hitchhiker&rsquo;s Guide to the galaxy from Douglas Adams</a> and <a href="https://www.goodreads.com/book/show/52696249-animal-farm">Animal Farm by George Orwell</a></li>

<li id="fn:2">un-/marshalling are the <a href="https://go.dev/blog/json">go equivalent</a> of de-/serialization of data</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Fri, 09 Sep 2022 12:54:08 +0200</pubDate>
    </item>
    <item>
      <title>godot wild jam 48</title>
      <link>https://evilcookie.de/godot-wild-jam-48.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>godot wild jam 48 - crack in the shell</h1>

<p><a href="https://github.com/Tch1b0">Johannes</a> and I participated at the <a href="https://itch.io/jam/godot-wild-jam-48">godot wild jam 48</a> having the theme <em>moon</em>.
Our submission is <a href="https://itch.io/jam/godot-wild-jam-48/rate/1670064">Crack in the shell</a>: <em>A race against time
in space. Will the oxygen last to get back to the base?</em></p>

<ul>
<li><a href="https://itch.io/jam/godot-wild-jam-48/rate/1670064">jam submission</a></li>
<li><a href="https://tch1b0.itch.io/crack-in-the-shell">game</a></li>
<li><a href="https://github.com/Glow-Project/gwj-48">source</a></li>
<li>soundtracks: <a href="https://soundcloud.com/noise-taeter/welcome-to-the-moon">Welcome to the moon</a>, <a href="https://soundcloud.com/noise-taeter/wrong-path">Wrong path</a></li>
</ul>

<h2>Internals</h2>

<h3>Dall-E Logo</h3>

<p>Since Johannes has a beta-subscription for Dall-E, we were a bit curious and tried to generate interesting logos.
We ended up with <em>Closeup of an astronaut helmet flying towards a black hole, 8k, award winning</em> and chose <a href="https://labs.openai.com/s/691FEP4ybAx8eZQuc726qHq1">the third one</a>:</p>

<p><img src="godot-wild-jam-48_dalle_astronaut.png"/></p>

<h3>Atmosphere</h3>

<p>We wanted to make an immersive 3D game on the moon. But we knew our abilities creating a convincing atmosphere are limited. So we tried creating immersion by balancing <em>sensory overload</em> with <em>controlled guiding</em>. Lastly the sound- and audio design helped us to gain more space aesthetics.</p>

<h4>Sensory overload</h4>

<p><em>Intro, breathing noises, alarm, red blinking lights, &ldquo;warning, oxygen tank damaged&rdquo;.</em></p>

<p>You need to survive while oxygen is almost empty and without any orientation. Basically an oversimplified labyrinth with timer.</p>

<h4>Controlled guiding</h4>

<p><em>&ldquo;Mind the crater, if you get in, there is no way out.&rdquo;</em></p>

<p>With voice lines from the helmet AI and the mate from the base, the player has constant feedback about beeing on track and <em>doing the right things</em>. Next we had a satellite map that can be shown live on-demand. The satellite itself is visible in the sky by his blinking lights giving the player a constant safety net.</p>

<h4>Sound design</h4>

<p>The atmosphere starts within the intro: heavy breathing. It gives the player an immediate hint what this game is about. The crack sound is synchronized with the title to point out the challenge.</p>

<p>The scene itself starts with an alarm and an AI voice. I used Ableton Live to chain some effects:</p>

<ul>
<li>a raw natural voice recorded with my Shure-SM58</li>
<li>vocoder: make the sound more robotic</li>
<li>chorus: add some warmth and vibrato</li>
<li>high pass filter: low frequencies make AI vocals (think of Siri or Alexa) dirty and feel &ldquo;rumbly&rdquo;, filtering them out help to clearify the voice</li>
<li>duplicate channel and slighetly add an offset to the second (~100ms): add a manual &ldquo;flanger&rdquo; or delayesque sound, this will add some <a href="https://www.youtube.com/watch?v=q5kkwermfs4">glados vibes</a></li>
</ul>

<p>Next to the AI, the mate tries to communicate with the player via radio transmission. With some more effects this radio vibe can be added within godot<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>:</p>

<ul>
<li>again my voice</li>
<li>distortion + limiter, let the vocal clip and lower the volume afterwards down immediately: add a rich palette of overtones known from <a href="https://www.youtube.com/watch?v=DejhGSEu8wk&amp;t=549s">famous space audio logs</a>. This will make the vocals quickly unclear and must be gently tweaked.</li>
<li>band pass filter: cut most of the low frequencies (likewise to the AI) but also some high ones. This will immitate the highly limited bandwith of radio transmissions in space.</li>
</ul>

<p><img src="godot-wild-jam-48_audio_busses.png"/><img src="godot-wild-jam-48_bandpass.png"/></p>

<h4>Audio design</h4>

<p>How does the moon sound like? This is easy in reality. No atmosphere means -&gt; no air were sound can travel -&gt; silence. But cinematographically a sub bass consisting of just a sine wave with sweeping low pass filter and volume adds some depth to the scene. This can be heared in the track <a href="https://soundcloud.com/noise-taeter/welcome-to-the-moon">Welcome to the moon</a>.</p>

<p>When the oxygen tank is almost empty, the more dramatic track <a href="https://soundcloud.com/noise-taeter/wrong-path">Wrong path</a> adds promptly more tension. Starting with gentle and quiet detuned bells, adding a ascending &ldquo;staried&rdquo; loop inspired from the matrix movie soundtrack. It will envolve, adding tension and finally drop when the oxygen tank is empty.</p>

<p>Finally when the player reaches the base in time, some pads with bunch of chained choruses reward the player and the mate speakes without any effect in his natural voice.</p>

<h3>Satellite map with viewports</h3>

<p>The satellite is a model with a camera facing towards the center point of the map. The rotation is made simply by rotating the center point. The camera is then mapped to a viewport on a tablet model that can be toggled by the player.</p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">I originally did the effect chain in Ableton Live, too. But since I couldn&rsquo;t work on the jam on the weekend, I did the chain within godot, so I simply could Johannes send raw voice lines via Telegram.</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Mon, 22 Aug 2022 12:37:13 +0200</pubDate>
    </item>
    <item>
      <title>bye,bye old blog raphaelpour.de</title>
      <link>https://evilcookie.de/byebye-old-blog-raphaelpourde.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>bye bye old blog raphaelpour.de</h1>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">&gt; vim /etc/nginx/nginx.conf <span class="o">&amp;&amp;</span> systemctl restart nginx <span class="c1"># redirect raphaelpour.de to evilcookie.de</span>
</span></span><span class="line"><span class="cl">&gt; <span class="nb">echo</span> <span class="s2">&#34;DROP DATABASE wordpress;&#34;</span> <span class="p">|</span> mysql
</span></span><span class="line"><span class="cl">&gt; rm -rf /var/www/wordpress
</span></span></code></pre>
<p>It was time to let go of my longest running blog so far. Although archive.org dates back
the first occurrence to <a href="https://web.archive.org/web/20160110001415/http://raphaelpour.de/">2016</a>, the
impressum says 2015.</p>

<p>I migrated the imho best posts to <code>$this</code> new blog:</p>

<ul>
<li><a href="saving-goats-with-prolog.html">saving goats with prolog</a></li>
<li><a href="debugging-c-with-gdb.html">debugging c with gdb</a></li>
<li><a href="inside-a-c-float.html">inside a c float</a></li>
</ul>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Mon, 01 Aug 2022 19:01:48 +0200</pubDate>
    </item>
    <item>
      <title>Inside a C float</title>
      <link>https://evilcookie.de/inside-a-c-float.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Inside a C float</h1>

<h2>Preface</h2>

<p>This post was originally published in my old blog raphaelpour.de on 12.01.2018.
This was a great introduction of how memory gets intrpreted within a type system
and how to look behind the magic. I&rsquo;ve added the part <a href="#ieee-754-compoents">IEEE 754
components</a>.</p>

<h2>Article</h2>

<p>Handling with floats can  be irritating while it is one of the non-integral datatypes. This means that the displayed value (e.g. via
<code>printf(&quot;%f&quot;,somefloat)</code>)  is different to the one actualy stored in memory. This is caused by <a href="http://ieeexplore.ieee.org/servlet/opac?punumber=2355">IEEE754</a>.</p>

<p>To get the real values we have to go inside the float. A cast wouldn&rsquo;t do the
job, because it would just turn a 3.1415 into 3<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>.
C has a very nice keyword which can help us: <code>union</code>
Instead of casting datatypes, we just map different variables with different datatypes to the exact same memory.</p>

<p>The following four-liner will do the trick for us.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">union</span> <span class="n">floatDbg</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">float</span> <span class="n">f</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">c</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="p">;</span>
</span></span></code></pre>
<p>Now we can access every byte of the float and get the real value. To know what the values are telling us, we would need to know the IEEE754 Algorithm. But that is another story.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">union</span> <span class="n">floatDbg</span> <span class="n">dbg</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">dbg</span><span class="p">.</span><span class="n">f</span> <span class="o">=</span> <span class="mf">13.37</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// decimal output
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">%.2f -&gt; %d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">f</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="p">)</span><span class="p">;</span> 
</span></span><span class="line"><span class="cl"><span class="c1">// out: 13.37 -&gt; 133 235 85 65
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// hex output
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">%.2f -&gt; %x %x %x %x</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">f</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="c1">// out: 13.37 -&gt; 85 eb 55 41
</span></span></span></code></pre>
<h3>IEEE 754 compnents</h3>

<p>On my little endian machine, we can even get the actual components of the IEE754
float. Bitmasks help to limit the amount of bits we want to map into a struct
field:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="k">union</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">float</span> <span class="n">f</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">c</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="kt">unsigned</span> <span class="nl">fraction</span><span class="p">:</span><span class="mi">23</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="kt">unsigned</span> <span class="nl">exponent</span><span class="p">:</span><span class="mi">8</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="kt">unsigned</span> <span class="nl">sign</span><span class="p">:</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="n">floatDbg</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">dump</span><span class="p">(</span><span class="n">floatDbg</span> <span class="n">dbg</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span> <span class="n">argv</span><span class="p">[</span><span class="p">]</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">floatDbg</span> <span class="n">dbg</span><span class="p">,</span><span class="n">dbg2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">dbg</span><span class="p">.</span><span class="n">f</span> <span class="o">=</span> <span class="mf">13.37</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">--[ raw ]--</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">   float: %.2f</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">f</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">   bytes: %02x %02x %02x %02x</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">     bin: %08b %08b %08b %08b</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">c</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">--[ iee754 components] --</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">    sign: %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">sign</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">exponent: %d (real=%d)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">exponent</span><span class="o">-</span><span class="mi">127</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">exponent</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">fraction: %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">dbg</span><span class="p">.</span><span class="n">fraction</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/* out:
</span></span></span><span class="line"><span class="cl"><span class="cm"> * --[ raw ]--
</span></span></span><span class="line"><span class="cl"><span class="cm"> *    float: 13.37
</span></span></span><span class="line"><span class="cl"><span class="cm"> *    bytes: 41 55 eb 85
</span></span></span><span class="line"><span class="cl"><span class="cm"> *      bin: 01000001 01010101 11101011 10000101
</span></span></span><span class="line"><span class="cl"><span class="cm"> * 
</span></span></span><span class="line"><span class="cl"><span class="cm"> * --[ iee754 components] --
</span></span></span><span class="line"><span class="cl"><span class="cm"> *     sign: 0
</span></span></span><span class="line"><span class="cl"><span class="cm"> * exponent: 3 (real=130)
</span></span></span><span class="line"><span class="cl"><span class="cm"> * fraction: 5630853
</span></span></span></code></pre>
<div class="footnotes">

<hr>

<ol>
<li id="fn:1">this turns only out to be true if you are living in the <a href="https://en.wikipedia.org/wiki/Indiana_Pi_Bill">us state Indiana</a></li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Wed, 27 Jul 2022 15:00:13 +0200</pubDate>
    </item>
    <item>
      <title>debugging c with gdb</title>
      <link>https://evilcookie.de/debugging-c-with-gdb.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Debugging C with gdb</h1>

<h2>Preface</h2>

<p>This post was originally posted in my old blog raphaelpour.de on 06.02.2018. This is probably my most personally used blog post. Once in a while I
need to investigate a coredump that got collected by <code>systemd-coredump</code>. Although the post covers only the tip of the debugging iceberg, it&rsquo;s at least the tip from where you can start walking down.</p>

<h2>Introduction</h2>

<p>As long as the gcc tells you whats wrong (including the <code>-Wall</code> flag) you can at least barely locate the source of the error. What about <em>Segmentation Faults</em> which are hard to detect during compilation time? The <a href="https://www.gnu.org/software/gdb/">GNU Debugger</a> (short gdb) may give you a clue!</p>

<p>Gdb is a command line debugger for investigating binaries. Especially when the binary was compiled with debug information, the debugger can tell us a bit more about its state.</p>

<h2>Starting over with segmentation faults</h2>

<p>For example look at the following code which provokes a segmentation faults by writing to unallocated memory.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdlib.h&gt; </span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;string.h&gt; </span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdio.h&gt; </span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span> 
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">getLyrics</span><span class="p">(</span><span class="kt">char</span><span class="o">*</span> <span class="n">lyricBuffer</span><span class="p">)</span><span class="p">{</span> 
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">segFaultLyrics</span> <span class="o">=</span> <span class="sa"></span><span class="s">&#34;</span><span class="s">SegFault, SegFault! Whatcha gonna do? Whatcha gonna do when I come for you?</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">memcpy</span><span class="p">(</span><span class="n">lyricBuffer</span><span class="p">,</span> <span class="n">segFaultLyrics</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span><span class="n">segFaultLyrics</span><span class="p">)</span><span class="p">)</span><span class="p">;</span> 
</span></span><span class="line"><span class="cl"><span class="p">}</span> 
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span> 
</span></span><span class="line"><span class="cl"><span class="p">{</span> 
</span></span><span class="line"><span class="cl"> <span class="kt">char</span><span class="o">*</span> <span class="n">lyrics</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> 
</span></span><span class="line"><span class="cl"> <span class="n">getLyrics</span><span class="p">(</span><span class="n">lyrics</span><span class="p">)</span><span class="p">;</span> 
</span></span><span class="line"><span class="cl"> <span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">%s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">lyrics</span><span class="p">)</span><span class="p">;</span>                                                                                   
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>Let&rsquo;s compile it with gcc and see what happens on execute.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ gcc -Wall debugme1.c -o debugme1
</span></span><span class="line"><span class="cl">$ ./debugme1
</span></span><span class="line"><span class="cl">Segmentation fault <span class="o">(</span>core dumped<span class="o">)</span>
</span></span></code></pre>
<p>Gcc didn&rsquo;t complain anything, even with the <code>-Wall</code> flag.</p>

<p>In order to start over with the gdb, we have to compile our program with debug information. This can be achieved by adding the <code>-g</code> flag to the gcc parameter list.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nv">$gcc</span> -Wall debugme1.c -g -o debugme1
</span></span><span class="line"><span class="cl"><span class="nv">$gdb</span> debugme1
</span></span><span class="line"><span class="cl">Reading symbols from debugme1...done.
</span></span><span class="line"><span class="cl"><span class="o">(</span>gdb<span class="o">)</span> r
</span></span><span class="line"><span class="cl">Starting program: ~/debugme/debugme1
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Program received signal SIGSEGV, Segmentation fault.
</span></span><span class="line"><span class="cl">__memcpy_avx_unaligned <span class="o">(</span><span class="o">)</span> at ../sysdeps/x86_64/multiarch/memcpy-avx-unaligned.S:100
</span></span><span class="line"><span class="cl"><span class="m">100</span>     ../sysdeps/x86_64/multiarch/memcpy-avx-unaligned.S: No such file or directory.
</span></span></code></pre>
<p>As you can see, the gdb tells you which library-function causes the error. What we can&rsquo;t see is the location of this faulty library-function call in our source code.  The No such file or directory error can be ignored with the assumption that our call of this function is wrong and not the original source<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>.
This can be accomplished with the gdb command <code>bt</code> (short for back-trace).</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">(gdb) bt
</span></span><span class="line"><span class="cl">#0 __memcpy_avx_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-avx-unaligned.S:100
</span></span><span class="line"><span class="cl">#1 0x000000000040060c in getLyrics (lyricBuffer=0x0) at debugme1.c:8
</span></span><span class="line"><span class="cl">#2 0x000000000040062b in main () at debugme1.c:14
</span></span></code></pre>
<p>The back trace will print the last call stack where the faulty function is on the top. In our example we have to look at the function <code>getLyrics</code> in line 8 which will be the memcpy call.</p>

<p>## Division by zero</p>

<p>Imagine you worked out a fancy formula which solve a certain problem. Especially when you use fractions you have to take care of the range of the input values.
The following code will implement a formula which doesn&rsquo;t care about the input value. The compiler doesn&rsquo;t either.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdio.h&gt;            </span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdlib.h&gt;           </span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>                              
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">magicFormula</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>                             
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">a</span><span class="o">/</span><span class="n">b</span><span class="p">;</span>               
</span></span><span class="line"><span class="cl"><span class="p">}</span>                             
</span></span><span class="line"><span class="cl">                              
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span>                    
</span></span><span class="line"><span class="cl"><span class="p">{</span>                             
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">magicFormula</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">printf</span><span class="p">(</span><span class="sa"></span><span class="s">&#34;</span><span class="s">%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span><span class="n">n</span><span class="p">)</span><span class="p">;</span>         
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>This will cause a <em>floating point exception</em>. This isn&rsquo;t directly a <em>divison-by-zero</em> bug. If you would change the datatype from into float , this operation would be result inf for infinity. But a float  with the value inf can&rsquo;t be casted into an integer. However, we will ask the gdb if he can help us out again.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$gdb debugme2
</span></span><span class="line"><span class="cl">Reading symbols from debugme2...done.
</span></span><span class="line"><span class="cl">(gdb) r
</span></span><span class="line"><span class="cl">Starting program: ~/debugme/debugme2
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Program received signal SIGFPE, Arithmetic exception.
</span></span><span class="line"><span class="cl">0x0000000000400534 in magicFormula (a=1, b=0) at debugme2.c:6
</span></span><span class="line"><span class="cl">6           return a/b;
</span></span></code></pre>
<p>In order to see more than the faulty line, we can use the gdb-command <code>l</code> to list. This will maybe give us the context and a hint why the method magicFormula failed with <code>a=1</code> and <code>b=0</code></p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="p">(</span><span class="n">gdb</span><span class="p">)</span> <span class="n">l</span>
</span></span><span class="line"><span class="cl"><span class="mi">1</span>       <span class="err">#</span><span class="n">include</span> <span class="o">&lt;</span><span class="n">stdio</span><span class="p">.</span><span class="n">h</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="mi">2</span>       <span class="err">#</span><span class="n">include</span> <span class="o">&lt;</span><span class="n">stdlib</span><span class="p">.</span><span class="n">h</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="mi">3</span>
</span></span><span class="line"><span class="cl"><span class="mi">4</span>       <span class="kt">int</span> <span class="n">magicFormula</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="mi">5</span>       <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="mi">6</span>           <span class="k">return</span> <span class="n">a</span><span class="o">/</span><span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="mi">7</span>       <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="mi">8</span>
</span></span><span class="line"><span class="cl"><span class="mi">9</span>       <span class="kt">int</span> <span class="n">main</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="mi">10</span>      <span class="p">{</span>
</span></span></code></pre>
<h2>Tips &lsquo;n&rsquo; Tricks</h2>

<ul>
<li>your application <code>foo</code> needs arguments <code>bar</code> and <code>bbar</code>? Try this: <code>gdb --args foo bar bbar</code></li>
<li>more debug information with the gcc flag <code>-g3</code></li>
<li>there is a console-based gui included in gdb which can be opened with <code>gdb -tui</code></li>
<li><code>strip &lt;binary&gt;</code>  will remove all debug information which the gcc has included into your binary</li>
<li>generate gdb-friendly debug information <a href="https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html">with gcc flag</a>  <code>-ggdb</code></li>
</ul>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">if you think the memcpy is wrong and want to debug it, take a look at <a href="https://stackoverflow.com/a/13979032">this SO Post</a>.</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Wed, 27 Jul 2022 12:18:58 +0200</pubDate>
    </item>
    <item>
      <title>saving goats with prolog</title>
      <link>https://evilcookie.de/saving-goats-with-prolog.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Saving Goats with Prolog</h1>

<h2>Preface</h2>

<p>This post was originally posted in my old blog raphaelpour.de on 09.02.2018.
Retrospectively this post is a pretty good insight of my artifical intelligence studies back then.</p>

<p><img src="saving-goats-with-prolog_goatprolog.png"/></p>

<p>Spoiler: You might have guessed it already&hellip; you won’t see any real goat in here<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>.
This is about a planning problem and how we can solve it using Prolog. A planning
ploblem could be for example a game or a more or less complex task. You know the
starting and goal state and the rules to go from one state to another, but not if
and how many states are between<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>.</p>

<p>I will describe the problem, break it down to Prolog and solve it with an Iterative Depth Search (IDS).</p>

<h2>Where are the Goats now?</h2>

<p>Okay, first things first: There is only one goat. And this goat can only survive
under specific circumstances.</p>

<p>Imagine you are a ferryman, going from one riverside to the other. Next to some
rickety grandmas (which are taking the ferry almost every day to keep themselves busy)
and a bunch of heavily interested tourists (not interested at all), you were
commissioned to transport three things from riverside A to riverside B:</p>

<ul>
<li>goat</li>
<li>cabbage</li>
<li>wolf</li>
</ul>

<p>Rules:</p>

<ul>
<li>only one thing at a time transportable</li>
<li>goat eats Cabbage</li>
<li>wolf eats Goat</li>
</ul>

<p>How can the ferryman transport all three things from riverside A to B?</p>

<h2>Breakdown of the Problem</h2>

<p>Imagine playing a game which you never played before. The rules are clear but it
might not be clear which strategy is key. The best strategy in the first place
might be guessing or do things in a specific order to gain experience. To make the
things more formal: When I have situation X, which action/move/&hellip; leads me to the
goal situation?</p>

<p>Same thing in Prolog. We can implement the rules, but we need an algorithm which
tries to find a solution. In order to find something, you have to search.
While we have no heuristic (or in our game example: we have no experience) to rank
all current possible actions by shortest distance to the goal, we need an
<em>uninformed search algorithm</em>.</p>

<p>The most effective one is the <em>Iterative Depth Search</em> (IDS). It combines the
positive aspects of the breadth-first- such as the depth-first search and
is therefore optimal (finds always the shortest path).</p>

<p>The search algorithm can walk through a graph where the nodes are states and the
edges are the action/move/&hellip; you have to do in order to go from one state to an other.</p>

<p>In our example, ervery state contains the location of four things: Goat, Cabbage, Wolf
and Ferryman. Every thing can be either on riverside A or B. As a result every state
is a combination of the location of all four things. The Rules are telling us which actions
are allowed and which not.</p>

<p>Let’s imagine how a search graph would look alike (see graphic below). Each node is a state
and each edge is an action.</p>

<p>But this graph has some faulty edges which are not following our rules. Guess which!</p>

<p><img src="saving-goats-with-prolog_goatprolog_graph1.png"/></p>

<p>The following edges are wrong:</p>

<ul>
<li>edge 1: The ferryman is allowed to go alone, but either the goat is eating the cabbage
or the wolf is eating the goat (or both).</li>
<li>edge 3: The wolf is eating the goat.</li>
<li>edge 4: The goat is eating the cabbage.</li>
</ul>

<h2>The Prolog Program</h2>

<p>In order to make use of the search algorithm, we need to put every state into a List describing
the location of each thing: <code>[goat, cabbage, wolf, ferryman]</code>. We start off by describing the
start and goal state:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nf">start</span><span class="p">(</span><span class="p">[</span><span class="s">a</span><span class="p">,</span><span class="s">a</span><span class="p">,</span><span class="s">a</span><span class="p">,</span><span class="s">a</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl"><span class="nf">goal</span><span class="p">(</span><span class="p">[</span><span class="s">b</span><span class="p">,</span><span class="s">b</span><span class="p">,</span><span class="s">b</span><span class="p">,</span><span class="s">b</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span></code></pre>
<p>Next we create a transition allowing the ferryman to go alone from riverside A to riverside B.
This is accomplished by only allowing the ferryman variable to change the location, all other
variables have to stay where they are.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nf">transition0</span><span class="p">(</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="s">a</span><span class="p">]</span><span class="p">,</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="s">b</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span></code></pre>
<p>Let’s add all other transitions.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nf">transition0</span><span class="p">(</span><span class="p">[</span><span class="s">a</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="s">a</span><span class="p">]</span><span class="p">,</span><span class="p">[</span><span class="s">b</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="s">b</span><span class="p">]</span><span class="p">)</span><span class="p">.</span> 
</span></span><span class="line"><span class="cl"><span class="nf">transition0</span><span class="p">(</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="s">a</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="s">a</span><span class="p">]</span><span class="p">,</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="s">b</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="s">b</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl"><span class="nf">transition0</span><span class="p">(</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="s">a</span><span class="p">,</span><span class="s">a</span><span class="p">]</span><span class="p">,</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="s">b</span><span class="p">,</span><span class="s">b</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span></code></pre>
<p>This Transition goes only in one direction. Let’s make it symmetric by adding a new
transition predicate.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nf">transition</span><span class="p">(</span><span class="nv">X</span><span class="p">,</span><span class="nv">Y</span><span class="p">)</span> <span class="p">:-</span> <span class="nf">transition0</span><span class="p">(</span><span class="nv">X</span><span class="p">,</span><span class="nv">Y</span><span class="p">)</span><span class="p">;</span><span class="nf">transition0</span><span class="p">(</span><span class="nv">Y</span><span class="p">,</span><span class="nv">X</span><span class="p">)</span><span class="p">.</span>
</span></span></code></pre>
<p>The reason why I called the predicate transition and not rule is that the most rules
are missing. We actually can move from A to B with only on thing at a time, but it is
allowed to keep for example the wolf and the goat alone.
We need to validate each state in order to tell if the transition is allowed or not.
Let’s make a new predicate for the validation and add it later to our symmetric transition.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nf">valid</span><span class="p">(</span><span class="p">[</span><span class="nv">F</span><span class="p">,</span><span class="k">_</span><span class="p">,</span><span class="k">_</span><span class="p">,</span><span class="nv">F</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl"><span class="nf">valid</span><span class="p">(</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="k">_</span><span class="p">]</span><span class="p">)</span> <span class="p">:-</span> <span class="nv">G</span> <span class="s">\==</span> <span class="nv">C</span><span class="p">,</span> <span class="nv">G</span> <span class="s">\==</span><span class="nv">W</span><span class="p">.</span>
</span></span></code></pre>
<p>This predicate takes a single state and checks if:</p>

<ul>
<li>The Goat is with the ferryman -&gt; Everything is okay because the wolf doesn’t harm the cabbage</li>
<li>The Goat doesn’t share its location with either wolf or cabbage. We can exclude the ferryman here while we took care of him in the rule above</li>
</ul>

<p>Now we can add the valid predicate to our transition.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nf">transition</span><span class="p">(</span><span class="nv">X</span><span class="p">,</span><span class="nv">Y</span><span class="p">)</span> <span class="p">:-</span> <span class="p">(</span><span class="nf">transition0</span><span class="p">(</span><span class="nv">X</span><span class="p">,</span><span class="nv">Y</span><span class="p">)</span><span class="p">;</span><span class="nf">transition0</span><span class="p">(</span><span class="nv">Y</span><span class="p">,</span><span class="nv">X</span><span class="p">)</span><span class="p">)</span><span class="p">,</span> <span class="nf">valid</span><span class="p">(</span><span class="nv">X</span><span class="p">)</span><span class="p">,</span><span class="nf">valid</span><span class="p">(</span><span class="nv">Y</span><span class="p">)</span><span class="p">.</span>
</span></span></code></pre>
<h4>Summary</h4>

<ul>
<li>The <code>transition0</code>  Predicate describes which move is allowed from a to b.</li>
<li>The valid  Predicate checks if a single state is legal based on our rules.</li>
</ul>

<p>The transition Predicate uses our <code>transition0</code> in both directions in order to
go from a to b and from b to a. This is possible while Prolog doesn’t have fixed
Input and Output Variables.</p>

<h3>The Search Algorithm (IDS)</h3>

<p>As already mentioned, the Iterative Deepening Search Algorithm fits perfect for our needs.
In order to understand how this search works, I will build it up step by step.</p>

<p>At first we need the depth-first-search on which the IDS is based on.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nf">ds</span><span class="p">(</span><span class="nv">Node</span><span class="p">,</span> <span class="nv">Goal</span><span class="p">)</span> <span class="p">:-</span>
</span></span><span class="line"><span class="cl">    <span class="nv">Node</span> <span class="o">==</span> <span class="nv">Goal</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">transition</span><span class="p">(</span><span class="nv">Node</span><span class="p">,</span><span class="nv">Neighbour</span><span class="p">)</span><span class="p">,</span> <span class="nf">ds</span><span class="p">(</span><span class="nv">Neighbour</span><span class="p">,</span> <span class="nv">Goal</span><span class="p">)</span><span class="p">.</span>
</span></span></code></pre>
<p>The Depth-First search works with the Back-Tracking feature of Prolog. It goes
into depth until either a Goal is reached or transition  returns false. If the
transition is false, it will go to the previous call of transition and will try
all possible transition s until a goal has been reached or no transitions are
left<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup>.</p>

<p>This implementation doesn’t has a kind of a history in order to avoid infinite loops
when the graph has a circle.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nf">ds</span><span class="p">(</span><span class="nv">Node</span><span class="p">,</span> <span class="nv">Goal</span><span class="p">,</span> <span class="nv">Path</span><span class="p">)</span> <span class="p">:-</span>
</span></span><span class="line"><span class="cl">    <span class="nv">Node</span> <span class="o">==</span> <span class="nv">Goal</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">transition</span><span class="p">(</span><span class="nv">Node</span><span class="p">,</span><span class="nv">Neighbour</span><span class="p">)</span><span class="p">,</span> <span class="o">not</span><span class="p">(</span><span class="nf">member</span><span class="p">(</span><span class="nv">Neighbour</span><span class="p">,</span><span class="nv">Path</span><span class="p">)</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nf">ds</span><span class="p">(</span><span class="nv">Neighbour</span><span class="p">,</span> <span class="nv">Goal</span><span class="p">,</span> <span class="p">[</span><span class="nv">Neighbour</span><span class="p">|</span><span class="nv">Path</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span></code></pre>
<p>Now out Search keeps track of the previous passed nodes and passes no node twice.
Until now, our Search only returns a true or false whenever the goal can be reached
or not. What’s with the path itself? Unfortunately, the path will be deleted when the
search comes back from the recursion. This can be added by using an additional output
variable. This will be filled with a reserved version of our path while the head of
the path is the last move and the last element of the tail our start node.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nf">ds</span><span class="p">(</span><span class="nv">Node</span><span class="p">,</span> <span class="nv">Goal</span><span class="p">,</span> <span class="nv">Path</span><span class="p">,</span> <span class="nv">ReturnPath</span><span class="p">)</span> <span class="p">:-</span>
</span></span><span class="line"><span class="cl">    <span class="nv">Node</span> <span class="o">==</span> <span class="nv">Goal</span><span class="p">,</span> <span class="nf">reverse</span><span class="p">(</span><span class="nv">Path</span><span class="p">,</span> <span class="nv">ReturnPath</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">transition</span><span class="p">(</span><span class="nv">Node</span><span class="p">,</span><span class="nv">Neighbour</span><span class="p">)</span><span class="p">,</span> <span class="o">not</span><span class="p">(</span><span class="nf">member</span><span class="p">(</span><span class="nv">Neighbour</span><span class="p">,</span><span class="nv">Path</span><span class="p">)</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nf">ds</span><span class="p">(</span><span class="nv">Neighbour</span><span class="p">,</span> <span class="nv">Goal</span><span class="p">,</span> <span class="p">[</span><span class="nv">Neighbour</span><span class="p">|</span><span class="nv">Path</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span></code></pre>
<p>Now we have and uninformed depth-first-search but the <code>i</code> is still missing.
Let&rsquo;s add a loop <code>ids_loop</code> that increases the depth until the goal has been
reached. The loop is solved via recursive call of <code>ids_loop</code> where <code>ids_start</code>
is initializes the loop with the initial depth. Our <code>ds</code> has been extended with
a depth parameter which gets decremented on every recursive call. A depth of
zero will cause the search to return with <code>false</code>.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nf">ids_core</span><span class="p">(</span><span class="nv">Node</span><span class="p">,</span> <span class="nv">Path</span><span class="p">,</span> <span class="nv">Goal</span><span class="p">,</span> <span class="nv">DepthLimit</span><span class="p">,</span> <span class="nv">ReturnPath</span><span class="p">)</span> <span class="p">:-</span>
</span></span><span class="line"><span class="cl">    <span class="nv">Node</span> <span class="o">==</span> <span class="nv">Goal</span><span class="p">,</span><span class="nf">reverse</span><span class="p">(</span><span class="nv">Path</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nv">DepthLimit</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nf">transition</span><span class="p">(</span><span class="nv">Node</span><span class="p">,</span><span class="nv">Neighbour</span><span class="p">)</span><span class="p">,</span><span class="o">not</span><span class="p">(</span><span class="nf">member</span><span class="p">(</span><span class="nv">Neighbour</span><span class="p">,</span><span class="nv">Path</span><span class="p">)</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nf">ids_core</span><span class="p">(</span><span class="nv">Neighbour</span><span class="p">,</span><span class="p">[</span><span class="nv">Neighbour</span><span class="p">|</span><span class="nv">Path</span><span class="p">]</span><span class="p">,</span><span class="nv">Goal</span><span class="p">,</span><span class="nv">DepthLimit</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">ids_loop</span><span class="p">(</span><span class="nv">Start</span><span class="p">,</span><span class="nv">Goal</span><span class="p">,</span><span class="nv">DepthLimit</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">)</span> <span class="p">:-</span>
</span></span><span class="line"><span class="cl">    <span class="nf">ids_core</span><span class="p">(</span><span class="nv">Start</span><span class="p">,</span><span class="p">[</span><span class="nv">Start</span><span class="p">]</span><span class="p">,</span><span class="nv">Goal</span><span class="p">,</span><span class="nv">DepthLimit</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">ids_loop</span><span class="p">(</span><span class="nv">Start</span><span class="p">,</span><span class="nv">Goal</span><span class="p">,</span><span class="nv">DepthLimit</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">ids_start</span><span class="p">(</span><span class="nv">Start</span><span class="p">,</span><span class="nv">Goal</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">)</span> <span class="p">:-</span>
</span></span><span class="line"><span class="cl">    <span class="nf">ids_loop</span><span class="p">(</span><span class="nv">Start</span><span class="p">,</span><span class="nv">Goal</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span><span class="p">.</span>
</span></span></code></pre>
<p>This implementation is very generic and can be used not only for rescuing our goat.
For example think about looking for a path from 1 to 5 in the graph below.</p>

<p><img src="saving-goats-with-prolog_goatprolog_graph2.png"/></p>

<h2>Save the Goat (finally)</h2>

<p>Let’s mix all together and save the goat before it starves or get eaten by the bad wolf.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nf">start</span><span class="p">(</span><span class="p">[</span><span class="s">a</span><span class="p">,</span><span class="s">a</span><span class="p">,</span><span class="s">a</span><span class="p">,</span><span class="s">a</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl"><span class="nf">goal</span><span class="p">(</span><span class="p">[</span><span class="s">b</span><span class="p">,</span><span class="s">b</span><span class="p">,</span><span class="s">b</span><span class="p">,</span><span class="s">b</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">transition0</span><span class="p">(</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="nv">F1</span><span class="p">]</span><span class="p">,</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="nv">F2</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl"><span class="nf">transition0</span><span class="p">(</span><span class="p">[</span><span class="nv">F1</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="nv">F1</span><span class="p">]</span><span class="p">,</span><span class="p">[</span><span class="nv">F2</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="nv">F2</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl"><span class="nf">transition0</span><span class="p">(</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="nv">F1</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="nv">F1</span><span class="p">]</span><span class="p">,</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="nv">F2</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="nv">F2</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl"><span class="nf">transition0</span><span class="p">(</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="nv">F1</span><span class="p">,</span><span class="nv">F1</span><span class="p">]</span><span class="p">,</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="nv">F2</span><span class="p">,</span><span class="nv">F2</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">transition</span><span class="p">(</span><span class="nv">X</span><span class="p">,</span><span class="nv">Y</span><span class="p">)</span> <span class="p">:-</span> <span class="p">(</span><span class="nf">transition0</span><span class="p">(</span><span class="nv">X</span><span class="p">,</span><span class="nv">Y</span><span class="p">)</span><span class="p">;</span><span class="nf">transition0</span><span class="p">(</span><span class="nv">Y</span><span class="p">,</span><span class="nv">X</span><span class="p">)</span><span class="p">)</span><span class="p">,</span> <span class="nf">valid</span><span class="p">(</span><span class="nv">X</span><span class="p">)</span><span class="p">,</span><span class="nf">valid</span><span class="p">(</span><span class="nv">Y</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">valid</span><span class="p">(</span><span class="p">[</span><span class="nv">F</span><span class="p">,</span><span class="k">_</span><span class="p">,</span><span class="k">_</span><span class="p">,</span><span class="nv">F</span><span class="p">]</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl"><span class="nf">valid</span><span class="p">(</span><span class="p">[</span><span class="nv">G</span><span class="p">,</span><span class="nv">C</span><span class="p">,</span><span class="nv">W</span><span class="p">,</span><span class="k">_</span><span class="p">]</span><span class="p">)</span> <span class="p">:-</span> <span class="nv">G</span> <span class="s">\==</span> <span class="nv">C</span><span class="p">,</span> <span class="nv">G</span> <span class="s">\==</span><span class="nv">W</span><span class="p">.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">% Iterative Depth-Search Algorithm</span>
</span></span><span class="line"><span class="cl"><span class="nf">ids_core</span><span class="p">(</span><span class="nv">Node</span><span class="p">,</span> <span class="nv">Path</span><span class="p">,</span> <span class="nv">Goal</span><span class="p">,</span> <span class="nv">DepthLimit</span><span class="p">,</span> <span class="nv">ReturnPath</span><span class="p">)</span> <span class="p">:-</span>
</span></span><span class="line"><span class="cl">    <span class="nv">Node</span> <span class="o">==</span> <span class="nv">Goal</span><span class="p">,</span><span class="nf">reverse</span><span class="p">(</span><span class="nv">Path</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">transition0</span><span class="p">(</span><span class="nv">Node</span><span class="p">,</span><span class="nv">Neighbour</span><span class="p">)</span><span class="p">,</span><span class="o">not</span><span class="p">(</span><span class="nf">member</span><span class="p">(</span><span class="nv">Neighbour</span><span class="p">,</span><span class="nv">Path</span><span class="p">)</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nf">ids_core</span><span class="p">(</span><span class="nv">Neighbour</span><span class="p">,</span><span class="p">[</span><span class="nv">Node</span><span class="p">|</span><span class="nv">Path</span><span class="p">]</span><span class="p">,</span><span class="nv">Goal</span><span class="p">,</span><span class="nv">DepthLimit</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">ids_loop</span><span class="p">(</span><span class="nv">Start</span><span class="p">,</span><span class="nv">Goal</span><span class="p">,</span><span class="nv">DepthLimit</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">)</span> <span class="p">:-</span>
</span></span><span class="line"><span class="cl">    <span class="nf">ids_core</span><span class="p">(</span><span class="nv">Start</span><span class="p">,</span><span class="p">[</span><span class="nv">Start</span><span class="p">]</span><span class="p">,</span><span class="nv">Goal</span><span class="p">,</span><span class="nv">DepthLimit</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">ids_loop</span><span class="p">(</span><span class="nv">Start</span><span class="p">,</span><span class="nv">Goal</span><span class="p">,</span><span class="nv">DepthLimit</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">ids_start</span><span class="p">(</span><span class="nv">Start</span><span class="p">,</span><span class="nv">Goal</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">)</span> <span class="p">:-</span> <span class="nf">ids_loop</span><span class="p">(</span><span class="nv">Start</span><span class="p">,</span><span class="nv">Goal</span><span class="p">,</span><span class="nv">ReturnPath</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span><span class="p">.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">save_the_goat</span><span class="p">(</span><span class="p">)</span> <span class="p">:-</span>
</span></span><span class="line"><span class="cl">    <span class="nf">start</span><span class="p">(</span><span class="nv">S</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nf">goal</span><span class="p">(</span><span class="nv">G</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nf">ids_start</span><span class="p">(</span><span class="nv">S</span><span class="p">,</span><span class="nv">G</span><span class="p">,</span><span class="nv">R</span><span class="p">)</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nf">write</span><span class="p">(</span><span class="nv">R</span><span class="p">)</span><span class="p">.</span>
</span></span></code></pre>
<div class="footnotes">

<hr>

<ol>
<li id="fn:1">Except in the featured image but I adoptet her from Pixabay</li>

<li id="fn:2">And if there are multiple ways to reach the goal. But this is not important for us. While our approach with the Iterative Deepening Search finds always the shortest way to the goal.</li>

<li id="fn:3">For simplicity, I didn’t made transition  symmetric. This means that the search algorithm can go in both directions. In our example the search can only go from top to down. To be more correct I should’ve added arrows to all edges in Figure 2 to make the graph directional.</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Sat, 23 Jul 2022 18:54:31 +0200</pubDate>
    </item>
    <item>
      <title>make-gitlab approve button</title>
      <link>https://evilcookie.de/make-gitlab-approve-button.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>make - gitlab approve button</h1>

<p><img src="make-gitlab-approve-button_approve1.jpg"/>
<img src="make-gitlab-approve-button_approve2.jpg"/></p>

<p>I constructed the gitlab merge-request approve button as 3D model and printed
it. The font is <code>Sourcecode Pro</code>, which I discovered from the public gitlab
using the firefox developer console, but it still looks a bit off to the
original one.</p>

<p>Anyway, it fits nicely into a nerdy developer office.</p>

<h2>Next</h2>

<p>Since the feedback from my colleagues was quite positive, I thought about
printing more gitlab stuff like the green/red pipeline status symbol. Adding a
magnet would turn them into actual whiteboard helpers.</p>

<h2>Update (24.01.2023)</h2>

<p>Now available <a href="https://www.printables.com/model/359925-approve-brick">on printables</a>.</p>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Fri, 08 Jul 2022 12:24:02 +0200</pubDate>
    </item>
    <item>
      <title>we are developers world congress 2022</title>
      <link>https://evilcookie.de/we-are-developers-world-congress-2022.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>we are developers world congress 2022</h1>

<p>I attended at the <a href="https://www.wearedevelopers.com/world-congress">WeAreDevelopers world
congress</a> 2022 in Berlin.</p>

<p>Some facts:</p>

<ul>
<li>date: 14.06. - 15.06.</li>
<li>speakers: 250</li>
<li>atendees: 8000</li>
<li>regular ticket price 600€</li>
</ul>

<p><strong>Disclaimer:</strong> I&rsquo;m paraphrasing (italic) the speaker based on my notes and memories as best as I can.</p>

<ol>
<li><a href="#cpp">Evolution of C++ - Bjarne Stroustrup</a></li>
<li><a href="#game">We are all part of the game - Joanna Pirker</a></li>
<li><a href="#wolfenstein3d">Wolfenstein 3D Post mortem - John Romero</a></li>
</ol>

<h2>Evolution of C++ - Bjarne Stroustrup<a id='cpp'/></h2>

<p>The inventor of C++ <a href="https://www.stroustrup.com/">himself</a> gave a brief history
of C++, its features and progress over time.</p>

<h3>Low Level abstraction</h3>

<p><em>Bjarne&rsquo;s initial motivation to create C++ was the lack of C&rsquo;s (or any available
language) abstraction while keeping it&rsquo;s
flexibility talking to hardware without unecessary layers. Dynamic memory
without memory management. Someone needs to care about resource: RAII (Resource
acquisition is initialization. A class cares about acquiring a resource
via constructor and releasing it again via destructor, implicitly.</em></p>

<h3>All good engineering relies on feedback</h3>

<p><em>C++ was shaped by its users and use-cases. While its initial purpose was for the probable first network cluster software (wich got never developed), it got attention from bunch of other directions.</em></p>

<p>I conclude &ldquo;Shaphing through feedback&rdquo; from this and would even say that this is true for many more areas of our life. Especially positive feedback (or as AI people might say &ldquo;positive reinforcement&rdquo;) will let us focus on the things that went well. That&rsquo;s one metric I try to measure for private software projects, which make more fun if its useful for someone.</p>

<h3>Make it simple, don&rsquo;t be to clever</h3>

<p>What&rsquo;s called KISS (Keep it simple stupid) today was important back then to
avoid overengineering.</p>

<h3>Compile time optimizations</h3>

<p><em>Anything the compiler can compute, doesn&rsquo;t need to get computed at runtime.
From constant arithmetic expressions to static assertions. The latter has the
goal to outsource error-handling more to the compiler to improve runtime
performance.</em></p>

<h3>Influence</h3>

<p>It was very impressive that the language introduces sophisticated concepts like generics and shaped a whole
world<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>. Even if we don&rsquo;t use it, it seems to be anywhere: conceptual and as a
fundament for higher languages or engines.</p>

<h2>We are all part of the game - Joanna Pirker<a name='game'/></h2>

<p><a href="http://jpirker.com/about-johanna/">Joanna Pirker</a></p>

<h3>Physical presence</h3>

<p>_People celebrated birthdays and weddings within <a href="https://en.wikipedia.org/wiki/Animal_Crossing">Animal Crossing</a> during the pandemic<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>. While video converences like skype or zoom let their attendees feel the difference by lack of physical presence, games do. Like in Animal Crossing<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup>, there is a physical interactible presence/avatar representing the friend or family member._</p>

<p>Having a family spread across the country, playing games with physical presence can be quite helpful to overcome distance. Especially with my brother I play games like Minecraft, Fortnite, Raft, GTA, Borderlands, Risk of rain, No mans sky.</p>

<p>As long as this doesn&rsquo;t replace real interaction, this is a good thing in my opinion.</p>

<h2>Wolfenstein 3D Post mortem - John Romero<a name='wolfenstein3d'></a></h2>

<p><a href="https://romero.com/">John Romero</a> is a founder of the famous <a href="https://idsoftware.com">id software</a> game studio from 1991.</p>

<h3>Debugging</h3>

<p><em>There were no debugger around at that time, so the cycle was: making a small code change, test game, repeat. With Assembler and C.</em></p>

<p>Its amazing how this was even possible. They made their own engine and built a dozen of games per year, mostly two at the same time, with not more than six people. Debugging a game engine without debugger sounds like huge pain to me.
Maybe the whole automation, meta-language and tooling thing to accelerate the feedback loop on debugging prevents a developer to evolve their focus and &ldquo;stamina&rdquo;. Like how long do you follow the path down the rabbit hole when things go wrong? If you&rsquo;re already familiar with the assembler-hell, maybe nothing can stop you.
Nowadays I don&rsquo;t have any clue about processor registers in memory dumps and I primarily evaluate a more high level way of debug something than get my hands dirty. Maybe I should&hellip;</p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">Go introduces generics this year with 1.18</li>

<li id="fn:2">See <a href="https://www.washingtonpost.com/video-games/2020/04/02/animal-crossing-wedding-coronavirus/">Washington Post: The pandemic canceled their wedding. So they held it in Animal Crossing.</a></li>

<li id="fn:3">or in my case GTA 5</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Thu, 16 Jun 2022 23:38:54 +0200</pubDate>
    </item>
    <item>
      <title>blog-update-v0.3.0</title>
      <link>https://evilcookie.de/blog-update-v030.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>blog update: v0.3.0</h1>

<p><a href="https://github.com/RaphaelPour/blogctl/releases/tag/v0.3.0">Blogctl v0.3.0</a> is out!</p>

<ul>
<li>CI release automation</li>
<li>navigation in posts (next, previous, home)</li>
<li>syntax highlighting</li>
</ul>

<h2>CI release automation</h2>

<p><code>blogctl</code> can now be released pretty straight forward:</p>

<ul>
<li>add latest change to changelog<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>: <code>task cangelog</code></li>
<li>bump version and release it: <code>task release</code></li>
</ul>

<p>That&rsquo;s it! A <a href="https://github.com/RaphaelPour/blogctl/blob/master/.github/workflows/blogctl.yml#L32">tag pipeline will start</a> and create <a href="https://github.com/RaphaelPour/blogctl/releases/tag/v0.3.0">a new release</a> with 64bit binaries for linux and mac<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>.</p>

<h2>Navigation</h2>

<p>See blog article <a href="https://evilcookie.de/blog-update---navigation.html">blog update:
navigation</a>.</p>

<h2>Syntax highlighting</h2>

<p>Code blocks are now syntax highlighted<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup>. I decided to use a
more subtle, monochrome style only to keep focus. We used the lib
<a href="https://github.com/alecthomas/chroma">chroma</a> which supports a lot of languages
and can be configured via CSS. This feature also <a href="https://github.com/RaphaelPour/blogctl/blob/master/cmd/render.go#L301">adds some clutter to the html
template</a> where the CSS needs to be included. It&rsquo;s planned to clean this up and
outsource the stylesheet to the highlight package where it belongs to.</p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">I use <a href="https://github.com/MarkusFreitag/changelogger">changelogger</a> to add entries, bump versions and render summaries interactively.<br></li>

<li id="fn:2">Windows is not included as the interactive part of blogctl requires a unix shell to open a terminal editor configured via environment variables <code>VISUAL</code> or <code>EDITOR</code> (thanks to <a href="https://github.com/MarkusFreitag/changelogger/blob/master/pkg/editor/editor.go">changelogger</a> for that trick).<br></li>

<li id="fn:3">Thanks to <a href="https://github.com/Tch1b0">Tch1b0</a> for the contribution!</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Sun, 27 Mar 2022 09:43:35 +0200</pubDate>
    </item>
    <item>
      <title>clt 2022 - storage migration: schnell und einfach</title>
      <link>https://evilcookie.de/clt-2022---storage-migration-schnell-und-einfach.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>clt 2022 - storage migration: schnell und einfach</h1>

<p>I just did my first public german talk <a href="https://chemnitzer.linux-tage.de/2022/en/programm/beitrag/147">Storage Migration: Schnell und
einfach</a> about
transferring local storage fast and simple, last Saturday.</p>

<p>The lecture got recorded and I&rsquo;ll update this post with a link once published.</p>

<h2>Some data</h2>

<ul>
<li>~60 visitors</li>
<li>presentation took ~30 min.</li>
<li>interview took another ~10 min.</li>
<li><a href="https://chemnitzer.linux-tage.de/2022/media/video/147.mp4">recording</a></li>
<li><a href="https://chemnitzer.linux-tage.de/2022/media/programm/folien/147.pdf">slides</a></li>
<li><a href="https://chemnitzer.linux-tage.de/2022/media/programm/shortpaper/147.pdf">shortpaper</a></li>
<li><a href="https://chemnitzer.linux-tage.de/2022/de/programm/beitrag/147">clt site</a></li>
<li><del><a href="https://pad.live.linux-tage.de/HIq15alBRhqJMBR2dUlLCQ#">pad</a></del> dead</li>
<li><a href="https://chemnitzer.linux-tage.de/2022/en/programm/beitrag/bewertung/147/0ca2a2c40a0256ea7677cae468a687db">rating</a>
(1=bad..5=excellent)

<ul>
<li>17 ratings</li>
<li>structure and intelligibility: 4.5882352941176.round(1) = 4.5</li>
<li>correspondence with announcement: 4.5882352941176.round(1) = 4.5</li>
</ul></li>
</ul>

<h2>Summary</h2>

<p>We<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> optimized the migration of a 120GB disk with 50% used data
from roughly eight to about one minute. This could be accomplished by replacing
the former solution <a href="https://www.maier-komor.de/mbuffer.html">mbuffer</a> with our
self made one. A HTTP server/client simplifies the connection handling by natively
supporting encryption via TLS such as parallelism via concurrent connections. As
our local storage is a <a href="https://man7.org/linux/man-pages/man7/lvmthin.7.html">thin provisioned
lv</a>, we could use a block map to only
transfer used data.</p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">Cloud services team at <a href="https://www.hetzner.com/cloud">Hetzner Online</a></li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Mon, 14 Mar 2022 13:47:05 +0100</pubDate>
    </item>
    <item>
      <title>blog update about me</title>
      <link>https://evilcookie.de/blog-update-about-me.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>blog update: about me</h1>

<p><img src="blog-update-about-me_me.png"/></p>

<p>The confirmation of my <a href="https://chemnitzer.linux-tage.de/2022/de/programm/beitrag/147">CLT 2022
lecture</a>
triggered me to add more &lsquo;about me&rsquo; to my blog.</p>

<p>Originally I wanted to add static-site support to add a separate &lsquo;about me&rsquo;
page, but this would need a more sophisticated concept. So my intermediate solution was to
just hard code a banner with a short introduction.</p>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Fri, 25 Feb 2022 12:36:54 +0100</pubDate>
    </item>
    <item>
      <title>godot wild jam 42 - the ancient game of ur</title>
      <link>https://evilcookie.de/godot-wild-jam-42---the-ancient-game-of-ur.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>godot wild jam 42 - the ancient game of ur</h1>

<p>My mates<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> and I participated at the <a href="https://itch.io/jam/godot-wild-jam-42">42. Godot Wild
Jam</a> with our submission <a href="https://evilc00kie.itch.io/the-ancient-game-of-ur">The ancient
Game of Ur</a>.</p>

<p>The theme was <em>Ancient</em> and we decided to interpret the &lsquo;oldest known&rsquo; board
game <a href="https://en.wikipedia.org/wiki/Royal_Game_of_Ur"><em>Royal game of Ur</em></a>. We
decided to do a 3D game playing against an AI.</p>

<p>To fulfill the wildcard <em>Mom I&rsquo;m on TV</em><sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>, we added four AI&rsquo;s
with different strategies representing us developers:</p>

<ul>
<li>tch1bo: kicks out opponent whenever possible</li>
<li>kjarrigan:

<ul>
<li>1st: moves tokens to safe space at the end of the board, for tokens
positioned after the middle/shared special field</li>
<li>2nd: add as much tokens to the board as possible</li>
</ul></li>
<li>jOBraun:

<ul>
<li>1st: move token away from enemy that could probably kick the token out</li>
<li>2nd: move new token in if there are less than 3 on the board</li>
</ul></li>
<li>evilcookie:

<ul>
<li>1st: move to special field</li>
<li>2st: stay on middle/shared special fields as long as possible</li>
<li>3rd: try to kick out opponent&rsquo;s tokens in the first half the field</li>
</ul></li>
</ul>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1"><a href="https://github.com/Tch1b0">Johannes</a>, <a href="https://github.com/Kjarrigan">Holger</a> and <a href="https://github.com/j0braun">John</a><br></li>

<li id="fn:2">&ldquo;Shoehorn in developer cameos&rdquo;</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Tue, 22 Feb 2022 13:03:56 +0100</pubDate>
    </item>
    <item>
      <title>hcloud-ruby v1.0.3</title>
      <link>https://evilcookie.de/hcloud-ruby-v103.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>hcloud-ruby v1.0.3</h1>

<p>I&rsquo;m now contributing and maintaining the <a href="https://rubygems.org/gems/hcloud">ruby gem <code>hcloud</code></a>, a client for the
<a href="https://docs.hetzner.cloud/">Hetzner Cloud API</a>. As a first &lsquo;official act&rsquo;, we<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> tidied the repo up a bit and
released <a href="https://github.com/tonobo/hcloud-ruby/tree/v1.0.3">v1.0.3</a>.</p>

<h2>Changes</h2>

<ul>
<li>set up a working CI, shifting from travis<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> to <a href="https://github.com/tonobo/hcloud-ruby/blob/v1.0.3/.github/workflows/ruby.yml">github actions</a></li>
<li>support ruby 3.0+3.1</li>
</ul>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">credits to <a href="https://github.com/Kjarrigan">Holger</a></li>

<li id="fn:2"><a href="https://news.ycombinator.com/item?id=25338983">https://news.ycombinator.com/item?id=25338983</a><br></li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Thu, 17 Feb 2022 16:22:12 +0100</pubDate>
    </item>
    <item>
      <title>git: split commits</title>
      <link>https://evilcookie.de/git-split-commits.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>git: split commits</h1>

<p>Is that branch commit list familiar to you?</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">pick a70ebde big commit with major feature update
</span></span><span class="line"><span class="cl">pick e561140 minor change
</span></span><span class="line"><span class="cl">pick e3dfbbe minor change
</span></span><span class="line"><span class="cl">pick 5648ef4 minor change
</span></span></code></pre>
<p>That one big commit <code>a70ebde</code> that should better be several smaller ones?</p>

<ol>
<li>edit commit via rebase:

<ul>
<li><code>git rebase -i &lt;main branch&gt;</code></li>
<li>replace <code>pick</code> with <code>edit</code> or <code>e</code> of the big commit</li>
</ul></li>
<li>reset commit (softly!) via <code>git reset HEAD^</code></li>
<li>commit everything separately</li>
<li>finish rebase: <code>git rebase --continue</code></li>
</ol>

<p>If you get stuck in any stage, just abort the process with <code>git rebase --abort</code>.</p>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Fri, 11 Feb 2022 12:21:41 +0100</pubDate>
    </item>
    <item>
      <title>blog update - navigation</title>
      <link>https://evilcookie.de/blog-update---navigation.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>blog update: navigation</h1>

<p><a href="https://github.com/RaphaelPour/blogctl"><code>Blogctl</code></a> now renders navigation links per post:</p>

<ul>
<li>previous post: <code>&lt;</code></li>
<li><code>up</code> to the index</li>
<li>next post: <code>&gt;</code></li>
</ul>

<h2>Motivation</h2>

<p>Although I&rsquo;ve added <a href="https://github.com/RaphaelPour/blogctl/issues/33">the feature
request</a> over a year ago, now
was the right time to implement it.</p>

<p>Since a lot of projects vanish or get stale due to lack of motivation, I want to
develop blogctl and my blog differently.</p>

<p>Like if ideas were soap bubbles, growing bigger if the idea gets more useful or generates attention.
When they&rsquo;re big enough and pop, the right time for implementation has arrived. If they&rsquo;re flying out
of sight without popping, it might be better to wait or drop them entirely.</p>

<p>I try to make sure, with this strategy, that only <em>relevant</em> features get my
attention/motivation.</p>

<p>The <em>pop</em> of this feature actually happens due to <a href="https://github.com/RaphaelPour/blogctl/issues/33#issuecomment-1017966739">Robert&rsquo;s
+1</a>.</p>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Wed, 26 Jan 2022 12:47:44 +0100</pubDate>
    </item>
    <item>
      <title>aoc21-9 3d print of cave height map</title>
      <link>https://evilcookie.de/aoc21-9-3d-print-of-cave-height-map.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>AoC 2021 day 9 - 3D print of cave height map</h1>

<p>After solving the <a href="https://adventofcode.com/2021/day/9">puzzle of day 9</a> about a
cave with basins and heights from 0 to 9, we<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> thought about 3D printing the input as height map.</p>

<h2>Go program</h2>

<p>I generated an <a href="https://en.wikipedia.org/wiki/STL_(file_format)">STL model</a>
using the puzzle input as list of lines:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">renderSTL</span><span class="p">(</span><span class="nx">input</span> <span class="p">[</span><span class="p">]</span><span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">filename</span> <span class="o">:=</span> <span class="s">&#34;day09.stl&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// list of all generated boxes
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">boxes</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="p">[</span><span class="p">]</span><span class="nx">sdf</span><span class="p">.</span><span class="nx">SDF3</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// base plate on which the height 0 begins 
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">plate2d</span> <span class="o">:=</span> <span class="nx">sdf</span><span class="p">.</span><span class="nf">Box2D</span><span class="p">(</span><span class="nx">sdf</span><span class="p">.</span><span class="nx">V2</span><span class="p">{</span><span class="nb">float64</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">input</span><span class="p">)</span><span class="p">)</span><span class="p">,</span> <span class="nb">float64</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">input</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="p">)</span><span class="p">)</span><span class="p">}</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="nx">plate3d</span> <span class="o">:=</span> <span class="nx">sdf</span><span class="p">.</span><span class="nf">Extrude3D</span><span class="p">(</span><span class="nx">plate2d</span><span class="p">,</span> <span class="mf">2.0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// Move plate completely to the positive space. Initially the center of the
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// plate is positioned at the origin.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">plateM</span> <span class="o">:=</span> <span class="nx">sdf</span><span class="p">.</span><span class="nf">Translate3d</span><span class="p">(</span><span class="nx">sdf</span><span class="p">.</span><span class="nx">V3</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">float64</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">input</span><span class="p">)</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nb">float64</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">input</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="p">)</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">boxes</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">boxes</span><span class="p">,</span> <span class="nx">sdf</span><span class="p">.</span><span class="nf">Transform3D</span><span class="p">(</span><span class="nx">plate3d</span><span class="p">,</span> <span class="nx">plateM</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="nx">y</span><span class="p">,</span> <span class="nx">row</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">input</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="nx">x</span><span class="p">,</span> <span class="nx">cell</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">row</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="nx">cell</span> <span class="o">==</span> <span class="sc">&#39;0&#39;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">continue</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="nx">num</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">strconv</span><span class="p">.</span><span class="nf">Atoi</span><span class="p">(</span><span class="nb">string</span><span class="p">(</span><span class="nx">cell</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;error converting %d\n&#34;</span><span class="p">,</span> <span class="nx">cell</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="nx">box2d</span> <span class="o">:=</span> <span class="nx">sdf</span><span class="p">.</span><span class="nf">Box2D</span><span class="p">(</span><span class="nx">sdf</span><span class="p">.</span><span class="nx">V2</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">}</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// add one so level 0 has one unit
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="nx">height</span> <span class="o">:=</span> <span class="nb">float64</span><span class="p">(</span><span class="nx">num</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="nx">box3d</span> <span class="o">:=</span> <span class="nx">sdf</span><span class="p">.</span><span class="nf">Extrude3D</span><span class="p">(</span><span class="nx">box2d</span><span class="p">,</span> <span class="nx">height</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="nx">m</span> <span class="o">:=</span> <span class="nx">sdf</span><span class="p">.</span><span class="nf">Translate3d</span><span class="p">(</span><span class="nx">sdf</span><span class="p">.</span><span class="nx">V3</span><span class="p">{</span><span class="nb">float64</span><span class="p">(</span><span class="nx">x</span><span class="p">)</span><span class="p">,</span> <span class="nb">float64</span><span class="p">(</span><span class="nx">y</span><span class="p">)</span><span class="p">,</span> <span class="nx">height</span> <span class="o">/</span> <span class="mi">2</span><span class="p">}</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="nx">boxes</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">boxes</span><span class="p">,</span> <span class="nx">sdf</span><span class="p">.</span><span class="nf">Transform3D</span><span class="p">(</span><span class="nx">box3d</span><span class="p">,</span> <span class="nx">m</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;generated %d boxes\n&#34;</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="nx">boxes</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="nx">start</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Now</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="nx">render</span><span class="p">.</span><span class="nf">RenderSTL</span><span class="p">(</span><span class="nx">sdf</span><span class="p">.</span><span class="nf">Union3D</span><span class="p">(</span><span class="nx">boxes</span><span class="o">...</span><span class="p">)</span><span class="p">,</span> <span class="mi">400</span><span class="p">,</span> <span class="nx">filename</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;needed %s\n&#34;</span><span class="p">,</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Since</span><span class="p">(</span><span class="nx">start</span><span class="p">)</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p><img src="aoc21-9-3d-print-of-cave-height-map_slicer.jpg"/></p>

<h2>Impressions</h2>

<p><img src="aoc21-9-3d-print-of-cave-height-map_result1.jpg"/></p>

<p><img src="aoc21-9-3d-print-of-cave-height-map_result2.jpg"/></p>

<p><img src="aoc21-9-3d-print-of-cave-height-map_result3.jpg"/></p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">credits to <a href="https://github.com/MarkusFreitag">Markus</a></li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Fri, 14 Jan 2022 12:46:28 +0100</pubDate>
    </item>
    <item>
      <title>blog update: image support</title>
      <link>https://evilcookie.de/blog-update-image-support.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>blog update: image support</h1>

<p><img src="blog-update-image-support_test.png"/></p>

<p>blogctl now supports images.</p>

<h2>Concept</h2>

<p>Images can be placed inside the post folder and embedded via the <code>IMAGE(&lt;filename&gt;)</code> tag.
The renderer automatically:</p>

<ol>
<li>converts all tags to html</li>
<li>copies the images to the output directory</li>
<li>adds the post title as suffix to the filename.</li>
</ol>

<p>Last one is needed to avoid naming conflicts, having duplicate file names across different
posts<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>. Images that aren&rsquo;t referenced, get ignored. The tag helps me to avoid remembering the right path or parsing markdown/html to
adjust the final path.</p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">The output directory is flat and has no subdirectories.</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Thu, 13 Jan 2022 22:37:29 +0100</pubDate>
    </item>
    <item>
      <title>firefox: disable download dialog delay</title>
      <link>https://evilcookie.de/firefox-disable-download-dialog-delay.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>firefox: disable download dialog delay</h1>

<p>When downloading files with firefox, the ok button of the file-dialog stays
disabled for a few seconds. This bugged me a dozen of times. I looked
around the config and found a &lsquo;solution&rsquo;:</p>

<ol>
<li>goto <code>about:config</code></li>
<li>set <code>security.dialog_enable_delay</code> to <code>0</code></li>
</ol>

<h2>Downside</h2>

<p>On researching about the config value, it&rsquo;s existing must have a purpose
(right?), I stumbled accross this
post about <a href="https://www.squarefree.com/2004/07/01/race-conditions-in-security-dialogs/">Race conditions in security dialogs</a>
which stated:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">[...] the attack involves convincing the user to double-click a certain spot on
</span></span><span class="line"><span class="cl">the screen [...] where the &#39;Yes&#39; button will appear. The first click triggers
</span></span><span class="line"><span class="cl">the dialog; the second click lands on the &#39;Yes&#39; button.
</span></span></code></pre>
<p>Firefox&rsquo;s delay is <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=162020">their
fix</a> to the stated security
issue<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>.</p>

<h2>Fix</h2>

<p>I set the delay to <code>500</code> as a compromise.</p>

<p>year&hellip;</p>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">WOHA! The issue was filed 19 yrs ago! I went to elementary school that</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Wed, 06 Oct 2021 13:41:53 +0200</pubDate>
    </item>
    <item>
      <title>blog update: rss feed</title>
      <link>https://evilcookie.de/blog-update-rss-feed.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>blog update: rss feed</h1>

<p>Blogctl now <a href="https://github.com/RaphaelPour/blogctl/pull/37/commits/d9bbf469e1ab948752ff924f990873bdd11adc9c">generates an rss feed</a> along with the site.</p>

<h2>Motivation</h2>

<p>Since I started to read <a href="https://news.ycombinator.com/">HackerNews</a> on a daily basis, I found a bunch of
blogger that I wanted to keep track of without polling. RSS seemed the right solution for this type of
problem. I use the firefox extension <a href="https://addons.mozilla.org/en-US/firefox/addon/feedbroreader/">feedbro</a> to manage and read my feeds<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>.</p>

<p>This worked out quite well so far. Why not providing my own feed?</p>

<h2>Technical details</h2>

<p>The go package <a href="https://github.com/gorilla/feeds">gorilla/feeds</a> provides an
easy generator for RSS, atom and json.</p>

<ul>
<li><a href="http://antirez.com">Antirez</a>: creator of redis</li>
<li><a href="https://www.brendangregg.com/blog/index.html">Brendan Gregg</a>: Performance engineer currently working at Netflix</li>
<li><a href="https://go.dev/blog/">Go blog</a></li>
<li><a href="https://0pointer.net/blog/">Poettering</a>: creator of systemd</li>
<li><a href="https://xkcd.com/">xkcd</a>: comics about math, computer science and science in general</li>
<li><a href="https://www.monkeyuser.com/">MoneyUser</a>: comics about software development</li>
</ul>

<div class="footnotes">

<hr>

<ol>
<li id="fn:1">Non-exhaustive blog recommendations:</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Wed, 06 Oct 2021 10:52:03 +0200</pubDate>
    </item>
    <item>
      <title>Bad practice: busy waiting</title>
      <link>https://evilcookie.de/bad-practice-busy-waiting.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>bad practice: busy-waiting</h1>

<p>Busy-waiting is one of the easiest ways of exhausting a cpu<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="kc">true</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="cm">/* complex logic */</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>What looks like a stupid construct one would never do by accident is often
introduced on waiting a resource or state change. I mostly see this construct
on retrying connecting to a service a couple of times.</p>

<h2>Analyze</h2>

<p>Use <code>top</code>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">PID     USER       PR   NI VIRT      RES    SHR S %CPU    %MEM  TIME+   COMMAND
</span></span><span class="line"><span class="cl">1237306 evilcookie 20   0  702424    936    644 R 100.3   0.0   0:59.39 busywaiting      
</span></span></code></pre>
<p>The process has a load of one or higher.</p>

<h2>Solutions</h2>

<p>A general solution for busy-waiting is telling the CPU to do something else for
some time. This can be done by using the syscall <code>sleep</code><sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="s">&#34;time&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="kc">true</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="cm">/* complex logic */</span>
</span></span><span class="line"><span class="cl">    <span class="nx">time</span><span class="p">.</span><span class="nf">Sleep</span><span class="p">(</span><span class="mi">1</span> <span class="o">*</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Millisecond</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>Sleeping one millisecond is enough to make the process barely remarkable:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">PID     USER      PR   NI VIRT      RES    SHR S %CPU  %MEM  TIME+   COMMAND
</span></span><span class="line"><span class="cl">1242442 rpour     20   0  702476   1340    840 S 8.6   0.0   0:01.05 busywaiting
</span></span></code></pre>
<div class="footnotes">

<hr>

<ol>
<li id="fn:1">all examples are written in golang</li>

<li id="fn:2"><a href="https://man7.org/linux/man-pages/man3/sleep.3.html">sleep (3)</a>: &ldquo;On Linux, sleep() is implemented via <a href="https://man7.org/linux/man-pages/man2/nanosleep.2.html">nanosleep(2)</a>.&rdquo;</li>
</ol>

</div>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Fri, 09 Jul 2021 13:13:03 +0200</pubDate>
    </item>
    <item>
      <title>Read this blog with emacs</title>
      <link>https://evilcookie.de/read-this-blog-with-emacs.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Read this blog with emacs</h1>

<ol>
<li><a href="https://www.gnu.org/software/emacs/download.html">Download and install
emacs</a></li>
<li>start emacs</li>
<li>press <code>meta+x</code> where meta may either ctrl or alt</li>
<li>type <code>eww</code></li>
<li>type <code>evilcookie.de</code></li>
<li>hit <code>return</code></li>
<li>enjoy the blog:

<ul>
<li>navigate: arrow keys</li>
<li>visit links: <code>return</code></li>
<li>go back: <code>l</code></li>
</ul></li>
</ol>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Wed, 26 May 2021 12:53:08 +0200</pubDate>
    </item>
    <item>
      <title>--version always</title>
      <link>https://evilcookie.de/--version-always.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>&ndash;version always</h1>

<p><em>Am I in the matrix?</em></p>

<p>Which sounds like a quote is the result of hours testing and debugging with development releases.
When things get messy and intransparent, it&rsquo;s always good to have a <code>--version</code> printing some build information. Where <em>build information</em> is defined as date and version in this post. Since version control is a industry standard, the last commit sha can be used as version if no other version system is used.</p>

<p>Bonus:</p>

<ul>
<li>Log output of <code>--version</code> directly on every start: When a log lives longer than the version of the corresponding binary, it&rsquo;s easier for error tracing.</li>
<li>Monitor deployed version: Having a lot of servers running different versions of a binary, it becomes easier to export the version using the version-flag.</li>
<li>Distinguish binaries: Having multiple version of a binary at ones, it&rsquo;s easier to distinguish them by version/date.</li>
</ul>

<h3>Contents</h3>

<ul>
<li><a href="#example">Example</a>

<ul>
<li><a href="#linux">Linux variant</a></li>
<li><a href="#others">Others</a></li>
</ul></li>
<li><a href="#implementation">Implementation</a>

<ul>
<li><a href="#go">Go</a></li>
<li><a href="#c">C</a></li>
</ul></li>
<li><a href="#ideas">Further ideas</a></li>
</ul>

<h2>Example<a name='example'></h2>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ ./blogctl --version
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">BuildVersion:  v0.1.3-10-ge84a71f
</span></span><span class="line"><span class="cl">BuildDate:  2020-12-05T17:17:56+0100
</span></span></code></pre><pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ ./femto --version
</span></span><span class="line"><span class="cl">BuildDate: 2020-09-16T15:08:11+0200
</span></span><span class="line"><span class="cl">BuildVersion: v0.4.0-3-g8a901a5
</span></span></code></pre>
<h3>Linux variant<a name='linux'></h3>

<p>The linux variant includes a subset of:</p>

<ul>
<li>name</li>
<li>package</li>
<li>version</li>
<li>target distro</li>
<li>target distro version</li>
<li>license</li>
<li>author</li>
</ul>

<p>Like <code>gcc</code> or <code>bash</code>:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ gcc --version
</span></span><span class="line"><span class="cl">gcc <span class="o">(</span>GCC<span class="o">)</span> 10.2.1 <span class="m">20201125</span> <span class="o">(</span>Red Hat 10.2.1-9<span class="o">)</span>
</span></span><span class="line"><span class="cl">Copyright <span class="o">(</span>C<span class="o">)</span> <span class="m">2020</span> Free Software Foundation, Inc.
</span></span><span class="line"><span class="cl">This is free software<span class="p">;</span> see the <span class="nb">source</span> <span class="k">for</span> copying conditions.  There is NO
</span></span><span class="line"><span class="cl">warranty<span class="p">;</span> not even <span class="k">for</span> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
</span></span></code></pre><pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ bash --version
</span></span><span class="line"><span class="cl">GNU bash, version 5.0.17<span class="o">(</span>1<span class="o">)</span>-release <span class="o">(</span>x86_64-pc-linux-gnu<span class="o">)</span>
</span></span><span class="line"><span class="cl">Copyright <span class="o">(</span>C<span class="o">)</span> <span class="m">2019</span> Free Software Foundation, Inc.
</span></span><span class="line"><span class="cl">License GPLv3+: GNU GPL version <span class="m">3</span> or later &lt;http://gnu.org/licenses/gpl.html&gt;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">This is free software<span class="p">;</span> you are free to change and redistribute it.
</span></span><span class="line"><span class="cl">There is NO WARRANTY, to the extent permitted by law.
</span></span></code></pre><pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ md5sum --version
</span></span><span class="line"><span class="cl">md5sum <span class="o">(</span>GNU coreutils<span class="o">)</span> 8.30
</span></span><span class="line"><span class="cl">Copyright <span class="o">(</span>C<span class="o">)</span> <span class="m">2018</span> Free Software Foundation, Inc.
</span></span><span class="line"><span class="cl">License GPLv3+: GNU GPL version <span class="m">3</span> or later &lt;https://gnu.org/licenses/gpl.html&gt;.
</span></span><span class="line"><span class="cl">This is free software: you are free to change and redistribute it.
</span></span><span class="line"><span class="cl">There is NO WARRANTY, to the extent permitted by law.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Written by Ulrich Drepper, Scott Miller, and David Madore.
</span></span></code></pre>
<h3>Others<a name='others'></h3>

<p>Docker with version and build hash:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ docker --version
</span></span><span class="line"><span class="cl">Docker version 19.03.12, build 48a66213fe
</span></span></code></pre>
<p>Gpg which looks like the <a href="#linux">linux variant</a> but with all supported algorithms on top:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ gpg --version
</span></span><span class="line"><span class="cl">gpg <span class="o">(</span>GnuPG<span class="o">)</span> 2.2.19
</span></span><span class="line"><span class="cl">libgcrypt 1.8.5
</span></span><span class="line"><span class="cl">Copyright <span class="o">(</span>C<span class="o">)</span> <span class="m">2019</span> Free Software Foundation, Inc.
</span></span><span class="line"><span class="cl">License GPLv3+: GNU GPL version <span class="m">3</span> or later &lt;https://gnu.org/licenses/gpl.html&gt;
</span></span><span class="line"><span class="cl">This is free software: you are free to change and redistribute it.
</span></span><span class="line"><span class="cl">There is NO WARRANTY, to the extent permitted by law.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Home: /root/.gnupg
</span></span><span class="line"><span class="cl">Supported algorithms:
</span></span><span class="line"><span class="cl">Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
</span></span><span class="line"><span class="cl">Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
</span></span><span class="line"><span class="cl">        CAMELLIA128, CAMELLIA192, CAMELLIA256
</span></span><span class="line"><span class="cl">Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
</span></span><span class="line"><span class="cl">Compression: Uncompressed, ZIP, ZLIB, BZIP2
</span></span></code></pre>
<p>Vim with its verbose output:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">$ vim --version
</span></span><span class="line"><span class="cl">VIM - Vi IMproved 8.1 <span class="o">(</span><span class="m">2018</span> May 18, compiled Apr <span class="m">15</span> <span class="m">2020</span> 06:40:31<span class="o">)</span>
</span></span><span class="line"><span class="cl">Included patches: 1-2269
</span></span><span class="line"><span class="cl">Modified by team+vim@tracker.debian.org
</span></span><span class="line"><span class="cl">Compiled by team+vim@tracker.debian.org
</span></span><span class="line"><span class="cl">Huge version without GUI.  Features included <span class="o">(</span>+<span class="o">)</span> or not <span class="o">(</span>-<span class="o">)</span>:
</span></span><span class="line"><span class="cl">+acl               -farsi             -mouse_sysmouse    -tag_any_white
</span></span><span class="line"><span class="cl">+arabic            +file_in_path      +mouse_urxvt       -tcl
</span></span><span class="line"><span class="cl">+autocmd           +find_in_path      +mouse_xterm       +termguicolors
</span></span><span class="line"><span class="cl">+autochdir         +float             +multi_byte        +terminal
</span></span><span class="line"><span class="cl">-autoservername    +folding           +multi_lang        +terminfo
</span></span><span class="line"><span class="cl">-balloon_eval      -footer            -mzscheme          +termresponse
</span></span><span class="line"><span class="cl">+balloon_eval_term +fork<span class="o">(</span><span class="o">)</span>            +netbeans_intg     +textobjects
</span></span><span class="line"><span class="cl">-browse            +gettext           +num64             +textprop
</span></span><span class="line"><span class="cl">++builtin_terms    -hangul_input      +packages          +timers
</span></span><span class="line"><span class="cl">+byte_offset       +iconv             +path_extra        +title
</span></span><span class="line"><span class="cl">+channel           +insert_expand     -perl              -toolbar
</span></span><span class="line"><span class="cl">+cindent           +job               +persistent_undo   +user_commands
</span></span><span class="line"><span class="cl">-clientserver      +jumplist          +postscript        +vartabs
</span></span><span class="line"><span class="cl">-clipboard         +keymap            +printer           +vertsplit
</span></span><span class="line"><span class="cl">+cmdline_compl     +lambda            +profile           +virtualedit
</span></span><span class="line"><span class="cl">+cmdline_hist      +langmap           -python            +visual
</span></span><span class="line"><span class="cl">+cmdline_info      +libcall           +python3           +visualextra
</span></span><span class="line"><span class="cl">+comments          +linebreak         +quickfix          +viminfo
</span></span><span class="line"><span class="cl">+conceal           +lispindent        +reltime           +vreplace
</span></span><span class="line"><span class="cl">+cryptv            +listcmds          +rightleft         +wildignore
</span></span><span class="line"><span class="cl">+cscope            +localmap          -ruby              +wildmenu
</span></span><span class="line"><span class="cl">+cursorbind        -lua               +scrollbind        +windows
</span></span><span class="line"><span class="cl">+cursorshape       +menu              +signs             +writebackup
</span></span><span class="line"><span class="cl">+dialog_con        +mksession         +smartindent       -X11
</span></span><span class="line"><span class="cl">+diff              +modify_fname      +sound             -xfontset
</span></span><span class="line"><span class="cl">+digraphs          +mouse             +spell             -xim
</span></span><span class="line"><span class="cl">-dnd               -mouseshape        +startuptime       -xpm
</span></span><span class="line"><span class="cl">-ebcdic            +mouse_dec         +statusline        -xsmp
</span></span><span class="line"><span class="cl">+emacs_tags        +mouse_gpm         -sun_workshop      -xterm_clipboard
</span></span><span class="line"><span class="cl">+eval              -mouse_jsbterm     +syntax            -xterm_save
</span></span><span class="line"><span class="cl">+ex_extra          +mouse_netterm     +tag_binary        
</span></span><span class="line"><span class="cl">+extra_search      +mouse_sgr         -tag_old_static    
</span></span><span class="line"><span class="cl">   system vimrc file: <span class="s2">&#34;</span><span class="nv">$VIM</span><span class="s2">/vimrc</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">     user vimrc file: <span class="s2">&#34;</span><span class="nv">$HOME</span><span class="s2">/.vimrc</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"> 2nd user vimrc file: <span class="s2">&#34;~/.vim/vimrc&#34;</span>
</span></span><span class="line"><span class="cl">      user exrc file: <span class="s2">&#34;</span><span class="nv">$HOME</span><span class="s2">/.exrc</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">       defaults file: <span class="s2">&#34;</span><span class="nv">$VIMRUNTIME</span><span class="s2">/defaults.vim</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  fall-back <span class="k">for</span> <span class="nv">$VIM</span>: <span class="s2">&#34;/usr/share/vim&#34;</span>
</span></span><span class="line"><span class="cl">Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H   -Wdate-time  -g -O2 -fdebug-prefix-map<span class="o">=</span>/build/vim-iU6mZD/vim-8.1.2269<span class="o">=</span>. -fstack-protector-strong -Wformat -Werror<span class="o">=</span>format-security -D_REENTRANT -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE<span class="o">=</span><span class="m">1</span>       
</span></span><span class="line"><span class="cl">Linking: gcc   -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -o vim        -lm -ltinfo -lnsl  -lselinux  -lcanberra -lacl -lattr -lgpm -ldl     -L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -lpython3.8 -lcrypt -lpthread -ldl -lutil -lm -lm   
</span></span></code></pre>
<h2>Implementation<a name='implementation'></h2>

<p>Having compiled languages like Go or C, the build date and version can be added
at the build process by setting the corresponding variables.</p>

<p>For the date one can use <code>date '+%Y-%m-%dT%H:%M:%S%z'</code> and the latest commit sha as version via <code>git describe --always</code>.</p>

<h3>Go<a name='go'></h3>

<p>The variables <code>BuildDate</code> and <code>BuildVersion</code> can be set
during a go build like the following: <code>go build -ldflags &quot;-X main.BuildDate=&lt;date&gt; -X main.BuildVersion=&lt;version&gt;&quot;</code></p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;flag&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;fmt&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="nx">BuildDate</span>    <span class="kt">string</span>
</span></span><span class="line"><span class="cl">  <span class="nx">BuildVersion</span> <span class="kt">string</span>
</span></span><span class="line"><span class="cl">  <span class="nx">Version</span>      <span class="p">=</span> <span class="nx">flag</span><span class="p">.</span><span class="nf">Bool</span><span class="p">(</span><span class="s">&#34;version&#34;</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="s">&#34;Print build information&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">(</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">flag</span><span class="p">.</span><span class="nf">Parse</span><span class="p">(</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="o">*</span><span class="nx">Version</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;BuildVersion: &#34;</span><span class="p">,</span> <span class="nx">BuildVersion</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;BuildDate: &#34;</span><span class="p">,</span> <span class="nx">BuildDate</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<h3>C<a name='c'></h3>

<p>With the gcc version and date can be added as key-value pair using the <code>-D</code> prefix like the following:
<code>gcc -DBUILD_DATE=&quot;\&quot;DATE\&quot;&quot; -DBUILD_VERSION=&quot;\&quot;VERSION\&quot;&quot; main.c</code></p>

<p>Where <code>main.c</code> looks like this:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#</span><span class="cp">ifndef BUILD_DATE</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">define BUILD_DATE &#34;BUILD_DATE is missing&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">endif</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#</span><span class="cp">ifndef BUILD_VERSION</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">define BUILD_VERSION &#34;BUILD_VERSION is missing&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="cp">#</span><span class="cp">endif</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span> <span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span><span class="n">argv</span><span class="p">[</span><span class="p">]</span> <span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span><span class="p">(</span> <span class="n">argc</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="o">&amp;</span><span class="o">&amp;</span> <span class="n">strcmp</span><span class="p">(</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="p">,</span> <span class="sa"></span><span class="s">&#34;</span><span class="s">--version</span><span class="s">&#34;</span> <span class="p">)</span> <span class="o">=</span><span class="o">=</span> <span class="mi">0</span> <span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">printf</span><span class="p">(</span> <span class="sa"></span><span class="s">&#34;</span><span class="s">BuildDate: %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">BUILD_DATE</span> <span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">printf</span><span class="p">(</span> <span class="sa"></span><span class="s">&#34;</span><span class="s">BuildVersion: %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">BUILD_VERSION</span> <span class="p">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<h2>Further ideas<a name='ideas'></h2>

<p>Some inspiration which variables could be added to the build information:</p>

<ul>
<li>last commit message</li>
<li>last committer</li>
<li>version of the compiler/runtime</li>
<li>target platform</li>
</ul>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Tue, 12 Jan 2021 12:45:38 +0100</pubDate>
    </item>
    <item>
      <title>AoC day7</title>
      <link>https://evilcookie.de/aoc-day7.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>AoC day7</h1>

<p>Today&rsquo;s puzzles were about bags which contain a certain amount of other bags (and
so on) based on the rules from the input. The first one asks for the amount of
different bags in which our -shiny gold- one is contained. The second one asks
for the count of bags the own contains.</p>

<h2>Abstraction</h2>

<p>Let&rsquo;s say each bag is a node and each rule is an edge with the count as
edge-value. Then this problem can be converted into a <em>graph theory</em> one. Since
this puzzle is solvable it can be assumed that the graph has no circles.
Furthermore it can be assumed that this graph is a tree starting with the own
bag -shiny gold- as root. Bags which contain no further one are the leaves. All
other graphs not related to this tree (if any) are irrelevant and can be ignored.</p>

<p>This tree can be traversed for both puzzles recursively with an ordinary depth
search. Below is an implementation of a depth search finding a node in a given
tree.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Node</span> <span class="p">[</span><span class="p">]</span><span class="kt">string</span>
</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Tree</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="nx">Node</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">depthSearch</span><span class="p">(</span><span class="nx">current</span><span class="p">,</span> <span class="nx">goal</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">tree</span> <span class="nx">Tree</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="nx">current</span> <span class="o">==</span> <span class="nx">goal</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="nx">subNode</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">tree</span><span class="p">[</span><span class="nx">current</span><span class="p">]</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="nf">depthSearch</span><span class="p">(</span><span class="nx">subNode</span><span class="p">,</span> <span class="nx">goal</span><span class="p">,</span> <span class="nx">tree</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>In this simplified depth search, a tree maps nodes name to a node. A node is a list of all related sub nodes identified by node names.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Node</span> <span class="p">[</span><span class="p">]</span><span class="kt">string</span>
</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Tree</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="nx">Node</span>
</span></span></code></pre>
<p>The signature takes the current- such as the goal node name and the tree itself
returning if the goal has been reached.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">depthSearch</span><span class="p">(</span><span class="nx">current</span><span class="p">,</span> <span class="nx">goal</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">tree</span> <span class="nx">Tree</span><span class="p">)</span> <span class="kt">bool</span> 
</span></span></code></pre>
<p>The abort condition of this recursion is satisfied if the goal has been reached.
One can move this condition to the sub node loop. But imo it is code style to
put it at the very first showing any reader when this recursion ends such as
preventing errors leading to stack overflows.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">if</span> <span class="nx">current</span> <span class="o">==</span> <span class="nx">goal</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>To go in depth, the loop iterates over all sub nodes and calls itself for each
one. On reaching the goal the search immediately returns <code>true</code> and arises from
the depth. If the goal hasn&rsquo;t been reached a search terminates if a node hasn&rsquo;t any further sub nodes.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">for</span> <span class="nx">subNode</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">tree</span><span class="p">[</span><span class="nx">current</span><span class="p">]</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="nf">depthSearch</span><span class="p">(</span><span class="nx">subNode</span><span class="p">,</span> <span class="nx">goal</span><span class="p">,</span> <span class="nx">tree</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="kc">false</span>
</span></span></code></pre>
<h2>Puzzle 1 - Find node</h2>

<p>It should be counted how many nodes contain our -shiny gold- bag. This can be
accomplished by searching it in each unique node and round the times it could be
found.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nx">found</span> <span class="o">:=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">tree</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="nf">depthSearch</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="s">&#34;shiny gold&#34;</span><span class="p">,</span> <span class="nx">tree</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">found</span><span class="o">++</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>The code from the last section can be used directly for the search.</p>

<h2>Puzzle 2 - Count payload</h2>

<p>In this puzzle, each bag has various amounts of sub nodes. Those amounts are not
relevant for the search itself and called payload from here.</p>

<p>In contrast to the abstraction the below function is more a graph traversal than
a search. Since the payload of all nodes is needed to calculate the total count
of bags, the whole tree has to be traversed.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Node</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int</span>
</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Tree</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="nx">Node</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">DepthSearch</span><span class="p">(</span><span class="nx">current</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">tree</span> <span class="nx">Tree</span><span class="p">)</span> <span class="kt">int</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">total</span> <span class="o">:=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="nx">subNode</span><span class="p">,</span> <span class="nx">count</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">tree</span><span class="p">[</span><span class="nx">current</span><span class="p">]</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">total</span> <span class="o">+=</span> <span class="nx">count</span> <span class="o">*</span> <span class="nf">DepthSearch</span><span class="p">(</span><span class="nx">subNode</span><span class="p">,</span> <span class="nx">tree</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">total</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>Each node is now a mapping from sub node names to its payload. A tree is still a mapping from node name to node.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Node</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int</span>
</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Tree</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="nx">Node</span>
</span></span></code></pre>
<p>No goal is necessary anymore since all nodes have to be visited and the search returns the total amount based on the given calculation from AoC.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">DepthSearch</span><span class="p">(</span><span class="nx">current</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">tree</span> <span class="nx">Tree</span><span class="p">)</span> <span class="kt">int</span>
</span></span></code></pre>
<p>Initially, the total amount of <em>sub bags</em> is set to one in order to return the
count for the current bag itself. This is also the reason why the final count is
off by one. For example: A tree only containing our -shiny bag- has a count of zero and not the count of contained bags.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nx">total</span> <span class="o">:=</span> <span class="mi">1</span>
</span></span></code></pre>
<p>Using the payload and the return value of the
depth search, the amount of all bags inside one sub bag can be calculated.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">for</span> <span class="nx">subNode</span><span class="p">,</span> <span class="nx">count</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">tree</span><span class="p">[</span><span class="nx">current</span><span class="p">]</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">total</span> <span class="o">+=</span> <span class="nx">count</span> <span class="o">*</span> <span class="nf">DepthSearch</span><span class="p">(</span><span class="nx">subNode</span><span class="p">,</span> <span class="nx">tree</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>Finally return the calculated/found amount of bags. Note that the definition of
<code>total</code> and this return will be the only effective lines in leaves (nodes
without any sub nodes).</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="k">return</span> <span class="nx">total</span>
</span></span></code></pre>
<p>PS: I need to find alternatives for &lsquo;the&rsquo; beginning of sentences&hellip;</p>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Mon, 07 Dec 2020 18:35:56 +0100</pubDate>
    </item>
    <item>
      <title>AoC day1</title>
      <link>https://evilcookie.de/aoc-day1.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>AoC day 1</h1>

<p>The puzzles of day one were easy to solve in the first place, but have more
potential to optimize than I thought.</p>

<h2>Problem</h2>

<p><em>Find n addends which add up to 2020. Solution of the puzzle is the product of all addends</em> where <code>n=2</code> in puzzle one and <code>n=3</code> in puzzle two.</p>

<h2>Solution</h2>

<p>The idea was to find all unique subsets with n elements, where <code>n=2</code> in the
algorithm below.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="c1">// ex: input array of integers
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="nx">ex</span><span class="p">)</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="nx">j</span> <span class="o">:=</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">j</span> <span class="p">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="nx">ex</span><span class="p">)</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="nx">ex</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="o">+</span><span class="nx">ex</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="o">==</span> <span class="mi">2020</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;Found %d + %d = 2020\n&#34;</span><span class="p">,</span> <span class="nx">ex</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="p">,</span> <span class="nx">ex</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%d x %d = %d\n&#34;</span><span class="p">,</span> <span class="nx">ex</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="p">,</span> <span class="nx">ex</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span><span class="p">,</span> <span class="nx">ex</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">*</span> <span class="nx">ex</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre>
<p>The count of nested loops is equal to <code>n</code> which makes each subset accessible in
the innermost loop. To ensure that the subset is unique, each inner loop starts
with the index of the next outer loop plus one. By adding one all subsets are
being skipped which share the same number.</p>

<p>Uniqueness is important to conquer both: Performance and wrong solutions.
With unique subsets less than half the sums have to be calculated. Despite that,
the puzzle says that all addends have to be different.</p>

<h2>Visualization</h2>

<p>On <code>n=2</code>, a simple brute force approach where the indices of all nested loops
start at zero could be visualized with the following table. It shows the sum of
<em>all</em> subsets with two elements made up from the input .</p>

<table>
<thead>
<tr>
<th></th>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
</tr>
</thead>

<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>

<tr>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>

<tr>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>

<tr>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
</tr>
</tbody>
</table>
<p>The first observation one can make is the symmetry of the table. This is
caused by the <em>commutation property of addition</em> which basically states that
<code>x+y = y+x</code>. Good for us, we can get rid of almost one half and reduce the iteration count.</p>

<p>The next observation, is the diagonal. It is only made up of sums where the addends are equal. Better for us, we can get rid of them
either.</p>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Tue, 01 Dec 2020 13:03:45 +0100</pubDate>
    </item>
    <item>
      <title>AoC</title>
      <link>https://evilcookie.de/aoc.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>AoC</h1>

<p>The annual advent-of-code challenge is starting again at first of December. Ruby
was my last years choice of language, which I also used to do the <a href="https://github.com/RaphaelPour/advent-of-code">2015
event</a> for preparation. This year I&rsquo;ll use Go
since the majority of my daily projects are Go ones. My primary goal is to at
least try any puzzle and secondary write a post for the most interesting
solutions I came up with.</p>

<h2>Experience</h2>

<p>All puzzles are based on some kind of data transformation. You&rsquo;ll get an
input and have to transform it to get the solution.
Ruby is a good first AoC language since parsing and transforming data are easy
to implement out-of-the-box with native regex-support and a lot of map-reduce
functions.</p>

<h2>Expectation</h2>

<p>Using Go over Ruby for the same kind of data transformation is more complex and
time-consuming. Go has no native map-reduce and therefore all transformations
have to be done manually with (nested) loops which also get unreadable with
higher complexity.
On the other side I want to gain more experience with Go, since I&rsquo;m fairly new
to the language while I wrote my first line of code around December 2019.</p>

<h2>References</h2>

<ul>
<li><a href="https://adventofcode.com/">Advent of code</a></li>
<li><a href="https://github.com/RaphaelPour/aoc2020">My solutions</a></li>
</ul>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Tue, 24 Nov 2020 13:09:39 +0100</pubDate>
    </item>
    <item>
      <title>Hello internet</title>
      <link>https://evilcookie.de/hello-internet.html</link>
      <description></description>
      <content:encoded><![CDATA[<h1>Hello internet</h1>

<p>This blog is managed via <a href="https://github.com/RaphaelPour/blogctl">blogctl</a> and served via caddy container half-automatic.
I build blogctl and the edit-and-publish workflow with the following things in
mind:</p>

<ul>
<li>Focus: CLI-only, no distractions</li>
<li>Simplicity: Only the features currently needed</li>
<li>Minimalism: Focus on content and not style</li>
</ul>

<p>That&rsquo;s my premise for writing blog posts at least mid-term. I am easily
distractible and need a clean environment.</p>
]]></content:encoded>
      <author>Raphael Pour</author>
      <pubDate>Sun, 04 Oct 2020 14:07:48 +0200</pubDate>
    </item>
  </channel>
</rss>