<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Will BL</title>
    <description>The latest articles on DEV Community by Will BL (@williambl).</description>
    <link>https://dev.to/williambl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F255612%2Fdcb60a38-4f30-45b4-a526-ade440d0de2d.png</url>
      <title>DEV Community: Will BL</title>
      <link>https://dev.to/williambl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/williambl"/>
    <language>en</language>
    <item>
      <title>Can AI Deobfuscate Minecraft?</title>
      <dc:creator>Will BL</dc:creator>
      <pubDate>Thu, 05 Jan 2023 19:05:19 +0000</pubDate>
      <link>https://dev.to/williambl/can-ai-deobfuscate-minecraft-1bo6</link>
      <guid>https://dev.to/williambl/can-ai-deobfuscate-minecraft-1bo6</guid>
      <description>&lt;p&gt;OpenAI's ChatGPT, like many similar Large Language Models, has been used to perform many programming-related tasks. Writing obfuscation mappings seems to be a good fit for its abilities, as it involves reading and summarising text (code). I tested its capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;If you already understand what obfuscation mappings are, feel free to skip this part.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Minecraft: Java Edition&lt;/em&gt; is a game written in Java (&lt;em&gt;quelle surprise&lt;/em&gt;). Java source code is compiled to JVM bytecode for distribution, a little like the relationship between C and machine code.&lt;/p&gt;

&lt;p&gt;To modify the game, we want access to the Java source. However, there are two things in the way:&lt;/p&gt;

&lt;p&gt;Firstly, we have to &lt;em&gt;decompile&lt;/em&gt; the JAR, turning the bytecode back into Java. This is a very difficult job: a lot of work has been put into the &lt;a href="https://github.com/QuiltMC/quiltflower/" rel="noopener noreferrer"&gt;tools&lt;/a&gt; to make this happen.&lt;/p&gt;

&lt;p&gt;However, even then, we do not have readable code: Mojang, the developers of Minecraft, put their code through &lt;a href="https://www.guardsquare.com/proguard" rel="noopener noreferrer"&gt;ProGuard&lt;/a&gt;, which shrinks the bytecode by doing things such as renaming all methods and classes to things like &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, &lt;code&gt;c&lt;/code&gt;, &lt;code&gt;az&lt;/code&gt;, and so on. So we need a &lt;em&gt;mapping&lt;/em&gt; from these obfuscated names to readable names!&lt;/p&gt;

&lt;p&gt;For a while, the main mappings available were made by the &lt;a href="http://www.modcoderpack.com/" rel="noopener noreferrer"&gt;MCP&lt;/a&gt; project, and had a restrictive license. These were used first by MCP itself, and later &lt;a href="https://minecraftforge.net/" rel="noopener noreferrer"&gt;Minecraft Forge&lt;/a&gt;, a modloader and API.&lt;/p&gt;

&lt;p&gt;When &lt;a href="https://fabricmc.net/" rel="noopener noreferrer"&gt;Fabric&lt;/a&gt;, another modloader/API project, came onto the scene in 2018, it had to make its own mappings, which it called Yarn. It made Yarn freely available (CC-0), and effected a 'cleanroom policy' - no MCP names were to be mentioned in any Fabric community spaces, in case a Yarn contributor was 'tainted' by the strictly-licensed MCP mappings.&lt;/p&gt;

&lt;p&gt;And so it came to pass that the mappings were fractured; for there were two names for each class. "Lo," &lt;a href="https://www.minecraft.net/en-us/article/minecraft-snapshot-19w36a" rel="noopener noreferrer"&gt;said Mojang&lt;/a&gt;, "we shall bestow unto them an Official Mappings set, exported from Proguard itself".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffxtymqcirbyiz3riq652.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffxtymqcirbyiz3riq652.png" alt="XKCD Standards Comic" width="500" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Forge quickly switched to the Official Mappings. Fabric decided that a non-public domain mappings set wouldn't do; and besides, these names were all a bit strange and unlike what they were used to anyway, so they would prefer to maintain and use their own mappings, thank you very much.&lt;/p&gt;

&lt;p&gt;These days, there are four main mappings sets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://piston-data.mojang.com/v1/objects/42366909cc612e76208d34bf1356f05a88e08a1d/client.txt" rel="noopener noreferrer"&gt;Official Mappings&lt;/a&gt; (aka. Mojmap) exactly like what Mojang sees but without parameter names.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://parchmentmc.org/" rel="noopener noreferrer"&gt;Parchment&lt;/a&gt;, a project to create mappings for parameter names, and also including Javadoc, to be layered on top of the Official Mappings.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/fabricMC/yarn" rel="noopener noreferrer"&gt;Yarn&lt;/a&gt;, still going with its cleanroom meant to protect against a mappings set that no longer exists.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/QuiltMC/quilt-mappings/" rel="noopener noreferrer"&gt;Quilt Mappings&lt;/a&gt;. Quilt is a fork of Fabric made by many former-Fabric developers. Quilt Mappings are like Yarn, but without a cleanroom, and so may take inspiration from the Official Mappings. Its main purpose is to be like Yarn, but Mojmappier, or to be like Mojmap, but Yarnier - depending on who you ask.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  First Tests
&lt;/h2&gt;

&lt;p&gt;First, I set up a Quilt Mappings workspace. Why Quilt Mappings and not Yarn? Two reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;QM is missing mappings for more things, so it was easier to find obfuscated names for testing.&lt;/li&gt;
&lt;li&gt;The QM workspace allows using the &lt;a href="https://github.com/QuiltMC/quiltflower/" rel="noopener noreferrer"&gt;QuiltFlower&lt;/a&gt; decompiler, which can produce much nicer output than many other decompilers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It took me a few tries to find a prompt that worked well. I settled on this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have this Java method in the class &lt;code&gt;ClassName&lt;/code&gt;, but I don't know what to call it:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;code snippet
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Please suggest a name for this method and each of its parameters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  NativeImage#copyRect
&lt;/h3&gt;

&lt;p&gt;I first tried this method in &lt;code&gt;NativeImage&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;m_vmneozhc&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NativeImage&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;bl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;bl2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bl&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bl2&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPixelColor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setPixelColor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fthhs3f8swyln21yt6ly3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fthhs3f8swyln21yt6ly3.png" alt="Will asks ChatGPT to name the method and each parameter. It replies with 'copyImage - sourceImage, sourceX, sourceY, targetX, targetY, width, height, flipHorizontally, flipVertically'" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It suggests I call the method &lt;code&gt;copyImage(NativeImage sourceImage, int sourceX, int sourceY, int targetX, int targetY, int width, int height, boolean flipHorizontally, boolean flipVertically)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is pretty good! Mojang calls the method &lt;code&gt;copyRect&lt;/code&gt;, quite similar to ChatGPT's naming. It also names the parameters sensibly.&lt;/p&gt;

&lt;h3&gt;
  
  
  LocalPlayer#sendIsSprintingIfNeeded
&lt;/h3&gt;

