<?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>Forem: Jae Anne Bach Hardie</title>
    <description>The latest articles on Forem by Jae Anne Bach Hardie (@dulcedejae).</description>
    <link>https://forem.com/dulcedejae</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%2F458944%2F135bb502-6c74-4504-8ab9-89729757f32f.jpg</url>
      <title>Forem: Jae Anne Bach Hardie</title>
      <link>https://forem.com/dulcedejae</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dulcedejae"/>
    <language>en</language>
    <item>
      <title>Learning Rust 2: A Tiny Database is Born</title>
      <dc:creator>Jae Anne Bach Hardie</dc:creator>
      <pubDate>Sun, 30 Aug 2020 20:33:55 +0000</pubDate>
      <link>https://forem.com/dulcedejae/learning-rust-2-a-tiny-database-is-born-eef</link>
      <guid>https://forem.com/dulcedejae/learning-rust-2-a-tiny-database-is-born-eef</guid>
      <description>&lt;p&gt;Hello again! Tonight we're drinking a Chardonnay from Murcia, Spain, so shoutout to my home country hope you're holding up I hear things have been rough lately. It's pleasantly dry if not particularly complex, tasting mostly like crunchy green apples.&lt;/p&gt;

&lt;p&gt;Another thing that won't be particularly complex is my plan for the next steps in this project. Last time I said I was going to attempt to make a VCS — Version Control System, like Git or Mercurial — in Rust. We got as far as getting things running enough to read a file and print out it's contents, so not very far at all. Today I want to get away from just toying with the language and see if I can make something that's at least theoretically useful without being unachievable. When tackling a large project — especially when your only motivation is to learn things and maybe write silly blog posts — it's important to have small milestones that build on each other so you can evaluate your progress and learn as you go.&lt;/p&gt;

&lt;p&gt;I've decided that my first milestone is to make a non-branching, client-only VCS. It's like you had a git repository where you only have your main branch and there's no remote to push to. It's still useful in that you can view all previous states of the repository and roll back to them but it has no collaboration features. This is pretty simple to start with but it's also an important component of a more fleshed-out VCS. No matter how big Ribbit gets, it will still have to track a branch's history.&lt;/p&gt;

&lt;p&gt;The architecture for this kind of system can be really straightforward: a repository consists of a chronological list of Revisions, each of which consists of one or more Changes. Each Change is a transformation applied to a file. At least to start with we'll model every Change as completely replacing the previous state of the file since diffs and merging aren't necessary when we don't have collaboration features. We could store all this in many different ways but I figure SQLite is a reasonably scalable solution that seems to have &lt;a href="https://github.com/rusqlite/rusqlite"&gt;bindings for Rust&lt;/a&gt; available. I'm not looking forward to manual management of database connections but this is part of what learning Rust is.&lt;/p&gt;

&lt;p&gt;As a first step, I install the SQLite crate by adding it to my Cargo.toml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;rusqlite&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.24.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And I run &lt;code&gt;cargo build&lt;/code&gt;. Cargo fetches and builds the crate no problem, so now I should be able to create a database that stores the state of our repository. Taking inspiration from git, I'll store it under &lt;code&gt;.ribbit/repo.db&lt;/code&gt;. Let's see if it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rusqlite&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;create_database&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;rusqlite&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"./.ribbit/repo.db"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;rusqlite&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_database&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&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;I put the database creation logic into its own function. I want to start gently dividing the logic I'm writing into functions. Eventually I'll be making multiple crates to organise the code into relevant modules and it will be easier if everything isn't in one large main() function.&lt;/p&gt;