&lt;p&gt;Next, I tried this method, in the class which QM calls &lt;code&gt;ClientPlayerEntity&lt;/code&gt; (but Mojang calls &lt;code&gt;LocalPlayer&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;m_nfwipcth&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;bl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isSprinting&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bl&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lastSprinting&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;ClientCommandC2SPacket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Mode&lt;/span&gt; &lt;span class="n"&gt;lv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bl&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nc"&gt;ClientCommandC2SPacket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Mode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;START_SPRINTING&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ClientCommandC2SPacket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Mode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;STOP_SPRINTING&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;networkHandler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendPacket&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ClientCommandC2SPacket&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lv&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lastSprinting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1x2u5a8mxthadnfco9f6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1x2u5a8mxthadnfco9f6.png" alt="Will asks ChatGPT to name the method. It replies with 'updateSprintingStatus'" width="799" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It suggests &lt;code&gt;updateSprintingStatus()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is &lt;em&gt;not wrong&lt;/em&gt;, but it's a bit generic as a name - it doesn't capture that it involves telling the server over the network about the player's sprinting status.&lt;/p&gt;

&lt;h3&gt;
  
  
  MultiPlayerGameMode#performUseItemOn
&lt;/h3&gt;

&lt;p&gt;Lets try a longer method. I'm not going to show you the whole method this time (Minecraft is closed-source, after all), but I'll show you a snippet of this method in the class QM calls &lt;code&gt;ClientPlayerInteractionManager&lt;/code&gt;, and Mojang calls &lt;code&gt;MultiPlayerGameMode&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;ActionResult&lt;/span&gt; &lt;span class="nf"&gt;m_wiqrsdhj&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ClientPlayerEntity&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Hand&lt;/span&gt; &lt;span class="n"&gt;arg2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BlockHitResult&lt;/span&gt; &lt;span class="n"&gt;arg3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;BlockPos&lt;/span&gt; &lt;span class="n"&gt;lv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arg3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBlockPos&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;ItemStack&lt;/span&gt; &lt;span class="n"&gt;lv2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getStackInHand&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gameMode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;GameMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SPECTATOR&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ActionResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SUCCESS&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ar76hmm1k4vfq7555u1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ar76hmm1k4vfq7555u1.png" alt="Will asks ChatGPT to name the method and each parameter. It replies with 'attemptBlockInteraction - player, hand, blockHitResult'" width="786" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is alright. The method is run when right-clicking on a block - but only when holding an item. ChatGPT's name doesn't really capture this. Still, it's less ugly than Mojang's &lt;code&gt;performUseItemOn&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can it do more?
&lt;/h2&gt;

&lt;p&gt;So ChatGPT can name methods, not perfectly, but alright. But can it map whole classes?&lt;/p&gt;

&lt;p&gt;I tried it out with this prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have this Java class, but all the names are garbled:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;code snippet
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;For context, &amp;lt;context of how the class is used&amp;gt;.&lt;/p&gt;

&lt;p&gt;For each garbled name, suggest a proper name.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  BlockStatePredictionHandler
&lt;/h3&gt;

&lt;p&gt;I found a class which wasn't mapped in QM - Mojang calls it &lt;code&gt;BlockStatePredictionHandler&lt;/code&gt; - and stuck it in the prompt. I added some context, too:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For context, the class &lt;code&gt;ClientWorld&lt;/code&gt; has a private final field of this class. The methods of this class are called from the classes &lt;code&gt;ClientWorld&lt;/code&gt; and &lt;code&gt;ClientPlayerInteractionManager&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0p9cgtjy385w7y3q9nfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0p9cgtjy385w7y3q9nfz.png" alt="Will asks ChatGPT to name the symbols in the class. It replies with the results shown below" width="800" height="662"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Placeholder&lt;/th&gt;
&lt;th&gt;Mojmap&lt;/th&gt;
&lt;th&gt;ChatGPT&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;C_czisrdmd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;BlockStatePredictionHandler&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;BlockStateTracker&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;f_irkdwisi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;serverVerifiedStates&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;blockStateMap&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;f_hcvpxtyt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;currentSequenceNr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tickCounter&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;f_bmpbngyn&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;isPredicting&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;isTracking&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_plwiurco&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;retainKnownServerState&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;addBlockState&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_mmtdqsga&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;updateKnownServerState&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;updateBlockState&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_vfahppjl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;endPredictionsUpTo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rollbackBlockStates&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_rhbdpkkw&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;startPredicting&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;startTracking&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;close&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;&lt;code&gt;stopTracking&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_gqtwgmpw&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;currentSequence&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;getTickCounter&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_nssimvch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;isPredicting&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;isTracking&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;C_ivvmpfib&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ServerVerifiedState&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TrackedBlockState&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;f_bfinrexc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;playerPos&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;playerPosition&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;f_ovpelcnt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sequence&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;trackedTick&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;state&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;blockState&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;blockState&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_twfpffxt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;setSequence&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;updateTrackedTick&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_fxchmlnj&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;setBlockState&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;updateBlockState&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;While ChatGPT's names are coherent, and certainly consistent (see the consistency between fields and their getters/setters), it has a few flaws. See, for example, how it tried to rename &lt;code&gt;close&lt;/code&gt;, a non-obfuscated name inherited from Java's &lt;code&gt;AutoCloseable&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I didn't know what this class was actually for, so I asked ChatGPT - perhaps this would also give us some insight into why it named the symbols in the way it did?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fka514zij1emgcl66v4vv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fka514zij1emgcl66v4vv.png" alt="Will asks ChatGPT what the class does. It replies: " width="795" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last part of that, at least, is completely incorrect - block changes made by a player in creative mode are definitely &lt;em&gt;not&lt;/em&gt; rolled back when the player leaves the game. This cast doubt on the rest of the explanation, so I searched through a few Discord servers to see if anyone else had an explanation.&lt;/p&gt;

&lt;p&gt;Here's a (trimmed down) explanation by &lt;a href="https://github.com/SizableShrimp" rel="noopener noreferrer"&gt;SizableShrimp&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Basically, clients keep track of a sequence counter in their &lt;code&gt;BlockStatePredictionHandler&lt;/code&gt;. When client wants to perform any block modifying actions from &lt;code&gt;MultiPlayerGameMode&lt;/code&gt;, it will gen a new sequence number by increasing the counter.&lt;br&gt;
Now, while in prediction mode, any calls to &lt;code&gt;ClientLevel#setBlock&lt;/code&gt; will not be actually set in-world! They will be stored in the prediction handler.&lt;br&gt;
Now, after client finishes its clientside block-modifying action, this sequence number is sent to the server alongside the action the client is requesting to do. Server will then do the block-modifying action that the client requested (if possible).&lt;br&gt;
Once the server is "done", it will send a packet back to the client that initiated the action to process all block sequences up to that sequence id.&lt;br&gt;
They use this predictive action system thingy so that there aren't visual glitches on the client when what the client thinks should happen is different from what the server actually performs.&lt;br&gt;
The client will now delay setting blocks during predictive actions, wait for a server response on what actually happened, and then update it on the client.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(Full explanation is available in &lt;a href="https://discord.com/channels/313125603924639766/978656989506830406/982904891724927027" rel="noopener noreferrer"&gt;this message&lt;/a&gt; on the Forge Discord)&lt;/p&gt;

&lt;p&gt;Interesting - so ChatGPT correctly told us that the class tracks block changes and can roll them back, but it misinterprets the sequence number as a tick counter, and doesn't understand that the class is used to hold off on committing to clientside predictions until verified by the server.&lt;/p&gt;

&lt;p&gt;It doesn't understand &lt;em&gt;anything&lt;/em&gt;, in fact. This is one of the flaws of asking ChatGPT to explain something to you - it has no consistent internal model of the world. ChatGPT, like other Large Language Models, is able only to read some text and write more text that sounds like it should come after - as a result, it is very prone to giving completely incorrect answers about things while sounding very confident and authoritative.&lt;/p&gt;

&lt;h3&gt;
  
  
  MatrixUtil
&lt;/h3&gt;

&lt;p&gt;Let's try one more class. This one has some methods for messing with matrices. It's unmapped in QM; Mojang calls it &lt;code&gt;MatrixUtil&lt;/code&gt;. It's quite long (~200 lines) compared to our other tests.&lt;/p&gt;

&lt;p&gt;I gave ChatGPT the class, with the context:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For context, &lt;code&gt;m_xockxffa&lt;/code&gt; is called from the class &lt;code&gt;ItemRenderer&lt;/code&gt;, and &lt;code&gt;m_jeovkadj&lt;/code&gt; and &lt;code&gt;m_ibrymiig&lt;/code&gt; are called from the class &lt;code&gt;AffineTransformation&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnm0gqw3ocwq4xx3sso6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnm0gqw3ocwq4xx3sso6.png" alt="Will asks ChatGPT to name the symbols in the class. It replies with the results shown below" width="794" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Placeholder&lt;/th&gt;
&lt;th&gt;Mojmap&lt;/th&gt;
&lt;th&gt;ChatGPT&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;C_bmzqkdhp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MatrixUtil&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MatrixMathHelper&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;f_arxnkhow&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;G&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RADIUS_FACTOR&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;f_ddnzxrmh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;COSINE_OF_45_DEGREES&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;f_kqccjreh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SINE_OF_45_DEGREES&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_xockxffa&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mulComponentWise&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;scaleMatrix&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_kcqrzkbi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;approxGivensQuat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;computeUnitVectors&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_kniviwwf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;qrGivensQuat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;computeUnitVectorsFromYawPitch&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_skxdryqk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;stepJacobi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;computeQuaternionFromMatrix&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_kkfnnzhk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;&lt;code&gt;computeQuaternionFromYawPitch&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_kjbxjxks&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;&lt;code&gt;computeUnitVectorsFromQuaternion&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_pjmgwfwq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;&lt;code&gt;computeMatrixFromQuaternion&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_geumxflx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;&lt;code&gt;computeMatrixFromYawPitch&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_ibrymiig&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;svdDecompose&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m_jeovkadj&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;toAffine&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Whoever named the constants must've been a mathematician.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ChatGPT has a good start: &lt;code&gt;MatrixMathHelper&lt;/code&gt; is a solid name; &lt;code&gt;SINE&lt;/code&gt; and &lt;code&gt;COSINE&lt;/code&gt; &lt;code&gt;_OF_45_DEGREES&lt;/code&gt; is descriptive (and impressive, seeing as it's computed in radians). Unfortunately, it goes downhill from there.&lt;/p&gt;

&lt;p&gt;The rest of the names &lt;em&gt;look&lt;/em&gt; descriptive - in many cases, they look at first glance to be &lt;em&gt;better&lt;/em&gt; names than Mojang's. But once again, it's a case of ChatGPT being very good at sounding confident whilst being totally incorrect.&lt;/p&gt;

&lt;p&gt;The so-called &lt;code&gt;scaleMatrix&lt;/code&gt; method, taking a 4x4 Matrix and a float and returning a matrix with each element multiplied by the float, is named in a way that confuses matrix-scalar multiplication with the linear transformation of scaling.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;computeQuaternionFromMatrix&lt;/code&gt; is a technically-correct name - the method takes a 3x3 matrix and returns a quaternion. But it fails to convey what the method actually &lt;em&gt;does&lt;/em&gt;. &lt;code&gt;stepJacobi&lt;/code&gt; at least points you &lt;a href="https://en.wikipedia.org/wiki/Jacobi_method" rel="noopener noreferrer"&gt;in the right direction&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There's an even more damning problem, though: ChatGPT started hallucinating methods.&lt;/p&gt;

&lt;p&gt;In the table, you'll see some methods for which there are no ChatGPT names (because it got distracted and didn't name them), and some without Mojang names (because they don't exist - ChatGPT made them up).&lt;/p&gt;

&lt;p&gt;Oh dear.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;ChatGPT is an interesting tool. There is no doubt that it is very good at text prediction and generation. This sometimes generalises to being able to paraphrase, summarise, and appear to understand the meaning behind text. This is not true - it cannot understand meaning.&lt;/p&gt;

&lt;p&gt;For deobfuscation name mapping, Large Language models such as ChatGPT may be useful as &lt;a href="https://medium.com/tenable-techblog/g-3po-a-protocol-droid-for-ghidra-4b46fa72f1ff" rel="noopener noreferrer"&gt;assistive tools&lt;/a&gt;. They cannot be relied on to automate the naming process.&lt;/p&gt;

&lt;p&gt;In the specific case of Minecraft, with the existence of Mojmap, there is limited value in maintaining alternate mappings. There is more value in augmenting Mojmap, e.g. with Parchment. Therefore it would be useful to see how the process of mapping parameter names and writing Javadoc can be made more efficient.&lt;/p&gt;

&lt;p&gt;There is less room for error in parameter naming than class/member naming. Large Language Models could be used to help automate this process - however, specialised non-ML tools may be as or more useful.&lt;/p&gt;

&lt;p&gt;Stay tuned - I will test ChatGPT's ability to write Javadoc for decompiled methods in another post. I don't suspect it will do very well.&lt;/p&gt;

&lt;p&gt;Thanks to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shedaniel's &lt;a href="https://linkie.shedaniel.me/mappings" rel="noopener noreferrer"&gt;Linkie&lt;/a&gt;, an enormously useful tool for translating between mappings.&lt;/li&gt;
&lt;li&gt;The QM and Yarn &lt;a href="https://github.com/QuiltMC/quilt-mappings/graphs/contributors" rel="noopener noreferrer"&gt;contributors&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://openai.com/blog/chatgpt/" rel="noopener noreferrer"&gt;OpenAI&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The Quiltflower &lt;a href="https://github.com/QuiltMC/quiltflower/graphs/contributors" rel="noopener noreferrer"&gt;contributors&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>Top 5 IntelliJ IDEA Tips &amp; Tricks!</title>
      <dc:creator>Will BL</dc:creator>
      <pubDate>Sun, 26 Sep 2021 18:16:39 +0000</pubDate>
      <link>https://dev.to/williambl/top-5-intellij-idea-tips-tricks-3cid</link>
      <guid>https://dev.to/williambl/top-5-intellij-idea-tips-tricks-3cid</guid>
      <description>&lt;p&gt;&lt;a href="https://www.jetbrains.com/idea/" rel="noopener noreferrer"&gt;IntelliJ IDEA&lt;/a&gt; is an excellent all-rounder IDE by Jetbrains. It's most often used for Java and Kotlin, but can also be used to develop for JS, Rust, and many more languages. It's what I use for most of my programming, and so I thought I'd share what config tweaks, tricks, and plugins I've used that make it nicer.&lt;/p&gt;

&lt;h1&gt;
  
  
  Darcula? Make it darker!
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhe73qmxss6olwwyjcao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhe73qmxss6olwwyjcao.png" alt="An IntelliJ window with Darcula Darker theme"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Darcula is a very nice theme, but it always bugged me that it wasn't nearly as dark as the light theme is light. It felt like there was more potential there. &lt;a href="https://plugins.jetbrains.com/plugin/12692-darcula-darker-theme" rel="noopener noreferrer"&gt;Darcula Darker, by Vecheslav Druzhbin&lt;/a&gt;, darkens backgrounds, contrasting it more against text.&lt;/p&gt;

&lt;h1&gt;
  
  
  Rainbow Brackets
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj7b89ucycppjlpasvcts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj7b89ucycppjlpasvcts.png" alt="An example of rainbow brackets"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://plugins.jetbrains.com/plugin/10080-rainbow-brackets" rel="noopener noreferrer"&gt;This plugin&lt;/a&gt; may sound silly at first, but rainbow brackets honestly vastly improves readability of nested brackets. It works by giving each pair of brackets its own colour, so that nested sets are visually distinct.&lt;/p&gt;

&lt;p&gt;While we're on the rainbow topic, for those who work with CSV files often, &lt;a href="https://plugins.jetbrains.com/plugin/12896-rainbow-csv" rel="noopener noreferrer"&gt;Rainbow CSV&lt;/a&gt; may be useful.&lt;/p&gt;

&lt;h1&gt;
  
  
  Errors should be visible!
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3ibfwi8pgxur0znmngp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3ibfwi8pgxur0znmngp.png" alt="Code with an error highlighted in red"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sometimes, in very dense code, it can be difficult to find a single-character syntax error at a glance, as its signified by a tiny red squiggly line. How do you fix that, and make it stand out? Add a red highlight, too!&lt;/p&gt;

&lt;p&gt;(This can be done by going into Settings -&amp;gt; Editor -&amp;gt; Color Scheme -&amp;gt; General -&amp;gt; Errors and Warnings -&amp;gt; Error and setting Background to #630202)&lt;/p&gt;

&lt;h1&gt;
  
  
  Comments are for humans
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgcfufg9d2jjw724bzdw1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgcfufg9d2jjw724bzdw1.png" alt="Some code with bright pink comments"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One thing I will never understand is that comments, despite being more for humans' benefit than &lt;em&gt;the rest of the code&lt;/em&gt;, are always put in low-contrast greys, as if the machine, envious that it cannot read them, doesn't want me to be able to either.&lt;/p&gt;

&lt;p&gt;So make your comments bright pink.&lt;/p&gt;

&lt;p&gt;(This can be done by going into Settings -&amp;gt; Editor -&amp;gt; Color Scheme -&amp;gt; Language Defaults -&amp;gt; Block Comment + Line Comment and setting Foreground to #FC7CE1)&lt;/p&gt;

&lt;h1&gt;
  
  
  nya-nya-nya-nya-nya (or is it nyan-nyan-nyan?)
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsds8n1iwx1lidijqk5le.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsds8n1iwx1lidijqk5le.png" alt="A nyan cat progress bar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don't have any reason for &lt;a href="https://plugins.jetbrains.com/plugin/8575-nyan-progress-bar" rel="noopener noreferrer"&gt;this&lt;/a&gt; other than that it makes me smile. But do I really need another reason?&lt;/p&gt;

&lt;h1&gt;
  
  
  More!
&lt;/h1&gt;

&lt;p&gt;I have yet more &lt;em&gt;opinions&lt;/em&gt; on how to get the most out of your editor - follow me to get notified when part two of this series is out! You'll get to learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to get even more powerful git support&lt;/li&gt;
&lt;li&gt;How you might be able to get IntelliJ IDEA Ultimate for free&lt;/li&gt;
&lt;li&gt;Which side of the Emacs v. Vim editor war I'm on!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ide</category>
      <category>intellij</category>
      <category>java</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>Let's write a tiny JSON parser in Kotlin! Part 4: Strings</title>
      <dc:creator>Will BL</dc:creator>
      <pubDate>Thu, 20 May 2021 13:36:53 +0000</pubDate>
      <link>https://dev.to/williambl/let-s-write-a-tiny-json-parser-in-kotlin-part-4-strings-1bc</link>
      <guid>https://dev.to/williambl/let-s-write-a-tiny-json-parser-in-kotlin-part-4-strings-1bc</guid>
      <description>&lt;p&gt;Today we're going to learn how to parse strings in JSON. This is more complicated than the datatypes we've done so far, but don't worry, it's not bad :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;Let's recall our string definition from part 0:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A &lt;strong&gt;string&lt;/strong&gt; is a string of characters enclosed within double quotes (&lt;code&gt;"&lt;/code&gt;). Any character can be put within a string, except for the following, which must be escaped:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;double quotes (&lt;code&gt;"&lt;/code&gt;) [Escaped with &lt;code&gt;\"&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;backslash (&lt;code&gt;\&lt;/code&gt;) [Escaped with &lt;code&gt;\\&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;backspace [Escaped with &lt;code&gt;\b&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;form feed [Escaped with &lt;code&gt;\f&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;line feed [Escaped with &lt;code&gt;\n&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;carriage return [Escaped with &lt;code&gt;\r&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;horizontal tab [Escaped with &lt;code&gt;\t&lt;/code&gt;]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, the escape code &lt;code&gt;\/&lt;/code&gt; resolves to a forward slash (&lt;code&gt;/&lt;/code&gt;), and a backslash followed by &lt;code&gt;u&lt;/code&gt; followed by four hex digits resolves to the character at the Unicode codepoint specified by said hex digits.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fstring.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fstring.png" alt="A diagram showing the grammar for a JSON string"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Writing it
&lt;/h2&gt;

&lt;p&gt;First, let's set up the skeleton of our method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;readString&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;oldCursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StringBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The quotes
&lt;/h3&gt;

&lt;p&gt;A string will always start with a quote, so if we don't see one at the start, we can fail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="sc"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oldCursor&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The loop
&lt;/h3&gt;

&lt;p&gt;We'll next use a loop to iterate over each character, firstly making sure that there is a next character, and it isn't a double-quote (since that would mark the end of the string) - then, in the loop we'll store the current character in a variable so we can do our logic on it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hasNext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;peek&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="sc"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;char&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Escaped characters
&lt;/h3&gt;

&lt;p&gt;First, we need to check for escaped characters. These will always start with a &lt;code&gt;\&lt;/code&gt; and will always have at least one other character afterwards - so let's check for a backslash character, and then begin pattern-matching on the next character:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\\'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// just a single backslash, written as a double backslash to escape it&lt;/span&gt;
            &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;it&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can check for each valid following character, and add that to our string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;                &lt;span class="sc"&gt;'"'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="sc"&gt;'\\'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\\'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="sc"&gt;'/'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="sc"&gt;'b'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\b'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="sc"&gt;'f'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x0C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toChar&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                &lt;span class="sc"&gt;'n'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="sc"&gt;'r'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="sc"&gt;'t'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\t'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="sc"&gt;'u'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;readHexChar&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things of interest here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kotlin does not support &lt;code&gt;\f&lt;/code&gt; for form feeds, so we have to use the raw ASCII value.&lt;/li&gt;
&lt;li&gt;We've put the &lt;code&gt;\u0000&lt;/code&gt;-reading logic into a new function, &lt;code&gt;readHexChar&lt;/code&gt;, which we'll write in a second.&lt;/li&gt;
&lt;li&gt;We have &lt;code&gt;else -&amp;gt; return null&lt;/code&gt; as there are no other valid characters after a backslash. If you want to be slightly less spec-conforming, you could use &lt;code&gt;else -&amp;gt; result.append(it)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;readHexChar()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Let's make our &lt;code&gt;readHexChar&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;readHexChar&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Char&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;oldCursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;isHexDigit&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toChar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;NumberFormatException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oldCursor&lt;/span&gt;
        &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is fairly simple, using our &lt;code&gt;read&lt;/code&gt; and &lt;code&gt;isHexDigit&lt;/code&gt; functions, then parsing the resulting hex string, then converting it to a &lt;code&gt;Char&lt;/code&gt;. Simple!&lt;/p&gt;

&lt;h3&gt;
  
  
  The other characters
&lt;/h3&gt;

&lt;p&gt;The other branch of our &lt;code&gt;if&lt;/code&gt;, for non-escaped characters, is nice and simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toChar&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oldCursor&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The characters disallowed in JSON strings are the first 32 ASCII codepoints, the control characters. If we encounter one of those, we can fail. Otherwise, we add it to our string.&lt;/p&gt;

&lt;h3&gt;
  
  
  Leaving the loop
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we skip the last character (since it's a double quote) and return our final string.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Here's our final code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;readString&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;oldCursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StringBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="sc"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oldCursor&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hasNext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;peek&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="sc"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;char&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\\'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;it&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sc"&gt;'"'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="sc"&gt;'\\'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\\'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="sc"&gt;'/'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="sc"&gt;'b'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\b'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="sc"&gt;'f'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x0C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toChar&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                    &lt;span class="sc"&gt;'n'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="sc"&gt;'r'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="sc"&gt;'t'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\t'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="sc"&gt;'u'&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;readHexChar&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toChar&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oldCursor&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Want to improve it? You could instead throw an exception when encountering invalid characters, instead of returning null.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>json</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Let's write a tiny JSON parser in Kotlin! Part 3: Bools &amp; Nulls</title>
      <dc:creator>Will BL</dc:creator>
      <pubDate>Mon, 10 May 2021 11:30:47 +0000</pubDate>
      <link>https://dev.to/williambl/let-s-write-a-tiny-json-parser-in-kotlin-part-3-bools-nulls-4lpj</link>
      <guid>https://dev.to/williambl/let-s-write-a-tiny-json-parser-in-kotlin-part-3-bools-nulls-4lpj</guid>
      <description>&lt;p&gt;Lets learn how to read the two simplest elements: Booleans and Nulls. These don't get their own diagrams due to their simplicity, but they can be seen in the grammar diagram for values:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fvalue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fvalue.png" alt="A diagram showing the grammar for a JSON value"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Booleans
&lt;/h2&gt;

&lt;p&gt;A boolean is super simple, of course - &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; (no &lt;code&gt;yes&lt;/code&gt;es and &lt;code&gt;no&lt;/code&gt;s &lt;a href="https://hitchdev.com/strictyaml/why/implicit-typing-removed/" rel="noopener noreferrer"&gt;like YAML has&lt;/a&gt;!)&lt;/p&gt;

&lt;p&gt;So we can use the &lt;code&gt;read(String)&lt;/code&gt; method we defined earlier to read either &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;readBoolean&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;oldCursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oldCursor&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oldCursor&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will attempt to read &lt;code&gt;true&lt;/code&gt;, if that's not there it'll backtrack and try to read &lt;code&gt;false&lt;/code&gt;, and if that's not there it'll give up and give you &lt;code&gt;null&lt;/code&gt;. Simple.&lt;/p&gt;

&lt;p&gt;But not as simple as Null!&lt;/p&gt;

&lt;h2&gt;
  
  
  Null
&lt;/h2&gt;

&lt;p&gt;Null is the simplest data type (is it even a data type (in JSON)?)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;readNull&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;oldCursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"null"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"null"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oldCursor&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can probably see how this works - try to read the symbol &lt;code&gt;null&lt;/code&gt;: if it's there, return &lt;code&gt;true&lt;/code&gt; ("yes, there is a null here"); if it's not there, put the cursor back to where it was before and return &lt;code&gt;false&lt;/code&gt; ("nope, no nulls here")&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Awesome, we've learned how to read our first two JSON data types! These, of course, were the simplest - next up we'll be doing Strings - definitely trickier!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>tutorial</category>
      <category>json</category>
    </item>
    <item>
      <title>Let's write a tiny JSON parser in Kotlin! Part 2: The Parser</title>
      <dc:creator>Will BL</dc:creator>
      <pubDate>Thu, 06 May 2021 21:01:19 +0000</pubDate>
      <link>https://dev.to/williambl/let-s-write-a-tiny-json-parser-in-kotlin-part-2-the-parser-b8g</link>
      <guid>https://dev.to/williambl/let-s-write-a-tiny-json-parser-in-kotlin-part-2-the-parser-b8g</guid>
      <description>&lt;p&gt;So now we have an understanding of JSON and the components that make it up, but we have to create something that will read it - this will be our parser.&lt;/p&gt;

&lt;p&gt;Our parser will step through our JSON file character by character to read it, so it'll need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;remember our JSON&lt;/li&gt;
&lt;li&gt;remember where in the JSON it's currently looking&lt;/li&gt;
&lt;li&gt;know if it's at the end&lt;/li&gt;
&lt;li&gt;read the current character&lt;/li&gt;
&lt;li&gt;step to the next character&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let's do it!&lt;br&gt;
First, we'll create a class which will take in our JSON as a &lt;code&gt;CharSequence&lt;/code&gt; (we could use a &lt;code&gt;String&lt;/code&gt;, too - the functionality is the same, but this lets you do something weird like throw a &lt;code&gt;StringBuilder&lt;/code&gt; in there), and will remember where it's currently reading:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CharSequence&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's give it the ability to read and step through the input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CharSequence&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Char&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;++]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;peek&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Char&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;++&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;peek()&lt;/code&gt; will read the current character, &lt;code&gt;skip()&lt;/code&gt;, will move the cursor forwards by one, and &lt;code&gt;step()&lt;/code&gt; and read and then move on.&lt;/p&gt;

&lt;p&gt;However, trying to read past the end will throw an exception, so let's add a method to check if we're at the end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;hasNext&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is everything we'll need for moving along our JSON text. Next, let's add some functions to actually read it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;predicate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StringBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;predicate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;peek&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CharSequence&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StringBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;patternCursor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;peek&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;patternCursor&lt;/span&gt;&lt;span class="p"&gt;++])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two functions are vital to how the parser will do its job:&lt;/p&gt;

&lt;p&gt;They read the JSON one character at a time, and store what they've read in a buffer, until the character they read reaches a certain condition. For the first function, that condition is given via a predicate, and in the second, the condition is that the buffer's contents match a given string. Once the condition is met, the buffer's contents are returned.&lt;/p&gt;

&lt;p&gt;These five methods, simple as they seem, are extremely powerful, and all we need as a foundation for our parser!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>json</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Making a Discord Vaccine Bot</title>
      <dc:creator>Will BL</dc:creator>
      <pubDate>Fri, 19 Feb 2021 13:58:44 +0000</pubDate>
      <link>https://dev.to/williambl/making-a-discord-vaccine-bot-a32</link>
      <guid>https://dev.to/williambl/making-a-discord-vaccine-bot-a32</guid>
      <description>&lt;p&gt;I recently made &lt;a href="https://github.com/williambl/vaccine-bot"&gt;a Discord bot&lt;/a&gt; that tracks the UK vaccine rollout, using Java, &lt;a href="https://github.com/DV8FromTheWorld/JDA"&gt;JDA&lt;/a&gt;, and the &lt;a href="https://coronavirus.data.gov.uk/"&gt;coronavirus.data.gov.uk&lt;/a&gt; API.&lt;/p&gt;

&lt;h3&gt;
  
  
  First Ideas
&lt;/h3&gt;

&lt;p&gt;I'd been browsing the excellent &lt;a href="https://coronavirus.data.gov.uk"&gt;UK Coronavirus dashboard&lt;/a&gt;, and I saw the '&lt;a href="https://coronavirus.data.gov.uk/details/developers-guide"&gt;developers' guide&lt;/a&gt;' link.&lt;/p&gt;

&lt;p&gt;I gave it a quick look over, saw that it didn't require registering for an API key or anything, and had an idea: make a Discord bot to spread vaccine positivity in my group chats :)&lt;/p&gt;

&lt;h3&gt;
  
  
  JDA and Java
&lt;/h3&gt;

&lt;p&gt;I've done work on Discord bots for communities using JDA before, so I knew I'd use that for this project just because I had familiarity with it.&lt;/p&gt;

&lt;p&gt;Regarding language, I had the option to either use Java or Kotlin - I went with Java just because it tends to be quicker for Gradle to set up a Java project (not having to download the latest Kotlin stdlib), but I do much prefer Kotlin and for most purposes will use that.&lt;/p&gt;

&lt;h3&gt;
  
  
  First attempts
&lt;/h3&gt;

&lt;p&gt;My first attempt was very basic, and amounted to something similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;API_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"[...]"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Timer&lt;/span&gt; &lt;span class="no"&gt;TIMER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Timer&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="no"&gt;JDA&lt;/span&gt; &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;bot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;JDABuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createDefault&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setActivity&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Activity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;watching&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"the vaccine rollout"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="no"&gt;TIMER&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;scheduleAtFixedRate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TimerTask&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;@Override&lt;/span&gt;
            &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;checkStats&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LoginException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;[...]&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;checkStats&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;JDA&lt;/span&gt; &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;channelId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;JsonParser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parseReader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InputStreamReader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GZIPInputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;API_URL&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;openStream&lt;/span&gt;&lt;span class="o"&gt;()))).&lt;/span&gt;&lt;span class="na"&gt;getAsJsonObject&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getAsJsonArray&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;getAsJsonObject&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;getAsLong&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;[...]&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":tada: **Good news!**\nThere have now been "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s"&gt;" vaccinations in the UK!"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This worked, but was a bit barebones.&lt;/p&gt;