&lt;p&gt;When I try to run this, the compiler errors, complaining that it can't find "sqlite3.lib". I guess I don't have SQLite installed on my machine. I'm used to it being around but I must not have used it on any projects on this laptop yet. I install it via Chocolatey but that still doesn't work. I don't really want to spend my evening learning how to get C libraries to work on Windows so I follow the advice of the rusqlite README and enable the option to compile SQLite from source in my Cargo.toml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies.rusqlite]&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.24.0"&lt;/span&gt;
&lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;["bundled"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ribbit now compiles again but returns an error: cannot open database file. I'm pretty sure &lt;code&gt;Connection::open&lt;/code&gt; is meant to create the database file but it probably doesn't create the folder it should be in if that doesn't exist, so I need to figure out how to create a folder. I find the function I need in the &lt;a href="https://doc.rust-lang.org/std/fs/index.html"&gt;std::fs crate&lt;/a&gt; but my naive implementation doesn't compile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;create_database&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;rusqlite&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create_dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./.ribbit"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./.ribbit/repo.db"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&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;It turns out errors potentially returned from the fs crate are different from those returned from the rusqlite crate, so I can't just stick a &lt;code&gt;?&lt;/code&gt; after &lt;code&gt;create_dir&lt;/code&gt; and count on it to just short-circuit if an error is returned. I could create a custom Result type that could contain either kind of error but I figure if I can't create the directory to store the repository data there's not much else the program can do anyway so I decide to use the &lt;code&gt;.unwrap()&lt;/code&gt; method instead, which panics — aborts program execution — if there's an error. Panics don't need to be handled by the type system because the program terminates, but they do mean the error can't be caught later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;create_database&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;rusqlite&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create_dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./.ribbit"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./.ribbit/repo.db"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&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 works! An empty "./.ribbit/repo.db" file has been created, and reminds me I need to add &lt;code&gt;.ribbit&lt;/code&gt; to my .gitignore file. However, when I try to run the code again I see a problem. The program panics because we can't create a directory that already exists. That's a silly reason to abort execution because the database could still be created, so we'll have to check for the existence of the directory before trying to create it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;create_database&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;rusqlite&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ribbit_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"./.ribbit"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ribbit_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="nf"&gt;.kind&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ErrorKind&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AlreadyExists&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create_dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ribbit_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;other_error&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;panic!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other_error&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./.ribbit/repo.db"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&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;strong&gt;Correction added 2020-08-31&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This code is wrong. The error kind we need to match on is the file not existing rather than already existing. These are the perils of coding late at night, I got what I was doing all mixed up and then didn't test it properly. Part of my objective with this series is to show when and why mistakes happen during learning so I'm going to leave this here until I fix it in the next installment but I didn't want anyone to copy this code believing it should work as described.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;End correction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This uses a language feature that I learned to love years ago in Elixir: pattern matching. The branches of a "match" block execute only if the input to the match matches the left hand side and if it does any variables declared within the match store the value in that place of the structure. This is hard to explain but intuitive to write and allow us to easily extract the error from the result and match on its kind. Now the only step that is missing is to create the database table we'll need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;create_database&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;rusqlite&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ribbit_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"./.ribbit"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ribbit_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="nf"&gt;.kind&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ErrorKind&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AlreadyExists&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create_dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ribbit_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;other_error&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;panic!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other_error&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./.ribbit/repo.db"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="nf"&gt;.execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"create table if not exists changes (
            id text primary key,
            date_created integer not null,
            revision_id text not null,
            file_path text not null
        )"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;rusqlite&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NO_PARAMS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&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;In the future I'm pretty sure we'll need revisions at the very least to have their own table so they can have a message associated with them but for now both revisions and files existing simply as ids in the changes table will be enough. I confirm this code works by opening the database in &lt;a href="https://sqlectron.github.io/"&gt;SQLEctron&lt;/a&gt; and checking the table has been created.&lt;/p&gt;

&lt;p&gt;This is enough for one night. I already feel myself becoming more confident with Rust's syntax, even though most of my code is still written by modifying copy-and-paste example code from various documentation sources. Next time I'll look into how to read command line arguments so I can add commands to ribbit and start not only initialising the repository but saving some revisions to it.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>journey</category>
      <category>learning</category>
    </item>
    <item>
      <title>Learning Rust 1: Install things and read a file</title>
      <dc:creator>Jae Anne Bach Hardie</dc:creator>
      <pubDate>Wed, 26 Aug 2020 23:33:24 +0000</pubDate>
      <link>https://forem.com/dulcedejae/learning-rust-1-install-things-and-read-a-file-5613</link>
      <guid>https://forem.com/dulcedejae/learning-rust-1-install-things-and-read-a-file-5613</guid>
      <description>&lt;p&gt;I've tried to learn Rust multiple times. Unsuccessfully.&lt;/p&gt;