&lt;p&gt;It does three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sets up a bot with JDA, with the token given from the first command-line argument (&lt;code&gt;JDABuilder.createDefault(args[0])&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;sets the bot's activity as "watching the vaccine rollout" (&lt;code&gt;setActivity(Activity.watching("the vaccine rollout"))&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;sets a timer, which every 24 hours (&lt;code&gt;1000 * 60 * 60 * 24&lt;/code&gt; milliseconds) checks the vaccination count and sends a message to a channel as given in the second argument (&lt;code&gt;checkStats&lt;/code&gt; function)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I took me an hour or so to get to this point. Most of the time was spent trying to work out why the input I was receiving was garbled.&lt;/p&gt;

&lt;p&gt;Because I hadn't read this: &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M4US4N3W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3151s8vgh134sbheu4xf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M4US4N3W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3151s8vgh134sbheu4xf.png" alt="All API responses are compressed using GZip. The request client must therefore accept GZip encoded content." width="629" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RTFM, folks.&lt;/p&gt;

&lt;p&gt;One &lt;code&gt;GZIPInputStream&lt;/code&gt; later, everything was working! But what else could I do?&lt;/p&gt;

&lt;h3&gt;
  
  
  Extra features
&lt;/h3&gt;

&lt;p&gt;The next thing I did was percentage calculation, just done by dividing by &lt;code&gt;680000&lt;/code&gt; (roughly 0.01 times the UK population). There were decimal place mishaps at first:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V9An1FV5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3qkrlnz6wesfvmcc3on1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V9An1FV5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3qkrlnz6wesfvmcc3on1.png" alt="vaccine bot reporting first as '1%', then '154%', then finally the correct '15%', to reactions of &amp;quot;that's not right&amp;quot;, &amp;quot;that's definitely not right&amp;quot;, &amp;quot;154%? seems legit to me&amp;quot;, and finally &amp;quot;that's better&amp;quot;" width="610" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But it eventually worked well.&lt;/p&gt;

&lt;p&gt;I later added the count as words, which someone said they could parse more easily than the numerals:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There have now been 10971047 (that's ten million nine hundred seventy-one thousand forty-seven) vaccinations in the UK! That's 16% of the population!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I used a library called '&lt;a href="https://github.com/allegro/tradukisto"&gt;tradukisto&lt;/a&gt;' to do the work for me. It also supports other languages than English, which is cool.&lt;/p&gt;

&lt;p&gt;I also later added a command, &lt;code&gt;,vaccinebot&lt;/code&gt;, to get an immediate count:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AO9FOdvk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kl7z8lvv4nxl7grzn4b3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AO9FOdvk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kl7z8lvv4nxl7grzn4b3.png" alt="the bot being triggered by the ',vaccinebot' command" width="880" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This was a fun quick project, and it's had an uplifting impact on my friends: &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tlbuMST3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6wjxkg2dfdmern27skqd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tlbuMST3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6wjxkg2dfdmern27skqd.png" alt="people saying 'past the 12 million mark!!' and 'my mum is part of that number :)' as a response to Vaccine Bot" width="880" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If anyone else wants to run an instance of it, &lt;a href="https://github.com/williambl/vaccine-bot"&gt;the code is available&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm grateful that Public Health England have made the COVID data available via an accessible and documented API, and that the &lt;a href="https://coronavirus.data.gov.uk/"&gt;COVID dashboard website&lt;/a&gt; exists.&lt;/p&gt;

</description>
      <category>java</category>
      <category>discord</category>
      <category>bot</category>
      <category>vaccine</category>
    </item>
    <item>
      <title>Let's write a tiny JSON parser in Kotlin! Part 1: Characters</title>
      <dc:creator>Will BL</dc:creator>
      <pubDate>Thu, 18 Feb 2021 23:45:45 +0000</pubDate>
      <link>https://dev.to/williambl/let-s-write-a-tiny-json-parser-in-kotlin-part-1-characters-3ehl</link>
      <guid>https://dev.to/williambl/let-s-write-a-tiny-json-parser-in-kotlin-part-1-characters-3ehl</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/williambl/let-s-write-a-tiny-json-parser-in-kotlin-part-0-understanding-json-477h"&gt;the previous post&lt;/a&gt;, we looked at the elements that make up JSON. Now, lets start building something that can recognise them!&lt;/p&gt;

&lt;p&gt;To start off with, we'll need to define three important building blocks of JSON: &lt;strong&gt;whitespace&lt;/strong&gt;, &lt;strong&gt;digits&lt;/strong&gt;, and &lt;strong&gt;hex digits&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Whitespace
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fwhitespace.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fwhitespace.png" alt="A diagram showing the grammar for whitespace"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll remember that &lt;strong&gt;whitespace&lt;/strong&gt; is a string of zero or more spaces, line feeds (&lt;code&gt;\n&lt;/code&gt;), carriage returns (&lt;code&gt;\r&lt;/code&gt;), and horizontal tabs (&lt;code&gt;\t&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;To check if a character is a valid part of whitespace, we can define the following &lt;a href="https://kotlinlang.org/docs/reference/extensions.html" rel="noopener noreferrer"&gt;extension function&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;Char&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isWhitespace&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;' '&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\r'&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\n'&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\t'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which checks if the character is one of the characters allowed in whitespace. Simple!&lt;/p&gt;

&lt;h3&gt;
  
  
  Digits
&lt;/h3&gt;

&lt;p&gt;Digits are even simpler: the Arabic numerals 0..9. We can check if a character is a valid digit with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;Char&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDigit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sc"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="sc"&gt;'9'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works because in &lt;a href="https://en.wikipedia.org/wiki/ASCII" rel="noopener noreferrer"&gt;ASCII&lt;/a&gt; (and therefore also in Unicode) the characters for the ten digits are all assigned consecutive numbers - so&lt;br&gt;
&lt;code&gt;this in '0'..'9'&lt;/code&gt; becomes &lt;code&gt;'0' &amp;lt;= this &amp;amp;&amp;amp; this &amp;lt;= '9'&lt;/code&gt;, and &lt;code&gt;'0'&lt;/code&gt; and &lt;code&gt;'9'&lt;/code&gt; become their respective ASCII codepoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hex Digits
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;Char&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isHexDigit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sc"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="sc"&gt;'9'&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sc"&gt;'a'&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="sc"&gt;'f'&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="sc"&gt;'F'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is pretty much the same as &lt;code&gt;isDigit&lt;/code&gt;, but with extra checking for digits A through F. Remember to check for both upper and lower case!&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;All of these functions could also be written as &lt;a href="https://kotlinlang.org/docs/functions.html#single-expression-functions" rel="noopener noreferrer"&gt;expression functions&lt;/a&gt; - give that a go!&lt;/p&gt;

&lt;p&gt;In the next post, we'll start work on our parser.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>json</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Mixins, Kotlin, and Default Methods - why they don't work together</title>
      <dc:creator>Will BL</dc:creator>
      <pubDate>Sun, 25 Oct 2020 19:01:51 +0000</pubDate>
      <link>https://dev.to/williambl/mixins-kotlin-and-default-methods-why-they-don-t-work-together-417d</link>
      <guid>https://dev.to/williambl/mixins-kotlin-and-default-methods-why-they-don-t-work-together-417d</guid>
      <description>&lt;p&gt;A note for people using &lt;a href="https://github.com/SpongePowered/Mixin"&gt;Mixins&lt;/a&gt; which implement &lt;a href="https://kotlinlang.org/docs/reference/interfaces.html"&gt;interfaces&lt;/a&gt; which have default implementations of methods which are written in Kotlin.&lt;/p&gt;

&lt;p&gt;Lets say you have an interface in Kotlin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;MyKotlinterface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;doMyThing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;doThing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and a mixin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Mixin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PlayerEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyMixin&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;MyKotlinterface&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you might think that you can then do &lt;code&gt;(player as MyKotlinterface).doMyThing()&lt;/code&gt;. However, &lt;strong&gt;you will get an &lt;code&gt;AbstractMethodError&lt;/code&gt;&lt;/strong&gt;. Why? because Kotlin doesn't compile your interface how you'd expect it to.&lt;/p&gt;

&lt;p&gt;You'd think that it would compile like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;MyKotlinterface&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doMyThing&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;z&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doThing&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but &lt;em&gt;that would only work on JVMs at or above version 8, when default implementations for methods in interfaces were added&lt;/em&gt; - so Kotlin compiles it like &lt;em&gt;this&lt;/em&gt; instead, which works on all JVMs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;TestInterface&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* All calls to the default impl of this method
     * are rewritten by the kotlin compiler to use
     * the static method
     */&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doMyThing&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DefaultImpls&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doMyThing&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TestInterface&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;z&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doThing&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The side-effect of this is that when you add your interface to a class with that mixin, it bypasses the kotlin compiler's rewriting - and so, &lt;strong&gt;attempts to access the default impl of the method on the player will crash&lt;/strong&gt; with an &lt;code&gt;AbstractMethodError&lt;/code&gt;. There are different fixes for this, depending on which Kotlin version you're using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For Kotlin &amp;lt;1.2, you'll have to just write your implementations in your mixin class.&lt;/li&gt;
&lt;li&gt;For Kotlin 1.2&amp;lt;=version&amp;lt;1.4, annotate your method with &lt;code&gt;@JvmDefault&lt;/code&gt;, and put this in your build.gradle:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetbrains&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kotlin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gradle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;KotlinCompile&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;kotlinOptions&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;freeCompilerArgs&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s1"&gt;'-Xjvm-default'&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;For Kotlin &amp;gt;=1.4, just put this in your build.gradle:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetbrains&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kotlin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gradle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;KotlinCompile&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;kotlinOptions&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;freeCompilerArgs&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s1"&gt;'-Xjvm-default=all'&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and your default methods will be compiled as they should be!&lt;/p&gt;

&lt;p&gt;with thanks to &lt;a href="https://blog.jetbrains.com/kotlin/2020/07/kotlin-1-4-m3-generating-default-methods-in-interfaces/"&gt;this blog post&lt;/a&gt; and &lt;a href="https://github.com/Konloch/bytecode-viewer"&gt;this decompiler/bytecode viewer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>java</category>
      <category>mixins</category>
      <category>minecraft</category>
    </item>
    <item>
      <title>Let's write a tiny JSON parser in Kotlin! Part 0: Understanding JSON</title>
      <dc:creator>Will BL</dc:creator>
      <pubDate>Tue, 13 Oct 2020 13:46:40 +0000</pubDate>
      <link>https://dev.to/williambl/let-s-write-a-tiny-json-parser-in-kotlin-part-0-understanding-json-477h</link>
      <guid>https://dev.to/williambl/let-s-write-a-tiny-json-parser-in-kotlin-part-0-understanding-json-477h</guid>
      <description>&lt;p&gt;Nearly every language has some support for &lt;a href="https://www.json.org/" rel="noopener noreferrer"&gt;JSON&lt;/a&gt;: many have official libraries for dealing with it, and for those that don't there are plenty of third-party libraries - you're often spoiled for choice.&lt;/p&gt;

&lt;p&gt;With all these options, you'd almost never have to parse JSON yourself. But let's do that anyway!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is JSON Made of?
&lt;/h2&gt;

&lt;p&gt;JSON is built up of various elements - we can start with the simplest of these and work our way up until we can parse entire documents.&lt;/p&gt;

&lt;p&gt;On the &lt;a href="https://www.json.org/" rel="noopener noreferrer"&gt;JSON website&lt;/a&gt;, there are diagrams that show how each element of the JSON specification is defined. These can really help you wrap your head around the grammar, so they'll be reproduced in this post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Whitespace
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fwhitespace.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fwhitespace.png" alt="A diagram showing the grammar for whitespace"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets start with the simplest element - &lt;strong&gt;whitespace&lt;/strong&gt; is a string of zero or more spaces, line feeds (&lt;code&gt;\n&lt;/code&gt;), carriage returns (&lt;code&gt;\r&lt;/code&gt;), and horizontal tabs (&lt;code&gt;\t&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Strings
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fstring.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fstring.png" alt="A diagram showing the grammar for a JSON string"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;string&lt;/strong&gt; is a string of characters enclosed within double quotes (&lt;code&gt;"&lt;/code&gt;). Any character can be put within a string, except for the following, which must be escaped:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;double quotes (&lt;code&gt;"&lt;/code&gt;) [Escaped with &lt;code&gt;\"&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;backslash (&lt;code&gt;\&lt;/code&gt;) [Escaped with &lt;code&gt;\\&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;backspace [Escaped with &lt;code&gt;\b&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;form feed [Escaped with &lt;code&gt;\f&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;line feed [Escaped with &lt;code&gt;\n&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;carriage return [Escaped with &lt;code&gt;\r&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;horizontal tab [Escaped with &lt;code&gt;\t&lt;/code&gt;]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, the escape code &lt;code&gt;\/&lt;/code&gt; resolves to a forward slash (&lt;code&gt;/&lt;/code&gt;), and a backslash followed by &lt;code&gt;u&lt;/code&gt; followed by four hex digits resolves to the character at the Unicode codepoint specified by said hex digits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Numbers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Numbers&lt;/strong&gt; are pretty complicated:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fnumber.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fnumber.png" alt="A diagram showing the grammar for a JSON number"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They consist of an optional &lt;code&gt;-&lt;/code&gt; if the number is negative, followed by a digit. If the digit is nonzero, there can follow any amount of digits. If it is zero, there can be no more digits and we move on.&lt;/p&gt;

&lt;p&gt;There can then be a point (&lt;code&gt;.&lt;/code&gt;), after which there can be any amount of digits representing a decimal fraction.&lt;/p&gt;

&lt;p&gt;Afterwards, there can be an &lt;code&gt;e&lt;/code&gt; (or &lt;code&gt;E&lt;/code&gt;), followed by an optional sign for the exponent (&lt;code&gt;+&lt;/code&gt;/&lt;code&gt;-&lt;/code&gt;). After this, there can be any amount of digits for the exponent, for scientific notation-style numbers.&lt;/p&gt;

&lt;p&gt;😰 Wow, that's a lot. Numbers were definitely the hardest part of this parser to write for me. But don't worry if you don't understand it yet - you'll become well-acquainted with the grammar when writing the parser!&lt;/p&gt;

&lt;h3&gt;
  
  
  Values
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fvalue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fvalue.png" alt="A diagram showing the grammar for a JSON value"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In JSON, a &lt;strong&gt;value&lt;/strong&gt; is whitespace, followed by one of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an object&lt;/li&gt;
&lt;li&gt;an array&lt;/li&gt;
&lt;li&gt;a number&lt;/li&gt;
&lt;li&gt;the boolean value &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the boolean value &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;null&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;followed by whitespace.&lt;/p&gt;

&lt;h3&gt;
  
  
  Arrays
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Farray.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Farray.png" alt="A diagram showing the grammar for a JSON array"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arrays&lt;/strong&gt; are nice and simple. A collection of zero or more values (or whitespace) enclosed in square brackets, with a comma after every value but the last.&lt;/p&gt;

&lt;h3&gt;
  
  
  Objects
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fobject.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwillbl.dev%2Fimg%2Fjson%2Fobject.png" alt="A diagram showing the grammar for a JSON object"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;object&lt;/strong&gt; is a collection of zero or more &lt;code&gt;string : value&lt;/code&gt; pairs, surrounded by curly brackets, and with commas after all elements but the last.&lt;/p&gt;

&lt;h3&gt;
  
  
  Closing thoughts
&lt;/h3&gt;

&lt;p&gt;A few elements of the grammar can seem complicated at first (looking at you, numbers...), but those diagrams can be really useful. You may also want to take a look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf" rel="noopener noreferrer"&gt;ECMA-404, the official JSON spec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.crockford.com/mckeeman.html" rel="noopener noreferrer"&gt;The JSON grammar in McKeeman form&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kotlin</category>
      <category>tutorial</category>
      <category>json</category>
    </item>
  </channel>
</rss>