&lt;p&gt;I want to be upfront about that because it's a bit hard to admit. I'm a pretty experienced software engineer, mostly in web development but I used to work in data science. I'm curious and stubborn and generally pride myself on picking things up quickly. However, I never studied Computer Science, I never did any serious coding in a low-level language and so while theoretically I read the Rust docs and I understand I've never managed to make it all click in a way which makes it intuitive to reason about.&lt;/p&gt;

&lt;p&gt;I'm writing this in an attempt to break this cycle of picking it up, toying around with it, getting frustrated and going back to Javascript. I'm going to set myself up every few nights, pour myself a drink and write about my progress as I learn to solidify my thoughts and keep me honest. I think this might be useful to other Rust beginners (I certainly like reading other people's thought processed) but I'm not experienced enough to be properly didactic. Expect to come on a ride with me while I figure out why my code doesn't compile and hopefully learn to not make my mistakes, don't expect a coherent explanation of what the stack and the heap are. Those are two different words that both mean "a pile of things" and I keep forgetting which is which.&lt;/p&gt;

&lt;p&gt;The drink tonight is a French Manhattan, which is where you replace the vermouth with Chambord. I feel it's a misnomer, if anything it tastes less french than its more traditional cousin, all the herbal sophistication replaced with the flavour of blackberries marinated in cough syrup. The cloying sweetness is at least somewhat celebratory.&lt;/p&gt;

&lt;p&gt;Anyway, Rust.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project
&lt;/h2&gt;

&lt;p&gt;I'm going to attempt to make a version control system. This sounds like a good idea because&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It's the kind of thing that can be really big and complex but made out of simple building blocks.&lt;/li&gt;
&lt;li&gt;We'll need to build both a CLI and a server, which is neat variety.&lt;/li&gt;
&lt;li&gt;Manipulating lots of files performantly sounds like the kind of thing you'd use a language like Rust for.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I might regret this. It's a bit more ambitious than your standard TodoMVC but it's interesting, isn't it? Have you never stopped and wondered how someone starts coding something like git?&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Rust
&lt;/h2&gt;

&lt;p&gt;It turns out I already had rustup installed. If you don't have rustup installed, the &lt;a href="https://www.rust-lang.org/tools/install"&gt;Rust website&lt;/a&gt; provides installers if it isn't already in your package manager. Rustup is itself like a little package manager, it allows you to download different versions of Rust and switch between them. This is the kind of thing I don't have a reason to care about yet but I know from experience is really useful when you're switching between projects which were made with different versions of a language.&lt;/p&gt;

&lt;p&gt;I run &lt;code&gt;rustup update&lt;/code&gt; to update to the latest stable version. It's been a while since I last updated and I don't want to be caught out by things that might be different from the docs available out there. Fortunately, it's that easy.&lt;/p&gt;

&lt;p&gt;When I go to install a Rust plugin for my editor — VSCode, the editor that has taken over even my hardened, spacemacs-loving heart — I notice there's two: the official one and &lt;a href="https://rust-analyzer.github.io/"&gt;Rust Analyzer&lt;/a&gt;. It looks like Analyzer is an attempt to provide a more responsive IDE experience with things like go-to-reference and autocompletion. That's something I always thought was missing from the rust experience in my previous forays, so even though it's officially in alpha I take heart in the 5 star rating the plugin has and brave it. After all, if it doesn't work I can just switch to the regular language server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the project
&lt;/h2&gt;

&lt;p&gt;The docs say to use &lt;code&gt;cargo new&lt;/code&gt; to create a new Rust project. Cargo is, if I understand it right, the package manager for Rust packages, which are called crates (get it?). It's like Rust's &lt;code&gt;npm&lt;/code&gt;. I've decided to name my project "ribbit" for no other reason than it starts with "R" and I think it will be funny to type in the terminal, so I type &lt;code&gt;cargo new ribbit&lt;/code&gt; and that looks so funny it instantly validates my naming decision. Or maybe the Chambord is getting to me.&lt;/p&gt;

&lt;p&gt;Opening the folder in VSCode reveals &lt;code&gt;cargo.toml&lt;/code&gt; and &lt;code&gt;cargo.lock&lt;/code&gt; files and I've used npm enough to take a good guess at what those are. I actually really like the TOML format, it's much more human-readable than JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[package]
name = "ribbit"
version = "0.1.0"
authors = ["Jae Anne Bach Hardie &amp;lt;EMAIL REDACTED&amp;gt;"]
edition = "2018"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I don't know why "edition" is set to all the way back in 2018 but I decide not to worry about it. Other than that there's a &lt;code&gt;.gitignore&lt;/code&gt; file (very useful) and an extremely simple main function in &lt;code&gt;src/main.rs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&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;I'm not immediately sure how to run a Rust project but Cargo has been pretty intuitive so far so I type in &lt;code&gt;cargo run&lt;/code&gt; and am not disappointed to find it compiles the project in debug mode and outputs &lt;code&gt;Hello, world!&lt;/code&gt; to my terminal. So far, so good. I commit everything to a &lt;a href="https://github.com/jbachhardie/ribbit"&gt;new repository&lt;/a&gt; using VSCode's "publish" command that integrates with GitHub. Frustratingly, it creates the repository but doesn't add the origin to my local git and push, which I have to do manually. I guess they're still ironing out the kinks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading a file
&lt;/h2&gt;

&lt;p&gt;Time for the kind of thing that makes me really afraid. Let's see if we can read a file and print it to console. We're going to need to read a lot of files to make a VCS work!&lt;/p&gt;

&lt;p&gt;I start by copying the "read a file" example from the stdlib:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cargo.toml"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&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;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c"&gt;// read up to 10 bytes&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&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;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The bytes: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&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;To go through this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;use&lt;/code&gt; declarations import other crates, in this case the stdlib crates needed to open files.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;let&lt;/code&gt; declares an immutable variable, &lt;code&gt;let mut&lt;/code&gt; a mutable one. I love this in theory, in practice I still lack an intuition for when things need to be mutable. For example, I'd think you wouldn't need anything mutable to just read a file and not change it but I think the buffer here needs to be mutable so it can be changed to store the bytes of the file as they come in?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;&lt;/code&gt; passes something as a pointer, &lt;code&gt;&amp;amp;mut&lt;/code&gt; as a mutable pointer. I think. I'm sure we'll get to pointers right now I just know it has something to do with where memory is allocated and that the compiler will shout at me if I use the wrong one.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;?&lt;/code&gt; after an operation short-circuits the function to return failure if the op fails. This is how Rust does error handling and it's pretty clever. Functions explicitly return a &lt;code&gt;Result&lt;/code&gt; type but you can write them without having to think about that. It's like &lt;code&gt;async function()&lt;/code&gt; in Javascript, which will return a &lt;code&gt;Promise&lt;/code&gt; despite being written like synchronous code with exceptions, except the exceptions are also typed which is great.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyway, this code only reads 10 bytes and then prints them as integers rather than as Unicode so we have some ways to go before we're printing out the whole file recognizably. The standard library gives us &lt;code&gt;BufReader&lt;/code&gt; with an interface that makes it easier to read something in as a Unicode string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BufReader&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;BufReader&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c"&gt;// read a line into buffer&lt;/span&gt;
    &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="nf"&gt;.read_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&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 prints out the first line of the file! We're a while loop away from printing the whole thing, so let's look up how to do that. The documentation is hard to navigate at first, because &lt;code&gt;BufReader&lt;/code&gt; doesn't seem to have what I'm looking for. What is happening is that &lt;code&gt;BufReader&lt;/code&gt; implements the &lt;code&gt;BufRead&lt;/code&gt; trait. Traits are collections of methods that a type implements so &lt;code&gt;BufReader&lt;/code&gt; implements &lt;code&gt;BufRead&lt;/code&gt;, &lt;code&gt;Debug&lt;/code&gt;, &lt;code&gt;Read&lt;/code&gt; and &lt;code&gt;Seek&lt;/code&gt;. It's &lt;code&gt;BufRead&lt;/code&gt; that has the &lt;code&gt;read_line&lt;/code&gt; method, as well as a &lt;code&gt;lines&lt;/code&gt; method that returns an iterator. That's what we want, because iterators can be looped over with a &lt;code&gt;for&lt;/code&gt; loop.&lt;/p&gt;

&lt;p&gt;Before we do that, though, I'm starting to realize I'm not getting any IDE integration. I can't see the types of variables on hover and things like that. After some poking around it turns out I have to go to my VSCode settings and turn on individual Rust Analyzer features. Alpha software is alpha, I guess. I don't know which features I want so I check "Enable All Available Features" and hope nothing bad will happen. My code is immediately enriched with type information and I can see documentation on hover! This is amazing and reminds me of what I loved most about ReasonML, the fact that you don't have to manually declare types but the inferred types are added in by the IDE so you can see them.&lt;/p&gt;

&lt;p&gt;I first try&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="nf"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&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;but my new IDE integration quickly informs me that &lt;code&gt;line&lt;/code&gt; there is a &lt;code&gt;Result&lt;/code&gt; type that cannot be printed. Makes sense, I guess reading a line could fail. I try adding one of those convenient question marks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="nf"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&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;That's a syntax error. Now that I think about it, the &lt;code&gt;?&lt;/code&gt; operator goes on the operation not the name of the variable being assigned to. How about this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="nf"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&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;That's a different error but fortunately Rust error messages are pretty helpful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;the `?` operator can only be applied to values that implement `std::ops::Try`
the trait `std::ops::Try` is not implemented for `std::io::Lines&amp;lt;std::io::BufReader&amp;lt;std::fs::File&amp;gt;&amp;gt;`
required by `std::ops::Try::into_result`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I see what is happening. &lt;code&gt;lines()&lt;/code&gt; returns the &lt;em&gt;iterator&lt;/em&gt; and we need to unwrap each individual value returned from the iterator, not the iterator itself. I'm starting to think there might not be a nice sugar to do this in a &lt;code&gt;for&lt;/code&gt; loop declaration although I'd love if there was, just like Javascript has &lt;code&gt;for await (foo of iter)&lt;/code&gt;. Unwrapping it where it's used works fine, though, and makes me feel a bit silly for not having started there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BufReader&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cargo.toml"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;BufReader&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="nf"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&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;Ok&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;That compiles and prints out the file! Success!&lt;/p&gt;

&lt;p&gt;Before I go for the night, though, I notice that I'm getting an error when trying to auto-format the file. The log says &lt;code&gt;component rustfmt should be in the manifest&lt;/code&gt; so I'm guessing &lt;code&gt;rustup&lt;/code&gt; doesn't install the formatter by default. Weird choice but OK. I run &lt;code&gt;rustup component add rustfmt&lt;/code&gt; but that tells me&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;toolchain 'stable-x86_64-pc-windows-msvc' does not contain component 'rustfmt' for target 'x86_64-pc-windows-msvc'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um. Ok. Time to do some Googling. There's an &lt;a href="https://github.com/rust-lang/rustup/issues/1793"&gt;issue&lt;/a&gt; where others have had the same problem, the fix seems to be to reinstall the toolchain. I guess my version was too old and rustup got confused? The reinstall fixes it and the autoformatter runs, although my code was already formatted properly so it only reorders the imports. Still, very useful to have in place for later.&lt;/p&gt;

&lt;p&gt;Good night everyone!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>journey</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
