<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Chasing Rabbits]]></title>
  <link href="http://erickt.github.io/atom.xml" rel="self"/>
  <link href="http://erickt.github.io/"/>
  <updated>2016-02-27T07:43:59-08:00</updated>
  <id>http://erickt.github.io/</id>
  <author>
    <name><![CDATA[Erick Tryzelaar]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Serde 0.7]]></title>
    <link href="http://erickt.github.io/blog/2016/02/26/serde-0-dot-7/"/>
    <updated>2016-02-26T23:06:11-08:00</updated>
    <id>http://erickt.github.io/blog/2016/02/26/serde-0-dot-7</id>
    <content type="html"><![CDATA[<p>I&rsquo;m thrilled to announce <a href="https://github.com/serde-rs/serde">Serde</a> 0.7.0!
It&rsquo;s been a long time coming, and has a number of long awaited new features,
breaking changes, and other notable changes.  Serde 0.6.x is now deprecated,
and while I&rsquo;ll try to keep <code>serde_codegen</code> and <code>serde_macros</code> while projects
switch over to 0.7, I&rsquo;m going to shift more to a pull-based approach, so please
file a bug ticket if a nightly release has broken you.</p>

<p>On to the list on the major changes!</p>

<h2>Serde</h2>

<ul>
<li>Removed the word <code>Error</code> from <code>serde::de::Error</code> variants.</li>
<li>Renamed <code>visit_</code> methods to <code>serialize_</code> and <code>deserialize_</code>.</li>
<li>Removed dependency on the deprecated <a href="https://github.com/rust-num/num">num</a>
crate.</li>
<li>Require that implementations of <code>serde::de::Error</code> implement
<code>std::error::Error</code>.</li>
<li>Added <code>serde::de::Deserializer::deserialize_struct_field</code> hook that allows a
<code>Deserializer</code> to know the next value is a struct field.</li>
<li>Added <code>serde::ser::Error</code>, which allows a <code>Serialize</code> type produce an error
if it cannot be serialized.</li>
<li>Serializing <code>std::path::Path</code> with non-unicode characters will result in a
Serde error, rather than a panic.</li>
<li>Added implementations for <code>std::net</code> types.</li>
<li>Added <code>serde::de::Error::unknown_variant</code> error message hook.</li>
<li>Renamed <code>serde::de::Error::syntax</code> to <code>serde::de::Error::custom</code>.</li>
</ul>


<h2>Serde Codegen and Macros</h2>

<ul>
<li>Serde now by default ignores unknown fields when deserializing.  The previous
behavior, where Serde will report unknown fields as an error, can be
  opted in with the container annotation <code>#[serde(deny_unknown_fields)]</code>,
as in:</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[serde(deny_unknown_fields)]</span>
</span><span class='line'><span class="k">struct</span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">x</span><span class="o">:</span> <span class="n">usize</span><span class="p">,</span>
</span><span class='line'>    <span class="n">y</span><span class="o">:</span> <span class="n">usize</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>Added the container annotation <code>#[serde(rename="...")]</code>to rename the
container, as in:</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[serde(rename=</span><span class="s">&quot;point&quot;</span><span class="cp">)]</span>
</span><span class='line'><span class="k">struct</span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">x</span><span class="o">:</span> <span class="n">usize</span><span class="p">,</span>
</span><span class='line'>    <span class="n">y</span><span class="o">:</span> <span class="n">usize</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>Added the variantl annotation <code>#[serde(rename="...")]</code> to rename
variants, as in:</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">enum</span> <span class="n">Value</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[serde(rename=</span><span class="s">&quot;type&quot;</span><span class="cp">)]</span>
</span><span class='line'>    <span class="n">Type</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>Added rename annotation <code>#[serde(rename(serialize="...", deserialize="..."))]</code>
  that supports crazy schemas like AWS that expect serialized fields with the
first character lower case, and the deserialized response with the first
character upper cased.</li>
<li>Removed support for the unused format-specific rename support.</li>
<li>Added the field annotation <code>#[serde(default="$path")]</code>, where <code>$path</code> is a
reference to some function that returns a default value for a field if it&rsquo;s
not present when deserializing.  For example:</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">trait</span> <span class="n">MyDefault</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">my_default</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Self</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">struct</span> <span class="n">Point</span><span class="o">&lt;</span><span class="n">T</span><span class="o">:</span> <span class="n">MyDefault</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">x</span><span class="o">:</span> <span class="n">T</span><span class="p">,</span>
</span><span class='line'>    <span class="cp">#[serde(default=</span><span class="s">&quot;MyDefault::my_default&quot;</span><span class="cp">)]</span>
</span><span class='line'>    <span class="n">y</span><span class="o">:</span> <span class="n">T</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>Added the field annotation <code>#[serde(skip_serializing_if="$path")]</code>, where
<code>$path</code> is a path reference to some function that returns a <code>bool</code>, that if
true, should skip serializing the field.</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">trait</span> <span class="n">ShouldSkip</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">should_skip</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">bool</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">struct</span> <span class="n">Point</span><span class="o">&lt;</span><span class="n">T</span><span class="o">:</span> <span class="n">ShouldSkip</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">x</span><span class="o">:</span> <span class="n">T</span><span class="p">,</span>
</span><span class='line'>    <span class="cp">#[serde(skip_serializing_if=</span><span class="s">&quot;ShouldSkip::should_skip&quot;</span><span class="cp">)]</span>
</span><span class='line'>    <span class="n">y</span><span class="o">:</span> <span class="n">T</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>Added the field annotations <code>#[serde(serialize_with="$path")]</code> and
<code>#[serde(deserialize_with="$path")]</code>, where <code>$path</code> us a path reference to
some function that serializes a field, as in:</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">trait</span> <span class="n">MySerialization</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_with</span><span class="o">&lt;</span><span class="n">S</span><span class="o">:</span> <span class="n">Serializer</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span> <span class="n">serializer</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">S</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">S</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">deserialize_with</span><span class="o">&lt;</span><span class="n">D</span><span class="o">:</span> <span class="n">Deserializer</span><span class="o">&gt;</span><span class="p">(</span><span class="n">deserializer</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">D</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="p">,</span> <span class="n">D</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">struct</span> <span class="n">Record</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[serde(serialize_with=</span><span class="s">&quot;MySerialization::serialize_with&quot;</span><span class="cp">)]</span>
</span><span class='line'>    <span class="cp">#[serde(deserialize_with=</span><span class="s">&quot;MySerialization::deserialize_with&quot;</span><span class="cp">)]</span>
</span><span class='line'>    <span class="n">timestamp</span><span class="o">:</span> <span class="n">time</span><span class="o">::</span><span class="n">Timespec</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Serde JSON</h2>

<ul>
<li>Added <code>StreamDeserializer</code>, that enables parsing a stream of JSON values optionally
separated by whitespace into an iterator of those deserialized values.</li>
</ul>


<h2>Thanks</h2>

<p>I&rsquo;d like to thank everyone that&rsquo;s helped out over the past few months. Please
forgive me if I accidentally left you off the list:</p>

<ul>
<li>Craig M. Brandenburg</li>
<li>Florian Gilcher</li>
<li>Hans Kristian Flaatten</li>
<li>Issam Hakimi</li>
<li>Joe Wilm</li>
<li>John Heitmann</li>
<li>Marek Kotewicz</li>
<li>Ms2ger</li>
<li>Nathan Lilienthal</li>
<li>Oliver Schneider</li>
<li>Paul Woolcock</li>
<li>Roma Sokolov</li>
<li>Simon Persson</li>
<li>Thomas Bahn</li>
<li>Tom Jakubowski</li>
<li>thorbenk</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Stateful, Part 2: How Stateful Cheats at Analysis]]></title>
    <link href="http://erickt.github.io/blog/2016/01/28/stateful/"/>
    <updated>2016-01-28T08:22:33-08:00</updated>
    <id>http://erickt.github.io/blog/2016/01/28/stateful</id>
    <content type="html"><![CDATA[<p>As I mentioned in the last
<a href="https://erickt.github.io/blog/2016/01/27/stateful-in-progress-generators/">part</a>,
<code>Stateful</code> has some challenges it needs to overcome in order to add new and
exciting control flow mechanisms to Rust.  While we don&rsquo;t get access to any of
the cool analysis passes inside the Rust compiler, <code>Stateful</code> is able to sneak
around their necessity in many cases since it really only needs to support a
subset of Rust.  Here are some of the techniques it exploits, err, uses.</p>

<h3>Variables</h3>

<p>First off, let&rsquo;s talk about variables.  One of the primary things <code>Stateful</code>
needs to do is manage the process of state flowing through the machine.  However,
consider a statement like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="kd">let</span> <span class="n">x</span> <span class="o">=</span> <span class="p">...;</span>
</span></code></pre></td></tr></table></div></figure>


<p>&ldquo;Obviously it&rsquo;s a variable, right?&rdquo;  Actually you can&rsquo;t be sure.  What if
someone did:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">enum</span> <span class="n">Foo</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">x</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="kn">use</span> <span class="n">Foo</span><span class="o">::*</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Well then the compiler would helpfully report:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">foo</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">7</span><span class="o">:</span><span class="mi">9</span><span class="o">:</span> <span class="mi">7</span><span class="o">:</span><span class="mi">10</span> <span class="n">error</span><span class="o">:</span> <span class="n">declaration</span> <span class="n">of</span> <span class="err">`</span><span class="n">x</span><span class="err">`</span> <span class="n">shadows</span> <span class="n">an</span> <span class="k">enum</span> <span class="n">variant</span> <span class="n">or</span> <span class="n">unit</span><span class="o">-</span><span class="n">like</span> <span class="k">struct</span> <span class="k">in</span> <span class="n">scope</span> <span class="p">[</span><span class="n">E0413</span><span class="p">]</span>
</span><span class='line'><span class="n">foo</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">7</span>     <span class="kd">let</span> <span class="n">x</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>But that warning only works for simple <code>let</code> statements.  Consider what happens
with matches.  Consider:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">match</span> <span class="p">...</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">x</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="p">...</span> <span class="p">}</span>
</span><span class='line'>    <span class="n">y</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="p">...</span> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Is <code>x</code> or <code>y</code> a variable, or a variant?  There&rsquo;s no way to know unless you
perform name resolution, otherwise known as the resolve pass in the compiler.
Unfortunately though, there&rsquo;s no way for <code>Stateful</code> to run that analysis.  As
Sméagol said, &ldquo;There is another way.  More secret, and dark way.&rdquo;.  This leads
us to Cheat Number One: <strong>Stateful assumes that all lowercase identifiers are
variables, and uppercase ones are enum variants.</strong> Sure, Rust supports
lowercase variants, but there&rsquo;s no reason why <code>Stateful</code> has to use them.  It
makes our lives much easier.</p>

<h3>Types</h3>

<p>The next problem is typing.  Sure, Rust is nice and all that you can write a
local variable like <code>let x = ...</code> and it&rsquo;ll infer the type for you.  All Rust
asks for is that the user explicitly specify the type of a value that enters or
leaves the bounds of a function.  Our problem is that one of the main tasks of
<code>Stateful</code> is to lift variables into some <code>State</code> structure so that their
available when the function is re-entered.  So in effect, all variables inside
<code>Stateful</code> must be typed.  Consider the example from last week:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">fn</span> <span class="n">advance</span><span class="p">(</span><span class="k">mut</span> <span class="n">state</span><span class="o">:</span> <span class="n">State</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="nb">Option</span><span class="o">&lt;</span><span class="n">usize</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">State</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">loop</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">match</span> <span class="n">state</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">Enter</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="kd">let</span> <span class="k">mut</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>                <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Loop</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">i</span> <span class="p">});</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">Loop</span> <span class="p">{</span> <span class="k">mut</span> <span class="n">i</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">3</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Then</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">i</span> <span class="p">});</span>
</span><span class='line'>                <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Else</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">i</span> <span class="p">});</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">Then</span> <span class="p">{</span> <span class="k">mut</span> <span class="n">i</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">return_</span><span class="o">!</span><span class="p">(</span><span class="nb">Some</span><span class="p">(</span><span class="n">i</span><span class="p">);</span> <span class="n">State</span><span class="o">::</span><span class="n">AfterYield</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">i</span> <span class="p">});</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">Else</span> <span class="p">{</span> <span class="k">mut</span> <span class="n">i</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">AfterLoop</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">i</span> <span class="p">});</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">AfterYield</span> <span class="p">{</span> <span class="k">mut</span> <span class="n">i</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>                <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Loop</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">i</span> <span class="p">});</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">AfterLoop</span> <span class="p">{</span> <span class="k">mut</span> <span class="n">i</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Exit</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">Exit</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">return_</span><span class="o">!</span><span class="p">(</span><span class="nb">None</span><span class="p">;</span> <span class="n">State</span><span class="o">::</span><span class="n">Exit</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>This <code>State</code> enumeration is what I&rsquo;m talking about.  It gets passed into and
out of the <code>advance</code> function.  It needs to be some concrete type, which looks
something like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">enum</span> <span class="n">State</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">Enter</span><span class="p">,</span>
</span><span class='line'>    <span class="n">Loop</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">usize</span> <span class="p">},</span>
</span><span class='line'>    <span class="n">Then</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">usize</span> <span class="p">},</span>
</span><span class='line'>    <span class="n">Else</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">usize</span> <span class="p">},</span>
</span><span class='line'>    <span class="n">AfterYield</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">usize</span> <span class="p">},</span>
</span><span class='line'>    <span class="n">AfterLoop</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">usize</span> <span class="p">},</span>
</span><span class='line'>    <span class="n">Exit</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The problem is that we want to write code like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[generator]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">gen3</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Item</span><span class="o">=</span><span class="n">usize</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>    <span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">3</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">yield_</span><span class="o">!</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
</span><span class='line'>        <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>So how can we resolve this?  Well first, we could wait for
<a href="https://github.com/rust-lang/rfcs/pull/105">RFC 105</a>
or <a href="https://github.com/rust-lang/rfcs/pull/1305">RFC 1305</a> to get implemented,
but that&rsquo;s not happening any time soon.  Until then, there is cheat number two:
<strong>Hide state variables in a boxed trait</strong>.  This one is from Eduard Burtescu.
Instead of the nice well typed example from the last post, we actually generate
some code that hides the types with an over abundance of generic types:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">fn</span> <span class="n">gen3</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Item</span><span class="o">=</span><span class="n">usize</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">struct</span> <span class="n">Wrapper</span><span class="o">&lt;</span><span class="n">S</span><span class="p">,</span> <span class="n">F</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">state</span><span class="o">:</span> <span class="n">S</span><span class="p">,</span>
</span><span class='line'>        <span class="n">next</span><span class="o">:</span> <span class="n">F</span><span class="p">,</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">impl</span><span class="o">&lt;</span><span class="n">S</span><span class="p">,</span> <span class="n">T</span><span class="p">,</span> <span class="n">F</span><span class="o">&gt;</span> <span class="nb">Iterator</span> <span class="k">for</span> <span class="n">Wrapper</span><span class="o">&lt;</span><span class="n">S</span><span class="p">,</span> <span class="n">F</span><span class="o">&gt;</span>
</span><span class='line'>        <span class="n">where</span> <span class="n">S</span><span class="o">:</span> <span class="nb">Default</span><span class="p">,</span>
</span><span class='line'>              <span class="n">F</span><span class="o">:</span> <span class="n">Fn</span><span class="p">(</span><span class="n">S</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="nb">Option</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">S</span><span class="p">)</span>
</span><span class='line'>      <span class="p">{</span>
</span><span class='line'>          <span class="k">type</span> <span class="n">Item</span> <span class="o">=</span> <span class="n">T</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>          <span class="k">fn</span> <span class="n">next</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Option</span><span class="o">&lt;</span><span class="n">Self</span><span class="o">::</span><span class="n">Item</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>              <span class="kd">let</span> <span class="n">old_state</span> <span class="o">=</span> <span class="o">::</span><span class="n">std</span><span class="o">::</span><span class="n">mem</span><span class="o">::</span><span class="n">replace</span><span class="p">(</span>
</span><span class='line'>                  <span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">.</span><span class="n">state</span><span class="p">,</span>
</span><span class='line'>                  <span class="n">S</span><span class="o">::</span><span class="n">default</span><span class="p">());</span>
</span><span class='line'>
</span><span class='line'>              <span class="kd">let</span> <span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">next_state</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">next</span><span class="p">)(</span><span class="n">old_state</span><span class="p">);</span>
</span><span class='line'>              <span class="bp">self</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">next_state</span><span class="p">;</span>
</span><span class='line'>              <span class="n">value</span>
</span><span class='line'>          <span class="p">}</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">enum</span> <span class="n">State</span><span class="o">&lt;</span><span class="n">T0</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">Enter</span><span class="p">,</span>
</span><span class='line'>        <span class="n">Loop</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">T0</span> <span class="p">},</span>
</span><span class='line'>        <span class="n">Then</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">T0</span> <span class="p">},</span>
</span><span class='line'>        <span class="n">Else</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">T0</span> <span class="p">},</span>
</span><span class='line'>        <span class="n">AfterYield</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">T0</span> <span class="p">},</span>
</span><span class='line'>        <span class="n">AfterLoop</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">T0</span> <span class="p">},</span>
</span><span class='line'>        <span class="n">Exit</span><span class="p">,</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">impl</span><span class="o">&lt;</span><span class="n">T0</span><span class="o">&gt;</span> <span class="nb">Default</span> <span class="k">for</span> <span class="n">State</span><span class="o">&lt;</span><span class="n">T0</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">fn</span> <span class="n">default</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Self</span> <span class="p">{</span>
</span><span class='line'>            <span class="p">{</span>
</span><span class='line'>                <span class="n">State</span><span class="o">::</span><span class="n">State1End</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">Box</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="n">Wrapper</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Start</span><span class="p">,</span> <span class="o">|</span><span class="k">mut</span> <span class="n">state</span><span class="o">|</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">loop</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">match</span> <span class="n">state</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">State</span><span class="o">::</span><span class="n">Enter</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                    <span class="kd">let</span> <span class="k">mut</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>                    <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Loop</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">i</span> <span class="p">});</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>                <span class="n">State</span><span class="o">::</span><span class="n">Loop</span> <span class="p">{</span> <span class="k">mut</span> <span class="n">i</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                    <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">3</span> <span class="p">{</span>
</span><span class='line'>                        <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Then</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">i</span> <span class="p">});</span>
</span><span class='line'>                    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>                        <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Else</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">i</span> <span class="p">});</span>
</span><span class='line'>                    <span class="p">}</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>                <span class="n">State</span><span class="o">::</span><span class="n">Then</span> <span class="p">{</span> <span class="k">mut</span> <span class="n">i</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">return_</span><span class="o">!</span><span class="p">(</span><span class="nb">Some</span><span class="p">(</span><span class="n">i</span><span class="p">);</span> <span class="n">State</span><span class="o">::</span><span class="n">AfterYield</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">i</span> <span class="p">});</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>                <span class="n">State</span><span class="o">::</span><span class="n">Else</span> <span class="p">{</span> <span class="k">mut</span> <span class="n">i</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">AfterLoop</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">i</span> <span class="p">});</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>                <span class="n">State</span><span class="o">::</span><span class="n">AfterYield</span> <span class="p">{</span> <span class="k">mut</span> <span class="n">i</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>                    <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Loop</span> <span class="p">{</span> <span class="n">i</span><span class="o">:</span> <span class="n">i</span> <span class="p">});</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>                <span class="n">State</span><span class="o">::</span><span class="n">AfterLoop</span> <span class="p">{</span> <span class="k">mut</span> <span class="n">i</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Exit</span><span class="p">);</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>                <span class="n">State</span><span class="o">::</span><span class="n">Exit</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">return_</span><span class="o">!</span><span class="p">(</span><span class="nb">None</span><span class="p">;</span> <span class="n">State</span><span class="o">::</span><span class="n">Exit</span><span class="p">);</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}))</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>All for the cost of a boxed variable.  It&rsquo;s not ideal, but it does let us keep
experimenting.  However, if we do want to avoid this allocation, we can just
require that all variables that survive across a yield point have their type
specified.  So our previous example would be written as:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[generator]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">gen3</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Item</span><span class="o">=</span><span class="n">usize</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">i</span><span class="o">:</span> <span class="n">usize</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>    <span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">3</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">yield_</span><span class="o">!</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
</span><span class='line'>        <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>It&rsquo;s not so bad here, but it&rsquo;d get obnoxious if we had a generator like:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[generator]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">complicated</span><span class="p">(</span><span class="n">items</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="n">usize</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Item</span><span class="o">=</span><span class="n">usize</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">items</span><span class="p">.</span><span class="n">iter</span><span class="p">().</span><span class="n">map</span><span class="p">(</span><span class="o">|</span><span class="n">item</span><span class="o">|</span> <span class="n">item</span> <span class="o">*</span> <span class="mi">3</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">for</span> <span class="n">item</span> <span class="k">in</span> <span class="n">iter</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">yield_</span><span class="o">!</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The type of <code>iter</code>, by the way, is impossible to write because there is
currently no way to specify the type of the closure.  Instead, it needs to be
rewritten to use a free function:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[generator]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">complicated</span><span class="p">(</span><span class="n">items</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="n">usize</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Item</span><span class="o">=</span><span class="n">usize</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">map</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="n">usize</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">usize</span> <span class="p">{</span> <span class="o">*</span><span class="n">item</span> <span class="o">*</span> <span class="mi">3</span> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="n">iter</span><span class="o">:</span> <span class="n">std</span><span class="o">::</span><span class="n">iter</span><span class="o">::</span><span class="nb">Map</span><span class="o">&lt;</span>
</span><span class='line'>            <span class="n">std</span><span class="o">::</span><span class="n">slice</span><span class="o">::</span><span class="n">Iter</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="p">,</span> <span class="n">usize</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'>            <span class="k">fn</span><span class="p">(</span><span class="o">&amp;</span><span class="n">&#39;a</span> <span class="n">usize</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">usize</span>
</span><span class='line'>        <span class="o">&gt;</span>
</span><span class='line'>        <span class="o">=</span> <span class="n">items</span><span class="p">.</span><span class="n">iter</span><span class="p">().</span><span class="n">map</span><span class="p">(</span><span class="n">map</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">for</span> <span class="n">item</span> <span class="k">in</span> <span class="n">iter</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">yield_</span><span class="o">!</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>If we want to support closures though, we need to use the <code>Box&lt;Iterator&lt;...&gt;</code>
trick.</p>

<h3>References</h3>

<p>This one&rsquo;s a doozy.  Here&rsquo;s an example of the problem.  Consider:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[generator]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">gen</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span><span class="p">(</span><span class="n">opt</span><span class="o">:</span> <span class="nb">Option</span><span class="o">&lt;&amp;</span><span class="n">&#39;a</span> <span class="k">mut</span> <span class="n">usize</span><span class="o">&gt;</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Item</span><span class="o">=&amp;</span><span class="n">&#39;a</span> <span class="k">mut</span> <span class="n">usize</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">match</span> <span class="n">opt</span> <span class="p">{</span>
</span><span class='line'>        <span class="nb">Some</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="n">yield_</span><span class="o">!</span><span class="p">(</span><span class="n">value</span><span class="p">);</span> <span class="p">}</span>
</span><span class='line'>        <span class="nb">None</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>This would look something like this (which also demonstrates how <code>match</code>
statements are represented):</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="p">...</span>
</span><span class='line'><span class="n">Box</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="n">Wrapper</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">State0Start</span> <span class="p">{</span> <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span> <span class="p">},</span> <span class="o">|</span><span class="k">mut</span> <span class="n">state</span><span class="o">|</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">loop</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">match</span> <span class="n">state</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">State0Start</span> <span class="p">{</span> <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">match</span> <span class="n">opt</span> <span class="p">{</span>
</span><span class='line'>                    <span class="nb">Some</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                        <span class="n">state</span> <span class="o">=</span> <span class="n">State</span><span class="o">::</span><span class="n">State2Arm</span> <span class="p">{</span>
</span><span class='line'>                            <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span><span class="p">,</span>
</span><span class='line'>                            <span class="n">value</span><span class="o">:</span> <span class="n">value</span><span class="p">,</span>
</span><span class='line'>                        <span class="p">};</span>
</span><span class='line'>                        <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>                    <span class="p">}</span>
</span><span class='line'>                    <span class="nb">None</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                        <span class="n">state</span> <span class="o">=</span> <span class="n">State</span><span class="o">::</span><span class="n">State3Arm</span> <span class="p">{</span> <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span> <span class="p">};</span>
</span><span class='line'>                        <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>                    <span class="p">}</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">State1End</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">return</span> <span class="p">(</span><span class="o">::</span><span class="n">std</span><span class="o">::</span><span class="n">option</span><span class="o">::</span><span class="nb">Option</span><span class="o">::</span><span class="nb">None</span><span class="p">,</span> <span class="n">State</span><span class="o">::</span><span class="n">State1End</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">State2Arm</span> <span class="p">{</span> <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span><span class="p">,</span> <span class="n">value</span><span class="o">:</span> <span class="n">value</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">return</span> <span class="p">(</span><span class="o">::</span><span class="n">std</span><span class="o">::</span><span class="n">option</span><span class="o">::</span><span class="nb">Option</span><span class="o">::</span><span class="nb">Some</span><span class="p">(</span><span class="n">value</span><span class="p">),</span>
</span><span class='line'>                        <span class="n">State</span><span class="o">::</span><span class="n">State5AfterYield</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span><span class="p">,</span>
</span><span class='line'>                    <span class="n">value</span><span class="o">:</span> <span class="n">value</span><span class="p">,</span>
</span><span class='line'>                <span class="p">});</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">State3Arm</span> <span class="p">{</span> <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="p">{</span>
</span><span class='line'>                <span class="p">};</span>
</span><span class='line'>                <span class="n">state</span> <span class="o">=</span> <span class="n">State</span><span class="o">::</span><span class="n">State4MatchJoin</span> <span class="p">{</span> <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span> <span class="p">};</span>
</span><span class='line'>                <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">State4MatchJoin</span> <span class="p">{</span> <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="o">::</span><span class="n">std</span><span class="o">::</span><span class="n">mem</span><span class="o">::</span><span class="nb">drop</span><span class="p">(</span><span class="n">opt</span><span class="p">);</span>
</span><span class='line'>                <span class="n">state</span> <span class="o">=</span> <span class="n">State</span><span class="o">::</span><span class="n">State1End</span><span class="p">;</span>
</span><span class='line'>                <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">State5AfterYield</span> <span class="p">{</span>
</span><span class='line'>                              <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span><span class="p">,</span> <span class="n">value</span><span class="o">:</span> <span class="n">value</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="o">::</span><span class="n">std</span><span class="o">::</span><span class="n">mem</span><span class="o">::</span><span class="nb">drop</span><span class="p">(</span><span class="n">value</span><span class="p">);</span>
</span><span class='line'>                <span class="n">state</span> <span class="o">=</span> <span class="n">State</span><span class="o">::</span><span class="n">State4MatchJoin</span> <span class="p">{</span> <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span> <span class="p">};</span>
</span><span class='line'>                <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}))</span>
</span></code></pre></td></tr></table></div></figure>


<p>Zero in on this block:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="p">...</span>
</span><span class='line'><span class="nb">Some</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">state</span> <span class="o">=</span> <span class="n">State</span><span class="o">::</span><span class="n">State2Arm</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span><span class="p">,</span>
</span><span class='line'>        <span class="n">value</span><span class="o">:</span> <span class="n">value</span><span class="p">,</span>
</span><span class='line'>    <span class="p">};</span>
</span><span class='line'>    <span class="k">continue</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="p">...</span>
</span></code></pre></td></tr></table></div></figure>


<p>The type of <code>opt</code> is <code>Option&lt;&amp;'a mut usize&gt;</code>, and <code>value</code> is <code>&amp;'a mut usize</code>.
So we&rsquo;ve got two outstanding mutable borrows, which is illegal.  The real
problem is that <code>Stateful</code> without Resolve and the Borrow Checker pass, it
cannot know if a use of the variable is a copy or move in all cases.  So we now
have cheat number 3: <strong>Use pseudo-macros to hint to Stateful if a type is
copyable or movable</strong>.  This is the same technique we use to implement the
pseudo-macro <code>yield_!(...)</code>, where we would add <code>move_!(...)</code> and <code>copy_!(...)</code>
to inform <code>Stateful</code> when something has been, well, moved or copied.  Our
previous example would then be written as:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[generator]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">gen</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span><span class="p">(</span><span class="n">opt</span><span class="o">:</span> <span class="nb">Option</span><span class="o">&lt;&amp;</span><span class="n">&#39;a</span> <span class="k">mut</span> <span class="n">usize</span><span class="o">&gt;</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Item</span><span class="o">=&amp;</span><span class="n">&#39;a</span> <span class="k">mut</span> <span class="n">usize</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">match</span> <span class="n">move_</span><span class="o">!</span><span class="p">(</span><span class="n">opt</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="nb">Some</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="n">yield_</span><span class="o">!</span><span class="p">(</span><span class="n">value</span><span class="p">);</span> <span class="p">}</span>
</span><span class='line'>        <span class="nb">None</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Which would then give <code>Stateful</code> enough information to generate something like
this, which would then know that the match consumed the option:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">Box</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="n">Wrapper</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">State0Start</span> <span class="p">{</span> <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span> <span class="p">},</span> <span class="o">|</span><span class="k">mut</span> <span class="n">state</span><span class="o">|</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">loop</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">match</span> <span class="n">state</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">State0Start</span> <span class="p">{</span> <span class="n">opt</span><span class="o">:</span> <span class="n">opt</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">match</span> <span class="n">opt</span> <span class="p">{</span>
</span><span class='line'>                    <span class="nb">Some</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                        <span class="n">state</span> <span class="o">=</span> <span class="n">State</span><span class="o">::</span><span class="n">State2Arm</span> <span class="p">{</span>
</span><span class='line'>                            <span class="n">value</span><span class="o">:</span> <span class="n">value</span><span class="p">,</span>
</span><span class='line'>                        <span class="p">};</span>
</span><span class='line'>                        <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>                    <span class="p">}</span>
</span><span class='line'>                    <span class="nb">None</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                        <span class="n">state</span> <span class="o">=</span> <span class="n">State</span><span class="o">::</span><span class="n">State3Arm</span><span class="p">;</span>
</span><span class='line'>                        <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>                    <span class="p">}</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">State1End</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">return</span> <span class="p">(</span><span class="o">::</span><span class="n">std</span><span class="o">::</span><span class="n">option</span><span class="o">::</span><span class="nb">Option</span><span class="o">::</span><span class="nb">None</span><span class="p">,</span> <span class="n">State</span><span class="o">::</span><span class="n">State1End</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">State2Arm</span> <span class="p">{</span> <span class="n">value</span><span class="o">:</span> <span class="n">value</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">return</span> <span class="p">(</span><span class="o">::</span><span class="n">std</span><span class="o">::</span><span class="n">option</span><span class="o">::</span><span class="nb">Option</span><span class="o">::</span><span class="nb">Some</span><span class="p">(</span><span class="n">value</span><span class="p">),</span>
</span><span class='line'>                <span class="n">State</span><span class="o">::</span><span class="n">State5AfterYield</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">State3Arm</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">state</span> <span class="o">=</span> <span class="n">State</span><span class="o">::</span><span class="n">State4MatchJoin</span><span class="p">;</span>
</span><span class='line'>                <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">State4MatchJoin</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">state</span> <span class="o">=</span> <span class="n">State</span><span class="o">::</span><span class="n">State1End</span><span class="p">;</span>
</span><span class='line'>                <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">State5AfterYield</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">state</span> <span class="o">=</span> <span class="n">State</span><span class="o">::</span><span class="n">State4MatchJoin</span><span class="p">;</span>
</span><span class='line'>                <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}))</span>
</span></code></pre></td></tr></table></div></figure>


<p>I&rsquo;m also considering some default rules, that can be overridden with these
macros:</p>

<ul>
<li>If a value is known to be copyable (it&rsquo;s a primitive type, or it&rsquo;s a <code>&amp;T</code>
type), then it&rsquo;s always copied. All other types are assumed to not be
copyable.</li>
<li>Non-copyable types are moved when passed into a function argument, unless
wrapped in a <code>copy_!(...)</code> hint.</li>
<li>Non-copyable type method calls are by reference, unless explicitly wrapped in
a <code>move_!(...)</code> hint.</li>
<li>Non-copyable types are moved in <code>match</code> statement, unless one of the match
arms uses <code>ref</code> or <code>ref mut</code>.</li>
</ul>


<p>Hopefully this will enable a vast majority of code to work without
<code>copy_!(...)</code> or <code>move_!(...)</code>.</p>

<h3>Conclusion</h3>

<p>Those are our major cheats!  I&rsquo;m sure there will be plenty more in the future.
In the meantime, I want to show off some some actual working code!  Check this
puppy out!</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">feature</span><span class="p">(</span><span class="n">plugin</span><span class="p">)]</span>
</span><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">plugin</span><span class="p">(</span><span class="n">stateful</span><span class="p">)]</span>
</span><span class='line'>
</span><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">allow</span><span class="p">(</span><span class="n">dead_code</span><span class="p">)]</span>
</span><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">allow</span><span class="p">(</span><span class="n">non_shorthand_field_patterns</span><span class="p">)]</span>
</span><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">allow</span><span class="p">(</span><span class="n">unused_mut</span><span class="p">)]</span>
</span><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">allow</span><span class="p">(</span><span class="n">unused_variables</span><span class="p">)]</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[generator]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">gen</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="p">,</span> <span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">items</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="p">[</span><span class="n">T</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="n">T</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">items</span><span class="p">.</span><span class="n">iter</span><span class="p">();</span>
</span><span class='line'>    <span class="k">loop</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">match</span> <span class="n">iter</span><span class="p">.</span><span class="n">next</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Some</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">yield_</span><span class="o">!</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="nb">None</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">break</span><span class="p">;</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">};</span>
</span><span class='line'>    <span class="p">};</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">items</span> <span class="o">=</span> <span class="o">&amp;</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">];</span>
</span><span class='line'>    <span class="k">for</span> <span class="n">value</span> <span class="k">in</span> <span class="n">gen</span><span class="p">(</span><span class="n">items</span><span class="p">).</span><span class="n">take</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="nb">println</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;{}&quot;</span><span class="p">,</span> <span class="n">value</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Produces:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="mi">1</span>
</span><span class='line'><span class="mi">2</span>
</span><span class='line'><span class="mi">3</span>
</span></code></pre></td></tr></table></div></figure>


<p>Isn&rsquo;t it beautiful?  We got generics, mutable variables, loops, matches,
breaks, <strong>and</strong> a whole host of ignored warnings!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Stateful: A Rust Experimental Syntax Extension for Generators and More]]></title>
    <link href="http://erickt.github.io/blog/2016/01/27/stateful-in-progress-generators/"/>
    <updated>2016-01-27T08:31:27-08:00</updated>
    <id>http://erickt.github.io/blog/2016/01/27/stateful-in-progress-generators</id>
    <content type="html"><![CDATA[<p>AKA: Erick Does More Horrible Things to Rust</p>

<p>Hello internet! It&rsquo;s been too long. Not only are the
<a href="http://www.meetup.com/rust-bay-area">Rust Meetups</a> back up and running, it&rsquo;s
time for me to start back to blogging. For the past couple months, I&rsquo;ve been
working on a new syntax extension that will allow people to create fun and
exciting new control flow mechanisms in stable Rust.  &ldquo;For the love of all that
is sigils, why?!&rdquo;  Well, Because I can.  Sometimes when you stare into the
madness, it stares back into you? Or something like that?</p>

<p>It&rsquo;s called <a href="https://github.com/erickt/stateful">Stateful</a>, which helpfully has
no documentation. Such an innocent name, right?  It&rsquo;s very much in progress
(and mostly broken) implementation of some of the ideas in this and future
posts.  So don&rsquo;t go and think these code snippets are executable just yet :)</p>

<p>Anyway, lets show off <code>Stateful</code> by showing how we can implement
<a href="https://en.wikipedia.org/wiki/Generator_%28computer_programming%29">Generators</a>.
We&rsquo;ve got an <a href="https://github.com/rust-lang/rfcs/issues/388">RFC ticket</a> to
implement them, but wouldn&rsquo;t it be nice to have them sooner?  For those of you
unfamiliar with the concept, Generators are function that can be returned from
multiple times, all while preserving state between those calls.  Basically,
they&rsquo;re just a simpler way to write
<a href="https://doc.rust-lang.org/std/iter/#iterator">Iterators</a>.</p>

<p>Say we wanted to iterate over the numbers 0, 1, and 2.  Today, we would write
an <code>Iterator</code> with something like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">struct</span> <span class="n">Iter3</span><span class="p">(</span><span class="n">usize</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span> <span class="n">Iter3</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">new</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Self</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">Iter3</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span> <span class="nb">Iterator</span> <span class="k">for</span> <span class="n">Iter3</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">next</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Option</span><span class="o">&lt;</span><span class="n">usize</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="mi">0</span> <span class="o">&lt;</span> <span class="mi">3</span> <span class="p">{</span>
</span><span class='line'>            <span class="kd">let</span> <span class="n">i</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="mi">0</span><span class="p">;</span>
</span><span class='line'>            <span class="bp">self</span><span class="p">.</span><span class="mi">0</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>            <span class="nb">Some</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">None</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">iter</span> <span class="o">=</span> <span class="n">Iter3</span><span class="o">::</span><span class="n">new</span><span class="p">();</span>
</span><span class='line'>    <span class="n">assert_eq</span><span class="o">!</span><span class="p">(</span><span class="n">iter</span><span class="p">.</span><span class="n">next</span><span class="p">(),</span> <span class="nb">Some</span><span class="p">(</span><span class="mi">0</span><span class="p">));</span>
</span><span class='line'>    <span class="n">assert_eq</span><span class="o">!</span><span class="p">(</span><span class="n">iter</span><span class="p">.</span><span class="n">next</span><span class="p">(),</span> <span class="nb">Some</span><span class="p">(</span><span class="mi">1</span><span class="p">));</span>
</span><span class='line'>    <span class="n">assert_eq</span><span class="o">!</span><span class="p">(</span><span class="n">iter</span><span class="p">.</span><span class="n">next</span><span class="p">(),</span> <span class="nb">Some</span><span class="p">(</span><span class="mi">2</span><span class="p">));</span>
</span><span class='line'>    <span class="n">assert_eq</span><span class="o">!</span><span class="p">(</span><span class="n">iter</span><span class="p">.</span><span class="n">next</span><span class="p">(),</span> <span class="nb">None</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The struct preserves our state across these function calls.  It&rsquo;s a pretty
straightforward implementation, but it does have some amount of boilerplate
code. For large iterator implementations, this state management can get quite
complicated.  Instead, lets see how this same code could be expressed with
something like <code>Stateful</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">plugin</span><span class="p">(</span><span class="n">stateful</span><span class="p">)]</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[generator]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">gen3</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Item</span><span class="o">=</span><span class="n">usize</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>    <span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">3</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">yield_</span><span class="o">!</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
</span><span class='line'>        <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Where <code>yield_!(i)</code> is some magical control flow mechanism that not only
returned some value <code>Some(i)</code>, but also made sure on the <code>iter.next()</code> would
jump the execution to just after the yield.  At the end of the generator, we&rsquo;d
just return <code>None</code>.  We could simplify this even more by unrolling that loop
into:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[generator]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">gen3_unrolled</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Item</span><span class="o">=</span><span class="n">usize</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">yield_</span><span class="o">!</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
</span><span class='line'>    <span class="n">yield_</span><span class="o">!</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span><span class='line'>    <span class="n">yield_</span><span class="o">!</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The fun part is figuring out how to convert these generators into something
that&rsquo;s roughly equivalent to <code>Iter3</code>.  At it&rsquo;s heart, <code>Iter3</code> really is a
simple state machine, where we save the counter state in the structure before
we &ldquo;yield&rdquo; the value to the caller.  Let&rsquo;s look at what we would generate for
<code>gen3_unrolled</code>.</p>

<p>First, we need some boilerplate, that sets up the state of our generator.  We
don&rsquo;t yet have <a href="https://aturon.github.io/blog/2015/09/28/impl-trait/">impl
trait</a>, so we hide all
our stuff in a module:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">fn</span> <span class="n">gen3_unrolled</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">gen3_unrolled</span><span class="o">::</span><span class="n">Generator</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">gen3_unrolled</span><span class="o">::</span><span class="n">Generator</span><span class="o">::</span><span class="n">new</span><span class="p">()</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kn">mod</span> <span class="n">gen3_unrolled</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">pub</span> <span class="k">struct</span> <span class="n">Generator</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">state</span><span class="o">:</span> <span class="n">State</span><span class="p">,</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">impl</span> <span class="n">Generator</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">pub</span> <span class="k">fn</span> <span class="n">new</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Self</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">Generator</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">state</span><span class="o">:</span> <span class="n">State</span><span class="o">::</span><span class="n">Enter</span><span class="p">,</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">...</span>
</span></code></pre></td></tr></table></div></figure>


<p>We represent our generator&rsquo;s state with an enum.  We have our initial state, a
state per yield, then an exit state:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">enum</span> <span class="n">State</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">Enter</span><span class="p">,</span>
</span><span class='line'>    <span class="n">AfterYield0</span><span class="p">,</span>
</span><span class='line'>    <span class="n">AfterYield1</span><span class="p">,</span>
</span><span class='line'>    <span class="n">AfterYield2</span><span class="p">,</span>
</span><span class='line'>    <span class="n">Exit</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Finally, we have our state machine, and a pretty trivial <code>Iterator</code>
implementation that manages entering and exiting the state machine:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span> <span class="nb">Iterator</span> <span class="k">for</span> <span class="n">Generator</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">type</span> <span class="n">Item</span> <span class="o">=</span> <span class="n">usize</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">next</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Option</span><span class="o">&lt;</span><span class="n">usize</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">state</span> <span class="o">=</span> <span class="n">mem</span><span class="o">::</span><span class="n">replace</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">.</span><span class="n">state</span><span class="p">,</span> <span class="n">State</span><span class="o">::</span><span class="n">Exit</span><span class="p">);</span>
</span><span class='line'>        <span class="kd">let</span> <span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">next_state</span><span class="p">)</span> <span class="o">=</span> <span class="n">advance</span><span class="p">(</span><span class="n">state</span><span class="p">);</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">next_state</span><span class="p">;</span>
</span><span class='line'>        <span class="n">result</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">advance</span><span class="p">(</span><span class="k">mut</span> <span class="n">state</span><span class="o">:</span> <span class="n">State</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="nb">Option</span><span class="o">&lt;</span><span class="n">usize</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">State</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">loop</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">state</span> <span class="o">=</span> <span class="k">match</span> <span class="n">state</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">Enter</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">return_</span><span class="o">!</span><span class="p">(</span><span class="nb">Some</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="n">State</span><span class="o">::</span><span class="n">AfterYield0</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">AfterYield0</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">return_</span><span class="o">!</span><span class="p">(</span><span class="nb">Some</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="n">State</span><span class="o">::</span><span class="n">AfterYield1</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">AfterYield1</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">return_</span><span class="o">!</span><span class="p">(</span><span class="nb">Some</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span> <span class="n">State</span><span class="o">::</span><span class="n">AfterYield2</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">AfterYield2</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Exit</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">Exit</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">return_</span><span class="o">!</span><span class="p">(</span><span class="nb">None</span><span class="p">;</span> <span class="n">State</span><span class="o">::</span><span class="n">Exit</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>We move the current <code>state</code> into <code>advance</code>, then have this <code>loop-match</code> state
machine.  Then there are 2 new control flow constructs:
<code>return_!($expr; $next_state)</code> and our old friend <code>goto!($next_state)</code>.
<code>return_!()</code> returns some value and also sets the position the generator should
resume at, and <code>goto!()</code> just sets the next state without leaving the function.</p>

<p>Here&rsquo;s one way they might be implemented:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">macro_rules</span><span class="o">!</span> <span class="n">goto</span> <span class="p">{</span>
</span><span class='line'>    <span class="p">(</span><span class="err">$</span><span class="n">next_state</span><span class="o">:</span><span class="n">expr</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="err">$</span><span class="n">state</span> <span class="o">=</span> <span class="err">$</span><span class="n">next_state</span><span class="p">;</span>
</span><span class='line'>        <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="n">macro_rules</span><span class="o">!</span> <span class="n">return_</span> <span class="p">{</span>
</span><span class='line'>    <span class="p">(</span><span class="err">$</span><span class="n">result</span><span class="o">:</span> <span class="n">expr</span><span class="p">;</span> <span class="err">$</span><span class="n">next_state</span><span class="o">:</span><span class="n">expr</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="p">(</span><span class="err">$</span><span class="n">result</span><span class="p">,</span> <span class="err">$</span><span class="n">next_state</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Relatively straightforward transformation, right?  But that&rsquo;s an easy case.
Things start to get a wee bit more complicated when we start thinking about how
we&rsquo;d transform <code>gen3</code>, because it&rsquo;s got both a <code>while</code> loop and a mutable
variable.  Lets see that in action.  I&rsquo;ll leave out the boilerplate code and
just focus on the <code>advance</code> function:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">fn</span> <span class="n">advance</span><span class="p">(</span><span class="k">mut</span> <span class="n">state</span><span class="o">:</span> <span class="n">State</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="nb">Option</span><span class="o">&lt;</span><span class="n">usize</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">State</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">loop</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">match</span> <span class="n">state</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">Enter</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="kd">let</span> <span class="k">mut</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>                <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Loop</span><span class="p">(</span><span class="n">i</span><span class="p">));</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">Loop</span><span class="p">(</span><span class="k">mut</span> <span class="n">i</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">3</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Then</span><span class="p">(</span><span class="n">i</span><span class="p">));</span>
</span><span class='line'>                <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Else</span><span class="p">(</span><span class="n">i</span><span class="p">));</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">Then</span><span class="p">(</span><span class="k">mut</span> <span class="n">i</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">return_</span><span class="o">!</span><span class="p">(</span><span class="nb">Some</span><span class="p">(</span><span class="n">i</span><span class="p">);</span> <span class="n">State</span><span class="o">::</span><span class="n">AfterYield</span><span class="p">(</span><span class="n">i</span><span class="p">));</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">Else</span><span class="p">(</span><span class="k">mut</span> <span class="n">i</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">AfterLoop</span><span class="p">(</span><span class="n">i</span><span class="p">));</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">AfterYield</span><span class="p">(</span><span class="k">mut</span> <span class="n">i</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>                <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Loop</span><span class="p">(</span><span class="n">i</span><span class="p">));</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">AfterLoop</span><span class="p">(</span><span class="k">mut</span> <span class="n">i</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">goto</span><span class="o">!</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">Exit</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">State</span><span class="o">::</span><span class="n">Exit</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">return_</span><span class="o">!</span><span class="p">(</span><span class="nb">None</span><span class="p">;</span> <span class="n">State</span><span class="o">::</span><span class="n">Exit</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now things are getting interesting! There are two critical things we can see
off the bat.  First, we need to reify the loops and conditionals into the state
machine, because they affect the control flow.  Second, we need to lift any
variables that are accessed across states into the <code>State</code> enum.</p>

<p>We can also start seeing the complications.  The obvious one is mutable
variables.  We need to somehow thread the information about <code>i</code>&rsquo;s mutability
through each of the states.  This naive implementation would trip over the
<code>#[warn(unused_mut)]</code> lint.  And now you might start to get a sense of the
horror that lies beneath <code>Stateful</code>.</p>

<p>At this point, you might be thinking to yourself, &ldquo;Self, if mutable variables
are going to be complicated, what about copies and moves?&rdquo;  You sound like a
pretty sensible person.  Therein lies madness.  You might want to stop thinking
too deeply on it.  If you can&rsquo;t, maybe you think &ldquo;Wait.
What about Generics?&rdquo; Yep.  &ldquo;Borrows?!&rdquo;  Now I&rsquo;m getting a little worried.
&ldquo;How do you even know what&rsquo;s a variable!?!&rdquo;  Sorry.</p>

<p>Yeah so there are one or two things that might be a tad challenging.</p>

<hr />

<p>So that&rsquo;s <code>Stateful</code>.  It&rsquo;s an experiment to get some real world experience
with these control flow mechanisms that may someday feed into RFCs, and maybe,
just maybe, might get implemented in the compiler.  There&rsquo;s no reason we need
to support everything, which would require us to basically reimplement the
compiler.  Instead, I believe there&rsquo;s a subset of Rust that we <em>can</em> support in
order to start getting real experience now.</p>

<p>Generators area really just the start.  There&rsquo;s a whole host of other things
that really are just other things that, if you just squint at em, are really
just state machines in disguise.  It&rsquo;s quite possible if we can pull
<code>Stateful</code>, we&rsquo;ll also be able to implement things like
<a href="https://en.wikipedia.org/wiki/Coroutine">Coroutines</a>,
<a href="https://en.wikipedia.org/wiki/Continuation-passing_style">Continuations</a>, and
that hot new mechanism all the cool languages are implementing these days,
<a href="https://en.wikipedia.org/wiki/Await">Async/Await</a>.</p>

<p>But that&rsquo;s all for later.  First is to get this to work.  In closing, I leave
you with these wise words.</p>

<blockquote><p>ph&#8217;nglui mglw&#8217;nafh Cthulhu R&#8217;lyeh wgah&#8217;nagl fhtagn.</p></blockquote>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[If You Use Unsafe, You Should Be Using Compiletest]]></title>
    <link href="http://erickt.github.io/blog/2015/09/22/if-you-use-unsafe/"/>
    <updated>2015-09-22T10:58:25-07:00</updated>
    <id>http://erickt.github.io/blog/2015/09/22/if-you-use-unsafe</id>
    <content type="html"><![CDATA[<p>One of the coolest things about the Rust typesystem is that you can use it to
make unsafe bindings safe. Read all about it in the
<a href="https://doc.rust-lang.org/nightly/nomicon/">Rustonomicon</a>. However, it can be
really quite easy to slip in a bug where you&rsquo;re not actually making the
guarantees you think you&rsquo;re making. For example, here&rsquo;s a real bug I made in
the <a href="https://github.com/erickt/rust-zmq">ZeroMQ FFI bindings</a> (which have been
edited for clarity):</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">struct</span> <span class="n">Socket</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">sock</span><span class="o">:</span> <span class="o">*</span><span class="k">mut</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_void</span><span class="p">,</span>
</span><span class='line'>    <span class="n">closed</span><span class="o">:</span> <span class="kt">bool</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span> <span class="n">Socket</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">pub</span> <span class="k">fn</span> <span class="n">as_poll_item</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span> <span class="n">events</span><span class="o">:</span> <span class="kt">i16</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">PollItem</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span> <span class="c1">// &lt;- BUG!!!</span>
</span><span class='line'>        <span class="n">PollItem</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">socket</span><span class="o">:</span> <span class="bp">self</span><span class="p">.</span><span class="n">sock</span><span class="p">,</span>
</span><span class='line'>            <span class="n">fd</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
</span><span class='line'>            <span class="n">events</span><span class="o">:</span> <span class="n">events</span><span class="p">,</span>
</span><span class='line'>            <span class="n">revents</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
</span><span class='line'>            <span class="n">marker</span><span class="o">:</span> <span class="n">PhantomData</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span> <span class="nb">Drop</span> <span class="k">for</span> <span class="n">Socket</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="nb">drop</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">zmq_sys</span><span class="o">::</span><span class="n">zmq_close</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">sock</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">pub</span> <span class="k">struct</span> <span class="n">PollItem</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">socket</span><span class="o">:</span> <span class="o">*</span><span class="k">mut</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_void</span><span class="p">,</span>
</span><span class='line'>    <span class="n">fd</span><span class="o">:</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span><span class="p">,</span>
</span><span class='line'>    <span class="n">events</span><span class="o">:</span> <span class="kt">i16</span><span class="p">,</span>
</span><span class='line'>    <span class="n">revents</span><span class="o">:</span> <span class="kt">i16</span><span class="p">,</span>
</span><span class='line'>    <span class="n">marker</span><span class="o">:</span> <span class="n">PhantomData</span><span class="o">&lt;&amp;</span><span class="n">&#39;a</span> <span class="n">Socket</span><span class="o">&gt;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">pub</span> <span class="k">fn</span> <span class="n">poll</span><span class="p">(</span><span class="n">items</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="p">[</span><span class="n">PollItem</span><span class="p">],</span> <span class="n">timeout</span><span class="o">:</span> <span class="kt">i64</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="kt">i32</span><span class="p">,</span> <span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">zmq_sys</span><span class="o">::</span><span class="n">zmq_poll</span><span class="p">(</span>
</span><span class='line'>            <span class="n">items</span><span class="p">.</span><span class="n">as_mut_ptr</span><span class="p">()</span> <span class="k">as</span> <span class="o">*</span><span class="k">mut</span> <span class="n">zmq_sys</span><span class="o">::</span><span class="n">zmq_pollitem_t</span><span class="p">,</span>
</span><span class='line'>            <span class="n">items</span><span class="p">.</span><span class="n">len</span><span class="p">()</span> <span class="k">as</span> <span class="n">c_int</span><span class="p">,</span>
</span><span class='line'>            <span class="n">timeout</span> <span class="k">as</span> <span class="n">c_long</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="n">rc</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="k">i32</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Err</span><span class="p">(</span><span class="n">errno_to_error</span><span class="p">())</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Ok</span><span class="p">(</span><span class="n">rc</span> <span class="k">as</span> <span class="kt">i32</span><span class="p">)</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Here&rsquo;s the bug if you missed my callout:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">fn</span> <span class="n">as_poll_item</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span> <span class="n">events</span><span class="o">:</span> <span class="kt">i16</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">PollItem</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span> <span class="c1">// &lt;- BUG!!!</span>
</span></code></pre></td></tr></table></div></figure>


<p>My intention was to tie the lifetime of <code>PollItem&lt;'a&gt;</code> to the lifetime of the
<code>Socket</code>, but because I left out one measly <code>'a</code>, Rust doesn&rsquo;t tie the two
together, and instead is actually using the <code>'static</code> lifetime. This then lets
you do something evil like:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="c1">// leak the pointer!</span>
</span><span class='line'><span class="kd">let</span> <span class="n">poll_item</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'>      <span class="kd">let</span> <span class="n">context</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">::</span><span class="n">Context</span><span class="o">::</span><span class="n">new</span><span class="p">();</span>
</span><span class='line'>      <span class="kd">let</span> <span class="n">socket</span> <span class="o">=</span> <span class="n">context</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">zmq</span><span class="o">::</span><span class="n">PAIR</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>      <span class="n">socket</span><span class="p">.</span><span class="n">as_poll_item</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</span><span class='line'><span class="p">};</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// And use the now uninitialized pointer! Wee! Party like it&#39;s C/C++!</span>
</span><span class='line'><span class="n">poll</span><span class="p">(</span><span class="o">&amp;</span><span class="p">[</span><span class="n">poll_item</span><span class="p">],</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span></code></pre></td></tr></table></div></figure>


<p>It&rsquo;s just that easy. Fix is simple, just change the function to use <code>&amp;'a self</code>
and Rust will refuse to compile this snippet. Job well done!</p>

<p>Well, no, not really. Because what was particularly devious about this bug is
that it actually came back. Later on I accidentally reverted <code>&amp;'a self</code> back to
<code>&amp;self</code> because I secretly hate myself. The project and examples still compiled
and ran, but that unitialized dereference was just waiting around to cause a
security vulnerability.</p>

<p>Oops.</p>

<p>Crap.</p>

<p>Making sure Rust actually rejects programs that it ought to be rejecting
<strong>fundamentally important</strong> when writing a library that uses Unsafe Rust.</p>

<p>That&rsquo;s where <a href="https://github.com/laumann/compiletest-rs">compiletest</a> comes in.
It&rsquo;s a testing framework that&rsquo;s been extacted from
<a href="https://github.com/rust-lang/rust">rust-lang/rust</a>
that lets you write these &ldquo;shouldn&rsquo;t-compile&rdquo; tests. Here&rsquo;s how to use it.
First add this to your <code>Cargo.toml</code>. We do a little feature dance because
currently <code>compiletest</code> only runs on nightly:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='toml'><span class='line'><span class="p">...</span>
</span><span class='line'><span class="p">[</span><span class="n">features</span><span class="p">]</span>
</span><span class='line'><span class="n">unstable</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;compiletest_rs&quot;</span><span class="p">]</span>
</span><span class='line'><span class="p">...</span>
</span><span class='line'>
</span><span class='line'><span class="p">[</span><span class="n">dependencies</span><span class="p">]</span>
</span><span class='line'><span class="n">compiletest_rs</span> <span class="o">=</span> <span class="p">{</span> <span class="s">&quot;version = &quot;</span><span class="err">*&quot;</span><span class="p">,</span> <span class="n">optional</span> <span class="o">=</span> <span class="n">true</span> <span class="p">}</span>
</span><span class='line'><span class="p">...</span>
</span></code></pre></td></tr></table></div></figure>


<p>Then, add add a test driver <code>tests/compile-tests.rs</code> (or whatever you want to
name it) that runs the compiletest tests:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">cfg</span><span class="p">(</span><span class="n">feature</span> <span class="o">=</span> <span class="s">&quot;unstable&quot;</span><span class="p">)]</span>
</span><span class='line'>
</span><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">compiletest_rs</span> <span class="k">as</span> <span class="n">compiletest</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">path</span><span class="o">::</span><span class="n">PathBuf</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">env</span><span class="o">::</span><span class="n">var</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">run_mode</span><span class="p">(</span><span class="n">mode</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;static</span> <span class="kt">str</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">config</span> <span class="o">=</span> <span class="n">compiletest</span><span class="o">::</span><span class="n">default_config</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="n">cfg_mode</span> <span class="o">=</span> <span class="n">mode</span><span class="p">.</span><span class="n">parse</span><span class="p">().</span><span class="n">ok</span><span class="p">().</span><span class="n">expect</span><span class="p">(</span><span class="s">&quot;Invalid mode&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">config</span><span class="p">.</span><span class="n">target_rustcflags</span> <span class="o">=</span> <span class="nb">Some</span><span class="p">(</span><span class="s">&quot;-L target/debug/ -L target/debug/deps/&quot;</span><span class="p">.</span><span class="n">to_owned</span><span class="p">());</span>
</span><span class='line'>    <span class="k">if</span> <span class="kd">let</span> <span class="nb">Ok</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="o">=</span> <span class="n">var</span><span class="o">::&lt;&amp;</span><span class="kt">str</span><span class="o">&gt;</span><span class="p">(</span><span class="s">&quot;TESTNAME&quot;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">s</span> <span class="o">:</span> <span class="n">String</span> <span class="o">=</span> <span class="n">name</span><span class="p">.</span><span class="n">to_owned</span><span class="p">();</span>
</span><span class='line'>        <span class="n">config</span><span class="p">.</span><span class="n">filter</span> <span class="o">=</span> <span class="nb">Some</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="n">config</span><span class="p">.</span><span class="n">mode</span> <span class="o">=</span> <span class="n">cfg_mode</span><span class="p">;</span>
</span><span class='line'>    <span class="n">config</span><span class="p">.</span><span class="n">src_base</span> <span class="o">=</span> <span class="n">PathBuf</span><span class="o">::</span><span class="n">from</span><span class="p">(</span><span class="n">format</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;tests/{}&quot;</span><span class="p">,</span> <span class="n">mode</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">compiletest</span><span class="o">::</span><span class="n">run_tests</span><span class="p">(</span><span class="o">&amp;</span><span class="n">config</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[test]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">compile_test</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">run_mode</span><span class="p">(</span><span class="s">&quot;compile-fail&quot;</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Finally, add the test! Here&rsquo;s the one I wrote, <code>tests/compile-fail/no-leaking-poll-items.rs</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">zmq</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">context</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">::</span><span class="n">Context</span><span class="o">::</span><span class="n">new</span><span class="p">();</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">_poll_item</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">socket</span> <span class="o">=</span> <span class="n">context</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">zmq</span><span class="o">::</span><span class="n">PAIR</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>        <span class="n">socket</span><span class="p">.</span><span class="n">as_poll_item</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="c1">//~ ERROR error: `socket` does not live long enough</span>
</span><span class='line'>    <span class="p">};</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now you can live in peace with the confidence that this bug won&rsquo;t ever appear again:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="o">%</span> <span class="n">multirust</span> <span class="n">run</span> <span class="n">nightly</span> <span class="n">cargo</span> <span class="n">test</span> <span class="o">--</span><span class="n">features</span> <span class="n">unstable</span>
</span><span class='line'>     <span class="n">Running</span> <span class="n">target</span><span class="o">/</span><span class="n">debug</span><span class="o">/</span><span class="n">compile_tests</span><span class="o">-</span><span class="mi">335</span><span class="n">c5f56b353961f</span>
</span><span class='line'>
</span><span class='line'><span class="n">running</span> <span class="mi">1</span> <span class="n">test</span>
</span><span class='line'>
</span><span class='line'><span class="n">running</span> <span class="mi">1</span> <span class="n">test</span>
</span><span class='line'><span class="n">test</span> <span class="p">[</span><span class="n">compile</span><span class="o">-</span><span class="n">fail</span><span class="p">]</span> <span class="n">compile</span><span class="o">-</span><span class="n">fail</span><span class="o">/</span><span class="n">no</span><span class="o">-</span><span class="n">leaking</span><span class="o">-</span><span class="n">poll</span><span class="o">-</span><span class="n">items</span><span class="p">.</span><span class="n">rs</span> <span class="p">...</span> <span class="n">ok</span>
</span><span class='line'>
</span><span class='line'><span class="n">test</span> <span class="n">result</span><span class="o">:</span> <span class="n">ok</span><span class="p">.</span> <span class="mi">1</span> <span class="n">passed</span><span class="p">;</span> <span class="mi">0</span> <span class="n">failed</span><span class="p">;</span> <span class="mi">0</span> <span class="n">ignored</span><span class="p">;</span> <span class="mi">0</span> <span class="n">measured</span>
</span><span class='line'>
</span><span class='line'><span class="n">test</span> <span class="n">compile_test</span> <span class="p">...</span> <span class="n">ok</span>
</span></code></pre></td></tr></table></div></figure>


<p>In summary, use <code>compiletest</code>, and demand it&rsquo;s use from the Unsafe Rust
libraries you use! Otherwise you can never be sure if unsafe and undefined
behavior like this will sneak into your project.</p>

<p>TLDR:</p>

<p><img class="center" src="http://erickt.github.io/images/compiletest-badtime.jpg" title="Bad Time" ></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Serde 0.5.0 - Many Many Changes]]></title>
    <link href="http://erickt.github.io/blog/2015/08/07/serde-0-dot-5-0-many-many-changes/"/>
    <updated>2015-08-07T08:14:22-07:00</updated>
    <id>http://erickt.github.io/blog/2015/08/07/serde-0-dot-5-0-many-many-changes</id>
    <content type="html"><![CDATA[<p>Hello all you beautiful and talented people! I&rsquo;m pleased to announce
<a href="https://github.com/serde-rs/serde">serde</a> 0.5.0. We&rsquo;re bumping the major
(unstable) version number here because there have been a huge amount of
breaking changes in the API. This has been done to better support serialization
formats like <a href="https://github.com/TyOverby/bincode">bincode</a>, which relies on
the <code>Serialize</code>e to hint to the <code>Serializer</code> how to parse the next bytes.
This will enable <a href="https://github.com/servo/servo/pull/6583">Servo</a> to use
bincode for its IPC protocol.</p>

<p>Here are the major changes:</p>

<ul>
<li><code>serde::json</code> was factored out into its own separate crate
<a href="https://crates.io/crates/serde_json">serde_json</a>
  <a href="https://github.com/serde-rs/serde/pull/114">#114</a>.</li>
<li>Added serialization and deserialization type hints.</li>
<li>Renamed many functions to change <code>visit_named_{map,seq}</code> to
  <code>visit_struct</code> and <code>visit_tuple_struct</code>
  <a href="https://github.com/serde-rs/serde/pull/114">#114</a>
<a href="https://github.com/serde-rs/serde/pull/120">#120</a>.</li>
<li>Added hooks to allow serializers to serialize newtype tuple structs without a
wrapper type <a href="https://github.com/serde-rs/serde/pull/121">#121</a>.</li>
<li>Remove <code>_error</code> from <code>de::Error</code>
<a href="https://github.com/serde-rs/serde/pull/129">#129</a>.</li>
<li>Rewrote json parser to not consume the whole stream
<a href="https://github.com/serde-rs/serde/pull/127">#127</a>.</li>
<li>Fixed <code>serde_macros</code> for generating fully generic code
<a href="https://github.com/serde-rs/serde/pull/117">#117</a>.</li>
</ul>


<p>Thank you to everyone that&rsquo;s helped with this release:</p>

<ul>
<li>Craig Brandenburg</li>
<li>Hugo Duncan</li>
<li>Jarred Nicholis</li>
<li>Oliver Schneider</li>
<li>Patrick Walton</li>
<li>Sebastian Thiel</li>
<li>Skylar Lipthay</li>
<li>Thomas Bahn</li>
<li>dswd</li>
</ul>


<h1>Benchmarks</h1>

<p>It&rsquo;s been a bit since we last did some
<a href="https://erickt.github.io/blog/2015/02/16/rewriting-rust-serialization-there-can-be-only-one-serde/">benchmarks</a>,
so here are the latest numbers with these compilers:</p>

<ul>
<li>rustc: 1.4.0-nightly (1181679c8 2015-08-07)</li>
<li>go: version go1.4.2 darwin/amd64</li>
<li>clang: Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)</li>
</ul>


<p><a href="https://github.com/TyOverby/bincode">bincode</a>&rsquo;s serde support makes its first
appearance, which starts out roughly 1/3 slower at serialization, but about the
same speed at deserialization. I haven&rsquo;t done much optimization, so there&rsquo;s
probably a lot of low hanging fruit.</p>

<p><a href="https://crates.io/crates/serde_json">serde_json</a> saw a good amount of
improvement, mainly from some compiler optimizations in the 1.4 nightly. The
deserializer is slightly slower due to the parser rewrite.</p>

<p><a href="https://github.com/dwrensha/capnproto-rust">capnproto-rust</a>&rsquo;s unpacked format
shows a surprisingly large large serialization improvement, with a 10x
improvement from 4GB/s to 15GB/s. Good job dwrensha!  Deserialization is half
as slow as before though. Perhaps I have a bug in my code?</p>

<p>I&rsquo;ve changed the Rust MessagePack implementation to
<a href="https://github.com/3Hren/msgpack-rust">rmp</a>, which has a wee bit faster
serializer, but deserialization was about the same.</p>

<p>I&rsquo;ve also updated the numbers for Go and C++, but those numbers stayed roughly
the same.</p>

<p>Serialization:</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library             </th>
<th> format                     </th>
<th> serialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>capnproto-rust</strong>  </td>
<td> <strong>Cap&#8217;n Proto (unpacked)</strong> </td>
<td> <del>4349</del> <strong>15448</strong>   </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto        </td>
<td> Cap&#8217;n Proto                </td>
<td> 3877                 </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>bincode</strong>         </td>
<td> <strong>Raw</strong>                    </td>
<td> <del>1020</del> <strong>3278</strong>    </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>bincode (serde)</strong> </td>
<td> <strong>Raw</strong>                    </td>
<td> <strong>2143</strong>             </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>capnproto-rust</strong>  </td>
<td> <strong>Cap&#8217;n Proto (packed)</strong>   </td>
<td> <del>583</del> <strong>656</strong>      </td>
</tr>
<tr>
<td> Go       </td>
<td> gogoprotobuf        </td>
<td> Protocol Buffers           </td>
<td> <del>596</del> 627          </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>rmp</strong>             </td>
<td> <strong>MessagePack</strong>            </td>
<td> <del>397</del> <strong>427</strong>      </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>rust-protobuf</strong>   </td>
<td> <strong>Protocol Buffers</strong>       </td>
<td> <del>357</del> <strong>373</strong>      </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>serde::json</strong>     </td>
<td> <strong>JSON</strong>                   </td>
<td> <del>288</del> <strong>337</strong>      </td>
</tr>
<tr>
<td> C++      </td>
<td> rapidjson           </td>
<td> JSON                       </td>
<td> 307                  </td>
</tr>
<tr>
<td> Go       </td>
<td> goprotobuf          </td>
<td> Protocol Buffers           </td>
<td> <del>214</del> 226          </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>serialize::json</strong> </td>
<td> <strong>JSON</strong>                   </td>
<td> <del>147</del> <strong>212</strong>      </td>
</tr>
<tr>
<td> Go       </td>
<td> ffjson              </td>
<td> JSON                       </td>
<td> 147                  </td>
</tr>
<tr>
<td> Go       </td>
<td> encoding/json       </td>
<td> JSON                       </td>
<td> 85                   </td>
</tr>
</tbody>
</table>


<p>Deserialization:</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library             </th>
<th> format                     </th>
<th> deserialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>capnproto-rust</strong>  </td>
<td> <strong>Cap&#8217;n Proto (unpacked)</strong> </td>
<td> <del>2185</del> <strong>1306</strong>      </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto        </td>
<td> Cap&#8217;n Proto (zero copy)    </td>
<td> 1407                   </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto        </td>
<td> Cap&#8217;n Proto                </td>
<td> 711                    </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>capnproto-rust</strong>  </td>
<td> <strong>Cap&#8217;n Proto (packed)</strong>   </td>
<td> <del>351</del> <strong>464</strong>        </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>bincode (serde)</strong> </td>
<td> <strong>Raw</strong>                    </td>
<td> <strong>310</strong>                </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>bincode</strong>         </td>
<td> <strong>Raw</strong>                    </td>
<td> <del>142</del> <strong>291</strong>        </td>
</tr>
<tr>
<td> Go       </td>
<td> gogoprotobuf        </td>
<td> Protocol Buffers           </td>
<td> 270                    </td>
</tr>
<tr>
<td> C++      </td>
<td> rapidjson           </td>
<td> JSON (sax)                 </td>
<td> 182                    </td>
</tr>
<tr>
<td> C++      </td>
<td> rapidjson           </td>
<td> JSON (dom)                 </td>
<td> 155                    </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>rust-protobuf</strong>   </td>
<td> <strong>Protocol Buffers</strong>       </td>
<td> <strong>143</strong>                </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>rmp</strong>             </td>
<td> <strong>MessagePack</strong>            </td>
<td> <del>138</del> <strong>128</strong>        </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>serde::json</strong>     </td>
<td> <strong>JSON</strong>                   </td>
<td> <del>140</del> <strong>122</strong>        </td>
</tr>
<tr>
<td> Go       </td>
<td> ffjson              </td>
<td> JSON                       </td>
<td> 95                     </td>
</tr>
<tr>
<td> Go       </td>
<td> goprotobuf          </td>
<td> Protocol Buffers           </td>
<td> 81                     </td>
</tr>
<tr>
<td> Go       </td>
<td> encoding/json       </td>
<td> JSON                       </td>
<td> 23                     </td>
</tr>
<tr>
<td> Rust     </td>
<td> serialize::json     </td>
<td> JSON                       </td>
<td> 23                     </td>
</tr>
</tbody>
</table>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Serde 0.4.0 - Syntax Extensions in Stable Rust and More!]]></title>
    <link href="http://erickt.github.io/blog/2015/05/18/serde-0-dot-4-0-now-supports-macros-in-stable-rust/"/>
    <updated>2015-05-18T07:57:19-07:00</updated>
    <id>http://erickt.github.io/blog/2015/05/18/serde-0-dot-4-0-now-supports-macros-in-stable-rust</id>
    <content type="html"><![CDATA[<p>Hello Internet! I&rsquo;m pleased to announce
<a href="https://github.com/serde-rs/serde">serde</a> 0.4.0, which now supports many new
features with help from our growing serde community. The largest is now serde
supports syntax extensions in stable Rust by way of
<a href="https://github.com/erickt/rust-syntex">syntex</a>. syntex is a fork of Rust&rsquo;s
parser library libsyntax that has been modified to enable code generation.
serde uses it along with a
<a href="http://doc.crates.io/build-script.html">Cargo build script</a> to expand the
<code>#[derive(Serialize, Deserialize)]</code> decorator annotations. Here&rsquo;s how to use
it.</p>

<p>First, lets start with a simple serde 0.3.x project that&rsquo;s forced to use
nightly because it uses <code>serde_macros</code>. The <code>Cargo.toml</code> is:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='toml'><span class='line'><span class="p">[</span><span class="n">package</span><span class="p">]</span>
</span><span class='line'><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;hello_world&quot;</span>
</span><span class='line'><span class="n">versio</span> <span class="o">=</span> <span class="s">&quot;0.1.0&quot;</span>
</span><span class='line'><span class="n">authors</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;Erick Tryzelaar &lt;erick.tryzelaar@gmail.com&gt;&quot;</span><span class="p">]</span>
</span><span class='line'><span class="n">license</span> <span class="o">=</span> <span class="s">&quot;MIT/Apache-2.0&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="p">[</span><span class="n">dependencies</span><span class="p">]</span>
</span><span class='line'><span class="n">serde</span> <span class="o">=</span> <span class="s">&quot;*&quot;</span>
</span><span class='line'><span class="n">serde_macros</span> <span class="o">=</span> <span class="s">&quot;*&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>And the actual library is <code>src/lib.rs</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">feature</span><span class="p">(</span><span class="n">custom_derive</span><span class="p">,</span> <span class="n">plugin</span><span class="p">)]</span>
</span><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">plugin</span><span class="p">(</span><span class="n">serde_macros</span><span class="p">)]</span>
</span><span class='line'>
</span><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">serde</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[derive(Serialize, Deserialize)]</span>
</span><span class='line'><span class="k">pub</span> <span class="k">struct</span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">x</span><span class="o">:</span> <span class="kt">u32</span><span class="p">,</span>
</span><span class='line'>    <span class="n">y</span><span class="o">:</span> <span class="kt">u32</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>In order to use Stable Rust, we can use the new <code>serde_codegen</code>. Our strategy
is to split our input into two files. The first is the entry point Cargo will
use to compile the library, <code>src/lib.rs</code>. The second is a template that
contains the macros, <code>src/lib.rs.in</code>. It will be expanded into
<code>$OUT_DIR/lib.rs</code>, which is included in <code>src/lib.rs</code>. So <code>src/lib.rs</code> looks
like:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">serde</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="n">include</span><span class="o">!</span><span class="p">(</span><span class="n">concat</span><span class="o">!</span><span class="p">(</span><span class="n">env</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;OUT_DIR&quot;</span><span class="p">),</span> <span class="s">&quot;/lib.rs&quot;</span><span class="p">));</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>src/lib.rs.in</code> then just looks like:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[derive(Serialize, Deserialize)]</span>
</span><span class='line'><span class="k">pub</span> <span class="k">struct</span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">x</span><span class="o">:</span> <span class="kt">u32</span><span class="p">,</span>
</span><span class='line'>    <span class="n">y</span><span class="o">:</span> <span class="kt">u32</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>In order to generate the <code>$OUT_DIR/lib.rs</code>, we&rsquo;ll use a Cargo build script.
We&rsquo;ll configure <code>Cargo.toml</code> with:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='toml'><span class='line'><span class="p">[</span><span class="n">package</span><span class="p">]</span>
</span><span class='line'><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;hello_world&quot;</span>
</span><span class='line'><span class="n">versio</span> <span class="o">=</span> <span class="s">&quot;0.1.0&quot;</span>
</span><span class='line'><span class="n">authors</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;Erick Tryzelaar &lt;erick.tryzelaar@gmail.com&gt;&quot;</span><span class="p">]</span>
</span><span class='line'><span class="n">license</span> <span class="o">=</span> <span class="s">&quot;MIT/Apache-2.0&quot;</span>
</span><span class='line'><span class="n">build</span> <span class="o">=</span> <span class="s">&quot;build.rs&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="p">[</span><span class="n">build-dependencies</span><span class="p">]</span>
</span><span class='line'><span class="n">syntex</span> <span class="o">=</span> <span class="s">&quot;*&quot;</span>
</span><span class='line'><span class="n">serde_codegen</span> <span class="o">=</span> <span class="s">&quot;*&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="p">[</span><span class="n">dependencies</span><span class="p">]</span>
</span><span class='line'><span class="n">serde</span> <span class="o">=</span> <span class="s">&quot;*&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Finally, the <code>build.rs</code> script itself uses <code>syntex</code> to expand the syntax
extensions:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">syntex</span><span class="p">;</span>
</span><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">serde_codegen</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">env</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">path</span><span class="o">::</span><span class="nb">Path</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">out_dir</span> <span class="o">=</span> <span class="n">env</span><span class="o">::</span><span class="n">var_os</span><span class="p">(</span><span class="s">&quot;OUT_DIR&quot;</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="n">src</span> <span class="o">=</span> <span class="nb">Path</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="s">&quot;src/lib.rs.in&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">dst</span> <span class="o">=</span> <span class="nb">Path</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="o">&amp;</span><span class="n">out_dir</span><span class="p">).</span><span class="n">join</span><span class="p">(</span><span class="s">&quot;lib.rs&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">registry</span> <span class="o">=</span> <span class="n">syntex</span><span class="o">::</span><span class="n">Registry</span><span class="o">::</span><span class="n">new</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">serde_codegen</span><span class="o">::</span><span class="n">register</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="n">registry</span><span class="p">);</span>
</span><span class='line'>    <span class="n">registry</span><span class="p">.</span><span class="n">expand</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">src</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">dst</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Downside 1: Error Locations</h2>

<p>While <code>syntex</code> is quite powerful, there are a few major downsides. Rust does
not yet support the ability for a generated file to provide error location
information from a template file. This means that tracking down errors requires
manually looking at the generated code and trying to identify where the error
in the template. However, there is a workaround.  It&rsquo;s actually not that
difficult to support <code>syntex</code> and the Rust Nightly compiler plugins. To update
our example, we&rsquo;ll change the <code>Cargo.toml</code> to:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='toml'><span class='line'><span class="p">[</span><span class="n">package</span><span class="p">]</span>
</span><span class='line'><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;hello_world&quot;</span>
</span><span class='line'><span class="n">versio</span> <span class="o">=</span> <span class="s">&quot;0.1.0&quot;</span>
</span><span class='line'><span class="n">authors</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;Erick Tryzelaar &lt;erick.tryzelaar@gmail.com&gt;&quot;</span><span class="p">]</span>
</span><span class='line'><span class="n">license</span> <span class="o">=</span> <span class="s">&quot;MIT/Apache-2.0&quot;</span>
</span><span class='line'><span class="n">build</span> <span class="o">=</span> <span class="s">&quot;build.rs&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="p">[</span><span class="n">features</span><span class="p">]</span>
</span><span class='line'><span class="n">default</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;with_syntex&quot;</span><span class="p">]</span>
</span><span class='line'><span class="n">nightly</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;serde_macros&quot;</span><span class="p">]</span>
</span><span class='line'><span class="n">with_syntex</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;serde&quot;</span><span class="p">,</span> <span class="s">&quot;serde_codegen&quot;</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="p">[</span><span class="n">build-dependencies</span><span class="p">]</span>
</span><span class='line'><span class="n">syntex</span> <span class="o">=</span> <span class="p">{</span> <span class="n">version</span> <span class="o">=</span> <span class="s">&quot;*&quot;</span><span class="p">,</span> <span class="n">optional</span> <span class="o">=</span> <span class="n">true</span> <span class="p">}</span>
</span><span class='line'><span class="n">serde_codegen</span> <span class="o">=</span> <span class="p">{</span> <span class="n">version</span> <span class="o">=</span> <span class="s">&quot;*&quot;</span><span class="p">,</span> <span class="n">optional</span> <span class="o">=</span> <span class="n">true</span> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="p">[</span><span class="n">dependencies</span><span class="p">]</span>
</span><span class='line'><span class="n">serde</span> <span class="o">=</span> <span class="s">&quot;*&quot;</span>
</span><span class='line'><span class="n">serde_macros</span> <span class="o">=</span> <span class="p">{</span> <span class="n">version</span> <span class="o">=</span> <span class="s">&quot;*&quot;</span><span class="p">,</span> <span class="n">optional</span> <span class="o">=</span> <span class="n">true</span> <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Then the <code>build.rs</code> is changed to optionally expand the macros in our template:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[cfg(feature = </span><span class="s">&quot;with_syntex&quot;</span><span class="cp">)]</span>
</span><span class='line'><span class="kn">mod</span> <span class="n">inner</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">extern</span> <span class="n">crate</span> <span class="n">syntex</span><span class="p">;</span>
</span><span class='line'>    <span class="k">extern</span> <span class="n">crate</span> <span class="n">serde_codegen</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">env</span><span class="p">;</span>
</span><span class='line'>    <span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">path</span><span class="o">::</span><span class="nb">Path</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">pub</span> <span class="k">fn</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">out_dir</span> <span class="o">=</span> <span class="n">env</span><span class="o">::</span><span class="n">var_os</span><span class="p">(</span><span class="s">&quot;OUT_DIR&quot;</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="n">src</span> <span class="o">=</span> <span class="nb">Path</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="s">&quot;src/lib.rs.in&quot;</span><span class="p">);</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">dst</span> <span class="o">=</span> <span class="nb">Path</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="o">&amp;</span><span class="n">out_dir</span><span class="p">).</span><span class="n">join</span><span class="p">(</span><span class="s">&quot;lib.rs&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="k">mut</span> <span class="n">registry</span> <span class="o">=</span> <span class="n">syntex</span><span class="o">::</span><span class="n">Registry</span><span class="o">::</span><span class="n">new</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="n">serde_codegen</span><span class="o">::</span><span class="n">register</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="n">registry</span><span class="p">);</span>
</span><span class='line'>        <span class="n">registry</span><span class="p">.</span><span class="n">expand</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">src</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">dst</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[cfg(not(feature = </span><span class="s">&quot;with_syntex&quot;</span><span class="cp">))]</span>
</span><span class='line'><span class="kn">mod</span> <span class="n">inner</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">pub</span> <span class="k">fn</span> <span class="n">main</span><span class="p">()</span> <span class="p">{}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">pub</span> <span class="k">fn</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">inner</span><span class="o">::</span><span class="n">main</span><span class="p">()</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Finally, <code>src/lib.rs</code> is updated to:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">cfg_attr</span><span class="p">(</span><span class="n">feature</span> <span class="o">=</span> <span class="s">&quot;nightly&quot;</span><span class="p">,</span> <span class="n">feature</span><span class="p">(</span><span class="n">plugin</span><span class="p">))]</span>
</span><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">cfg_attr</span><span class="p">(</span><span class="n">feature</span> <span class="o">=</span> <span class="s">&quot;nightly&quot;</span><span class="p">,</span> <span class="n">plugin</span><span class="p">(</span><span class="n">serde_macros</span><span class="p">))]</span>
</span><span class='line'>
</span><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">serde</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[cfg(feature = </span><span class="s">&quot;nightly&quot;</span><span class="cp">)]</span>
</span><span class='line'><span class="n">include</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;lib.rs.in&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[cfg(feature = </span><span class="s">&quot;with_syntex&quot;</span><span class="cp">)]</span>
</span><span class='line'><span class="n">include</span><span class="o">!</span><span class="p">(</span><span class="n">concat</span><span class="o">!</span><span class="p">(</span><span class="n">env</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;OUT_DIR&quot;</span><span class="p">),</span> <span class="s">&quot;/lib.rs&quot;</span><span class="p">));</span>
</span></code></pre></td></tr></table></div></figure>


<p>Then most development can happen with using the Nightly Rust and
<code>cargo build --no-default-features --features nightly</code> for better error
messages, but downstream consumers can use Stable Rust without worry.</p>

<h2>Downside 2: Macros in Macros</h2>

<p>Syntex can only expand macros inside macros it knows about, and it doesn&rsquo;t know
about the builtin macros. This is because a lot of the stable macros are using
unstable features under the covers. So unfortunately if you&rsquo;re using a library
like the quasiquoting library <a href="https://github.com/erickt/rust-quasi">quasi</a>,
you cannot write:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="kd">let</span> <span class="n">exprs</span> <span class="o">=</span> <span class="n">vec</span><span class="o">!</span><span class="p">[</span><span class="n">quote_expr</span><span class="o">!</span><span class="p">(</span><span class="n">cx</span><span class="p">,</span> <span class="mi">1</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)];</span>
</span></code></pre></td></tr></table></div></figure>


<p>Instead you have to pull out the syntex macros into a separate variable:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="kd">let</span> <span class="n">expr</span> <span class="o">=</span> <span class="n">quote_expr</span><span class="o">!</span><span class="p">(</span><span class="n">cx</span><span class="p">,</span> <span class="mi">1</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span><span class='line'><span class="kd">let</span> <span class="n">exprs</span> <span class="o">=</span> <span class="n">vec</span><span class="o">!</span><span class="p">[</span><span class="n">expr</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Downside 3: Compile Times</h2>

<p>Syntex can take a while to compile. It may be possible to optimize this, but
that may be difficult while keeping compatibility with <code>libsyntax</code>.</p>

<hr />

<p>That&rsquo;s <code>v0.4.0</code>. I hope you enjoy it! Please let me know if you run into any
<a href="https://github.com/serde-rs/serde/issues">problems</a>.</p>

<h2>Release Notes</h2>

<p>Here are other things that came with this version:</p>

<ul>
<li>Added field annotation to enable renaming fields for different backends
<a href="https://github.com/serde-rs/serde/pull/69">#69</a>. For example:</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">struct</span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'>  <span class="cp">#[serde(rename=</span><span class="s">&quot;X&quot;</span><span class="cp">)]</span>
</span><span class='line'>  <span class="n">x</span><span class="o">:</span> <span class="kt">u32</span><span class="p">,</span>
</span><span class='line'>
</span><span class='line'>  <span class="cp">#[serde(rename(json=</span><span class="s">&quot;the-x&quot;</span><span class="cp">, xml=</span><span class="s">&quot;X&quot;</span><span class="cp">)]</span>
</span><span class='line'>  <span class="n">y</span><span class="o">:</span> <span class="kt">u32</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>Faster JSON string parsing <a href="https://github.com/serde-rs/serde/pull/71">#71</a>.</li>
<li>Add a <code>LineColIterator</code> that tracks line and column information for
  deserializers <a href="https://github.com/serde-rs/serde/pull/58">#58</a>.</li>
<li>Improved bytestring support <a href="https://github.com/serde-rs/serde/pull/72">#72</a></li>
<li>Changed <code>de::PrimitiveVisitor</code> to also depend on <code>FromStr</code>
<a href="https://github.com/serde-rs/serde/pull/70">#70</a></li>
<li>Added impls for fixed sized arrays with 1 to 32 elements
<a href="https://github.com/serde-rs/serde/pull/74">#74</a></li>
<li>Added <code>json::Value::lookup</code>, that allows values to be extracted with
<code>value.lookup("foo.bar.baz")</code> <a href="https://github.com/serde-rs/serde/pull/76">#76</a></li>
</ul>


<p>Bug Fixes:</p>

<ul>
<li>Make sure that -0.0 gets serialized as &ldquo;-0.0&rdquo;
<a href="https://github.com/serde-rs/serde/commit/f0c87fb">f0c87fb</a>.</li>
<li>Missing field errors displayed original field name instead of renamed
<a href="https://github.com/serde-rs/serde/pull/64">#64</a>.</li>
<li>Fixed handling json integer overflow</li>
</ul>


<p>A special thanks to everyone that helped with this release:</p>

<ul>
<li>Alex Crichton</li>
<li>Andrew Poelstra</li>
<li>Corey Farwell</li>
<li>Hugo Duncan</li>
<li>Jorge Israel Peña</li>
<li>Kang Seonghoon</li>
<li>Mikhail Borisov</li>
<li>Oliver Schneider</li>
<li>Sebastian Thiel</li>
<li>Steven Fackler</li>
<li>Thomas Bahn</li>
<li>derhaskell</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Serde 0.3.1 - Now Compatible With Beta! Plus Aster and Quasi Updates]]></title>
    <link href="http://erickt.github.io/blog/2015/04/12/serde-0-dot-3-1-now-compatible-with-beta/"/>
    <updated>2015-04-12T11:53:43-07:00</updated>
    <id>http://erickt.github.io/blog/2015/04/12/serde-0-dot-3-1-now-compatible-with-beta</id>
    <content type="html"><![CDATA[<p>I just pushed up <a href="https://github.com/erickt/rust-serde">serde</a> 0.3.1 to
<a href="https://crates.io/crates/serde">crates.io</a>, which is now compatible with beta!
serde_macros 0.3.1, however still requires nightly.  But this means that if
you implement the all the traits using stable features, then any users of serde
should work with rust 1.0.</p>

<p>Here&rsquo;s what&rsquo;s also new in serde v0.3.1:</p>

<ul>
<li>Renamed <code>ValueDeserializer::deserializer</code> into <code>ValueDeserializer::into_deserializer</code>.</li>
<li>Renamed the attribute that changes the name a field is serialized
<code>#[serde(alias="...")]</code> to <code>#[serde(rename="...")]</code>.</li>
<li>Added implementations for <code>Box</code>, <code>Rc</code>, and <code>Arc</code>.</li>
<li>Updated <code>VariantVisitor</code> to hint to the deserializer which variant kind it is expecting.
This allows serializers to serialize a unit variant as a string.</li>
<li>Added an <code>Error::unknown_field_error</code> error message.</li>
<li>Progress on the documentation, but there&rsquo;s still plenty more to go.</li>
</ul>


<p>Upstream of serde, I&rsquo;ve been also doing some work on
<a href="https://github.com/erickt/rust-aster">aster</a> and
<a href="https://github.com/erickt/rust-quasi">quasi</a>, which are my helper libraries to
simplify writing syntax extensions.</p>

<p>aster v0.2.0:</p>

<ul>
<li>Added builders for qualified paths, slices, <code>Vec</code>, <code>Box</code>, <code>Rc</code>, and <code>Arc</code>.</li>
<li>Extended item builders to support <code>use</code> simple paths, globs, and lists.</li>
<li>Added a helper for building the <code>#[automatically_derived]</code> annotation.</li>
</ul>


<p>quasi v0.1.9:</p>

<ul>
<li>Backported support for <code>quote_attr!()</code> and <code>quote_matchers!()</code> from <code>libsyntax</code>.</li>
<li>Added support for unquoting arbitrary slices.</li>
</ul>


<p>Thanks for everyone&rsquo;s help with this release!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Serde 0.3]]></title>
    <link href="http://erickt.github.io/blog/2015/03/31/serde-0-dot-3/"/>
    <updated>2015-03-31T19:57:37-07:00</updated>
    <id>http://erickt.github.io/blog/2015/03/31/serde-0-dot-3</id>
    <content type="html"><![CDATA[<p>I&rsquo;m happy to announce that I&rsquo;ve released
<a href="https://github.com/erickt/rust-serde">serde</a> 0.3 on
<a href="https://crates.io/crates/serde">crates.io</a> today.  For those unfamiliar with
serde, it&rsquo;s a generic serialization framework, much like
<a href="https://github.com/rust-lang/rustc-serialize/">rustc-serialize</a>, but much more
powerful. Check out my <a href="http://erickt.github.io/blog/categories/serialization/">serialization series</a>
if you&rsquo;re interested in serde&rsquo;s original development.</p>

<p>There&rsquo;s been a ton of work since 0.2. Here are the highlights:</p>

<ul>
<li><p>Ported over from std::old_io to std::io. There is a bit of a performance hit
when serializing to <code>&amp;mut [u8]</code>, although it&rsquo;s really not that bad. In my goser
benchmarks, previously it ran in 373 MB/s, but now it&rsquo;s running at 260 MB/s.
However, this hasn&rsquo;t impacted the <code>Vec&lt;u8&gt;</code> serialization performance, nor
deserialization performance.</p></li>
<li><p>Much better JSON deserialization errors. Now <code>std::io::Error</code> is properly
propogated, and error locations are reported when a <code>Deserialize</code> raises an error.</p></li>
<li><p>Merged <code>serde::ser::Serializer</code> and <code>serde::ser::Visitor</code>.</p></li>
<li><p>Renamed <code>serde::ser::Serialize::visit</code> to <code>serde::ser::Serialize::serialize</code>.</p></li>
<li><p>Replaced <code>serde::ser::{Seq,Map}Visitor::size_hint</code> with a <code>len()</code> method that
returns an optional length. This has a little stronger emphasis that we either
need an exactly length or no length. Formats that need an exact length should
make sure to verify the length passed in matches the actual amount of values
serialized.</p></li>
<li><p><code>serde::json</code> now deserializes missing values as a <code>()</code>.</p></li>
<li><p>Finished implementing <code>#[derive(Serialize, Deserialize)]</code> for all struct and
enum forms.</p></li>
<li><p>Ported <code>serde_macros</code> over to <a href="https://github.com/erickt/rust-aster">aster</a>
and <a href="https://github.com/erickt/rust-quasi">quasi</a>, which simplies code
generation.</p></li>
<li><p>Removed the unnessary <code>first</code> argument from <code>visit_{seq,map}_elt</code>.</p></li>
<li><p>Rewrote enum deserializations to not require allocations. Oddly enough this
is a tad slower than the allocation form. I suspect it&rsquo;s coming from the
function calls not getting inlined away.</p></li>
<li><p>Allowed enum serialization and deserialization to support more than one
variant.</p></li>
<li><p>Allowed <code>Deserialize</code> types to hint that it&rsquo;s expecting a sequence or a map.</p></li>
<li><p>Allowed maps to be deserialized from a <code>()</code>.</p></li>
<li><p>Added a <code>serde::bytes::{Bytes,ByteBuf}</code>, which wrap <code>&amp;[u8]</code>/<code>Vec&lt;u8&gt;</code> to allow
some formats to encode these values more efficiently than generic sequences.</p></li>
<li><p>Added <code>serde::de::value</code>, which contains some helper deserializers to
deserialize from a Rust type.</p></li>
<li><p>Added impls for most collection types in the standard library.</p></li>
</ul>


<p>Thanks everyone that&rsquo;s helped out with this release!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rewriting Rust Serialization: Part 4: Serde2 Is Ready!]]></title>
    <link href="http://erickt.github.io/blog/2015/02/16/rewriting-rust-serialization-there-can-be-only-one-serde/"/>
    <updated>2015-02-16T07:32:54-08:00</updated>
    <id>http://erickt.github.io/blog/2015/02/16/rewriting-rust-serialization-there-can-be-only-one-serde</id>
    <content type="html"><![CDATA[<p>It&rsquo;s been a while, hasn&rsquo;t it? Here&rsquo;s
<a href="http://erickt.github.io/blog/2014/10/28/serialization/">part 1</a>,
<a href="http://erickt.github.io/blog/2014/11/03/performance/">part 2</a>,
<a href="http://erickt.github.io/blog/2014/11/03/performance/">part 2.1</a>,
<a href="http://erickt.github.io/blog/2014/11/03/performance/">part 2.2</a>,
<a href="http://erickt.github.io/blog/2014/12/13/rewriting-rust-serialization/">part 3</a>, and
<a href="http://erickt.github.io/blog/2014/12/13/performance-digression/">part 3.1</a>
if you want to catch up.</p>

<h2>Serde Version 2</h2>

<p>Well it&rsquo;s a long time coming, but serde2 is finally in a mostly usable
position! If you recall from
<a href="http://erickt.github.io/blog/2014/12/13/rewriting-rust-serialization/">part 3</a>,
one of the problems with serde1 is that we&rsquo;re paying a lot for tagging our
types, and it&rsquo;s really hurting us on the deserialization side of things. So
there&rsquo;s one other pattern that we can use that allows for lookahead that
doesn&rsquo;t need tags: visitors. A year or so ago I rewrote our generic hashing
framework to use the visitor pattern to great success. <code>serde2</code> came out of
experiments to see if I could do the same thing here. It turned out that it was
a really elegant approach.</p>

<h3>Serialize</h3>

<p>It all starts with a type that we want to serialize:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Serialize</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">Visitor</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span> <span class="n">visitor</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">V</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">V</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>(Aside: while I&rsquo;d rather use <code>where</code> here for this type parameter, that would
force me to write <code>&lt;V as Visitor&gt;::Value&gt;</code> due to
<a href="https://github.com/rust-lang/rust/issues/20300">#20300</a>).</p>

<p>This <code>Visitor</code> trait then looks like:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Visitor</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">type</span> <span class="n">Value</span><span class="p">;</span>
</span><span class='line'>    <span class="k">type</span> <span class="n">Error</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_unit</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_named_unit</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">_name</span><span class="o">:</span> <span class="o">&amp;</span><span class="kt">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">visit_unit</span><span class="p">()</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_bool</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">bool</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>So the implementation for a <code>bool</code> then looks like:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span> <span class="n">Serialize</span> <span class="k">for</span> <span class="kt">bool</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">Visitor</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span> <span class="n">visitor</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">V</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">V</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">visitor</span><span class="p">.</span><span class="n">visit_bool</span><span class="p">(</span><span class="o">*</span><span class="bp">self</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Things get more interesting when we get to compound structures like a sequence.
Here&rsquo;s <code>Visitor</code> again. It needs to both be able to visit the overall structure
as well as each item:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="p">...</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">visit_seq</span><span class="o">&lt;</span><span class="n">V</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">visitor</span><span class="o">:</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="n">where</span> <span class="n">V</span><span class="o">:</span> <span class="n">SeqVisitor</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">visit_seq_elt</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span>
</span><span class='line'>                    <span class="n">first</span><span class="o">:</span> <span class="kt">bool</span><span class="p">,</span>
</span><span class='line'>                    <span class="n">value</span><span class="o">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="n">where</span> <span class="n">T</span><span class="o">:</span> <span class="n">Serialize</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="p">...</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>We also have this <code>SeqVisitor</code> trait that the type to serialize provides. It
really just looks like an <code>Iterator</code>, but the type parameter has been moved to
the <code>visit</code> method so that it can return different types:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">SeqVisitor</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">Visitor</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">visitor</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="nb">Option</span><span class="o">&lt;</span><span class="n">V</span><span class="o">::</span><span class="n">Value</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">V</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">size_hint</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">usize</span><span class="p">,</span> <span class="nb">Option</span><span class="o">&lt;</span><span class="n">usize</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">None</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Finally, to implement this for a type like <code>&amp;[T]</code> we create an
<code>Iterator</code>-to-<code>SeqVisitor</code> adaptor and pass it to the visitor, which then in
turn visits each item:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">struct</span> <span class="n">SeqIteratorVisitor</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">iter</span><span class="o">:</span> <span class="n">Iter</span><span class="p">,</span>
</span><span class='line'>    <span class="n">first</span><span class="o">:</span> <span class="kt">bool</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">Iter</span><span class="o">:</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Item</span><span class="o">=</span><span class="n">T</span><span class="o">&gt;&gt;</span> <span class="n">SeqIteratorVisitor</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">pub</span> <span class="k">fn</span> <span class="n">new</span><span class="p">(</span><span class="n">iter</span><span class="o">:</span> <span class="n">Iter</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">SeqIteratorVisitor</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">SeqIteratorVisitor</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">iter</span><span class="o">:</span> <span class="n">iter</span><span class="p">,</span>
</span><span class='line'>            <span class="n">first</span><span class="o">:</span> <span class="k">true</span><span class="p">,</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span>
</span><span class='line'>    <span class="n">T</span><span class="o">:</span> <span class="n">Serialize</span><span class="p">,</span>
</span><span class='line'>    <span class="n">Iter</span><span class="o">:</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Item</span><span class="o">=</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'><span class="o">&gt;</span> <span class="n">SeqVisitor</span> <span class="k">for</span> <span class="n">SeqIteratorVisitor</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">Visitor</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">visitor</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="nb">Option</span><span class="o">&lt;</span><span class="n">V</span><span class="o">::</span><span class="n">Value</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">V</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">first</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">first</span><span class="p">;</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">first</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">match</span> <span class="bp">self</span><span class="p">.</span><span class="n">iter</span><span class="p">.</span><span class="n">next</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Some</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="kd">let</span> <span class="n">value</span> <span class="o">=</span> <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">visitor</span><span class="p">.</span><span class="n">visit_seq_elt</span><span class="p">(</span><span class="n">first</span><span class="p">,</span> <span class="n">value</span><span class="p">));</span>
</span><span class='line'>                <span class="nb">Ok</span><span class="p">(</span><span class="nb">Some</span><span class="p">(</span><span class="n">value</span><span class="p">))</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="nb">None</span> <span class="o">=&gt;</span> <span class="nb">Ok</span><span class="p">(</span><span class="nb">None</span><span class="p">),</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">size_hint</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">usize</span><span class="p">,</span> <span class="nb">Option</span><span class="o">&lt;</span><span class="n">usize</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">iter</span><span class="p">.</span><span class="n">size_hint</span><span class="p">()</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span>
</span><span class='line'>    <span class="nl">&#39;a</span><span class="p">,</span>
</span><span class='line'>    <span class="n">T</span><span class="o">:</span> <span class="n">Serialize</span><span class="p">,</span>
</span><span class='line'><span class="o">&gt;</span> <span class="n">Serialize</span> <span class="k">for</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="p">[</span><span class="n">T</span><span class="p">]</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">Visitor</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span> <span class="n">visitor</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">V</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">V</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">visitor</span><span class="p">.</span><span class="n">visit_seq</span><span class="p">(</span><span class="n">SeqIteratorVisitor</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">iter</span><span class="p">()))</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>SeqIteratorVisitor</code> is publically exposed, so it should be easy to use it with
custom data structures. Maps follow the same pattern (and also expose
<code>MapIteratorVisitor</code>), but each item instead uses <code>visit_visit_map_elt(first,
key, value)</code>.  Tuples, struct tuples, and tuple enum variants are all really
just named sequences. Likewise, structs and struct enum variants are just named
maps.</p>

<p>Because struct implementations are so common, here&rsquo;s an example how to do it:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">struct</span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">x</span><span class="o">:</span> <span class="kt">i32</span><span class="p">,</span>
</span><span class='line'>    <span class="n">y</span><span class="o">:</span> <span class="kt">i32</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">struct</span> <span class="n">PointVisitor</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">state</span><span class="o">:</span> <span class="kt">u32</span><span class="p">,</span>
</span><span class='line'>    <span class="n">value</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="n">Point</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="n">MapVisitor</span> <span class="k">for</span> <span class="n">PointVisitor</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">Visitor</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">visitor</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">V</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">V</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">match</span> <span class="bp">self</span><span class="p">.</span><span class="n">state</span> <span class="p">{</span>
</span><span class='line'>            <span class="mi">0</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="bp">self</span><span class="p">.</span><span class="n">state</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>                <span class="nb">Ok</span><span class="p">(</span><span class="nb">Some</span><span class="p">(</span><span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">visitor</span><span class="p">.</span><span class="n">visit_map_elt</span><span class="p">(</span><span class="k">true</span><span class="p">,</span> <span class="s">&quot;x&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">x</span><span class="p">))))</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="mi">1</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="bp">self</span><span class="p">.</span><span class="n">state</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>                <span class="nb">Ok</span><span class="p">(</span><span class="nb">Some</span><span class="p">(</span><span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">visitor</span><span class="p">.</span><span class="n">visit_map_elt</span><span class="p">(</span><span class="k">true</span><span class="p">,</span> <span class="s">&quot;y&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">y</span><span class="p">))))</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="n">_</span> <span class="o">=&gt;</span> <span class="nb">Ok</span><span class="p">(</span><span class="nb">None</span><span class="p">),</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span> <span class="n">Serialize</span> <span class="k">for</span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">Visitor</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span> <span class="n">visitor</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">V</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">V</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">visit_named_map</span><span class="p">(</span><span class="s">&quot;Point&quot;</span><span class="p">,</span> <span class="n">PointVisitor</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">state</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
</span><span class='line'>            <span class="n">value</span><span class="o">:</span> <span class="bp">self</span><span class="p">,</span>
</span><span class='line'>        <span class="p">})</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Fortunately <code>serde2</code> also comes with a <code>#[derive_serialize]</code> macro so you don&rsquo;t
need to write this out by hand if you don&rsquo;t want to.</p>

<h3>Serializer</h3>

<p>Now to actually build a serializer. We start with a trait:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Serializer</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">type</span> <span class="n">Value</span><span class="p">;</span>
</span><span class='line'>    <span class="k">type</span> <span class="n">Error</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span>
</span><span class='line'>        <span class="n">where</span> <span class="n">T</span><span class="o">:</span> <span class="n">Serialize</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>It&rsquo;s the responsibility of the serializer to create a visitor and then pass it
to the type. Oftentimes the serializer also implements <code>Visitor</code>, but it&rsquo;s not
required. Here&rsquo;s a snippet of the JSON serializer visitor:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">struct</span> <span class="n">Visitor</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="p">,</span> <span class="n">W</span><span class="o">:</span> <span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">writer</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="k">mut</span> <span class="n">W</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="p">,</span> <span class="n">W</span><span class="o">:</span> <span class="nb">Writer</span><span class="o">&gt;</span> <span class="n">Visitor</span> <span class="k">for</span> <span class="n">Visitor</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="p">,</span> <span class="n">W</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">type</span> <span class="n">Value</span> <span class="o">=</span> <span class="p">();</span>
</span><span class='line'>    <span class="k">type</span> <span class="n">Error</span> <span class="o">=</span> <span class="n">io</span><span class="o">::</span><span class="n">Error</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_unit</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">writer</span><span class="p">.</span><span class="n">write_all</span><span class="p">(</span><span class="n">b</span><span class="s">&quot;null&quot;</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_bool</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="o">:</span> <span class="kt">bool</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">if</span> <span class="n">value</span> <span class="p">{</span>
</span><span class='line'>            <span class="bp">self</span><span class="p">.</span><span class="n">writer</span><span class="p">.</span><span class="n">write_all</span><span class="p">(</span><span class="n">b</span><span class="s">&quot;true&quot;</span><span class="p">)</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="bp">self</span><span class="p">.</span><span class="n">writer</span><span class="p">.</span><span class="n">write_all</span><span class="p">(</span><span class="n">b</span><span class="s">&quot;false&quot;</span><span class="p">)</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_isize</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="o">:</span> <span class="n">isize</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">write</span><span class="o">!</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">writer</span><span class="p">,</span> <span class="s">&quot;{}&quot;</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_map</span><span class="o">&lt;</span><span class="n">V</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="k">mut</span> <span class="n">visitor</span><span class="o">:</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span>
</span><span class='line'>        <span class="n">where</span> <span class="n">V</span><span class="o">:</span> <span class="n">ser</span><span class="o">::</span><span class="n">MapVisitor</span><span class="p">,</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">writer</span><span class="p">.</span><span class="n">write_all</span><span class="p">(</span><span class="n">b</span><span class="s">&quot;{&quot;</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">while</span> <span class="kd">let</span> <span class="nb">Some</span><span class="p">(())</span> <span class="o">=</span> <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">visitor</span><span class="p">.</span><span class="n">visit</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span> <span class="p">{</span> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">writer</span><span class="p">.</span><span class="n">write_all</span><span class="p">(</span><span class="n">b</span><span class="s">&quot;}&quot;</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_map_elt</span><span class="o">&lt;</span><span class="n">K</span><span class="p">,</span> <span class="n">V</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">first</span><span class="o">:</span> <span class="kt">bool</span><span class="p">,</span> <span class="n">key</span><span class="o">:</span> <span class="n">K</span><span class="p">,</span> <span class="n">value</span><span class="o">:</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span>
</span><span class='line'>        <span class="n">where</span> <span class="n">K</span><span class="o">:</span> <span class="n">ser</span><span class="o">::</span><span class="n">Serialize</span><span class="p">,</span>
</span><span class='line'>              <span class="n">V</span><span class="o">:</span> <span class="n">ser</span><span class="o">::</span><span class="n">Serialize</span><span class="p">,</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="k">if</span> <span class="o">!</span><span class="n">first</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">writer</span><span class="p">.</span><span class="n">write_all</span><span class="p">(</span><span class="n">b</span><span class="s">&quot;,&quot;</span><span class="p">));</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">key</span><span class="p">.</span><span class="n">visit</span><span class="p">(</span><span class="bp">self</span><span class="p">));</span>
</span><span class='line'>        <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">writer</span><span class="p">.</span><span class="n">write_all</span><span class="p">(</span><span class="n">b</span><span class="s">&quot;:&quot;</span><span class="p">));</span>
</span><span class='line'>        <span class="n">value</span><span class="p">.</span><span class="n">visit</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Hopefully it is pretty straight forward.</p>

<h2>Deserialization</h2>

<p>Now serialization is the easy part. Deserialization is where it always gets
more tricky. We follow a similar pattern as serialization. A deserializee
creates a visitor which accepts any type (most resulting in an error), and
passes it to a deserializer. This deserializer then extracts it&rsquo;s next value
from it&rsquo;s stream and passes it to the visitor, which then produces the actual
type.</p>

<p>It&rsquo;s achingly close to the same pattern between a serializer and a serializee,
but as hard as I tried, I couldn&rsquo;t unify the two. The error semantics are
different. In serialization, you want the serializer (which creates the
visitor) to define the error. In deserialization, you want the deserializer
which consumes the visitor to define the error.</p>

<p>Let&rsquo;s start first with <code>Error</code>. As opposed to serialization, when we&rsquo;re
deserializing we can error both in the <code>Deserializer</code> if there is a parse
error, or in the <code>Deserialize</code> if it&rsquo;s received an unexpected value. We do this
with an <code>Error</code> trait, which allows a deserializee to generically create the
few errors it needs:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Error</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">syntax_error</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Self</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">end_of_stream_error</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Self</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">missing_field_error</span><span class="p">(</span><span class="o">&amp;</span><span class="n">&#39;static</span> <span class="kt">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Self</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now the <code>Deserialize</code> trait, which looks similar to <code>Serialize</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Deserialize</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">deserialize</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">D</span><span class="o">:</span> <span class="n">Deserializer</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="n">deserializer</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">D</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="p">,</span> <span class="n">D</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The <code>Visitor</code> also looks like the serialization <code>Visitor</code>, except for the
methods error by default.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Visitor</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">type</span> <span class="n">Value</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_bool</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">E</span><span class="o">:</span> <span class="n">Error</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">_v</span><span class="o">:</span> <span class="kt">bool</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="nb">Err</span><span class="p">(</span><span class="n">Error</span><span class="o">::</span><span class="n">syntax_error</span><span class="p">())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_isize</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">E</span><span class="o">:</span> <span class="n">Error</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="n">isize</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">visit_i64</span><span class="p">(</span><span class="n">v</span> <span class="k">as</span> <span class="kt">i64</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Sequences and Maps are also a little different:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Visitor</span> <span class="p">{</span>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_seq</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">SeqVisitor</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">_visitor</span><span class="o">:</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">V</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="nb">Err</span><span class="p">(</span><span class="n">Error</span><span class="o">::</span><span class="n">syntax_error</span><span class="p">())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_map</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">MapVisitor</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">_visitor</span><span class="o">:</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">V</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="nb">Err</span><span class="p">(</span><span class="n">Error</span><span class="o">::</span><span class="n">syntax_error</span><span class="p">())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">SeqVisitor</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">type</span> <span class="n">Error</span><span class="o">:</span> <span class="n">Error</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">T</span><span class="o">:</span> <span class="n">Deserialize</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="nb">Option</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">end</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">size_hint</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">usize</span><span class="p">,</span> <span class="nb">Option</span><span class="o">&lt;</span><span class="n">usize</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">None</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">MapVisitor</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">type</span> <span class="n">Error</span><span class="o">:</span> <span class="n">Error</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">K</span><span class="o">:</span> <span class="n">Deserialize</span><span class="p">,</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">Deserialize</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="nb">Option</span><span class="o">&lt;</span><span class="p">(</span><span class="n">K</span><span class="p">,</span> <span class="n">V</span><span class="p">)</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">match</span> <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">visit_key</span><span class="p">())</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Some</span><span class="p">(</span><span class="n">key</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="kd">let</span> <span class="n">value</span> <span class="o">=</span> <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">visit_value</span><span class="p">());</span>
</span><span class='line'>                <span class="nb">Ok</span><span class="p">(</span><span class="nb">Some</span><span class="p">((</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">)))</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="nb">None</span> <span class="o">=&gt;</span> <span class="nb">Ok</span><span class="p">(</span><span class="nb">None</span><span class="p">)</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_key</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">K</span><span class="o">:</span> <span class="n">Deserialize</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="nb">Option</span><span class="o">&lt;</span><span class="n">K</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_value</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">Deserialize</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">V</span><span class="p">,</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">end</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">size_hint</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">usize</span><span class="p">,</span> <span class="nb">Option</span><span class="o">&lt;</span><span class="n">usize</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">None</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Here is an example struct deserializer. Structs are deserialized as a map, but
since maps are unordered, we need a simple state machine to extract the values.
In order to get the keys, we just create an enum for the fields, and a custom
deserializer to convert a string into a field without an allocation:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">struct</span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">x</span><span class="o">:</span> <span class="kt">i32</span><span class="p">,</span>
</span><span class='line'>    <span class="n">y</span><span class="o">:</span> <span class="kt">i32</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span> <span class="n">Deserialize</span> <span class="k">for</span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">deserialize</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">D</span><span class="o">:</span> <span class="n">Deserializer</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="n">deserializer</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">D</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Point</span><span class="p">,</span> <span class="n">D</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">enum</span> <span class="n">Field</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">x</span><span class="p">,</span>
</span><span class='line'>            <span class="n">y</span><span class="p">,</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">struct</span> <span class="n">FieldVisitor</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">impl</span> <span class="n">Visitor</span> <span class="k">for</span> <span class="n">FieldVisitor</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">type</span> <span class="n">Value</span> <span class="o">=</span> <span class="n">Field</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>            <span class="k">fn</span> <span class="n">visit_str</span><span class="o">&lt;</span>
</span><span class='line'>                <span class="n">E</span><span class="o">:</span> <span class="n">Error</span><span class="p">,</span>
</span><span class='line'>            <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="o">:</span> <span class="o">&amp;</span><span class="kt">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Field</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">match</span> <span class="n">value</span> <span class="p">{</span>
</span><span class='line'>                    <span class="s">&quot;x&quot;</span> <span class="o">=&gt;</span> <span class="nb">Ok</span><span class="p">(</span><span class="n">Field</span><span class="o">::</span><span class="n">x</span><span class="p">),</span>
</span><span class='line'>                    <span class="s">&quot;y&quot;</span> <span class="o">=&gt;</span> <span class="nb">Ok</span><span class="p">(</span><span class="n">Field</span><span class="o">::</span><span class="n">y</span><span class="p">),</span>
</span><span class='line'>                    <span class="n">_</span> <span class="o">=&gt;</span> <span class="nb">Err</span><span class="p">(</span><span class="n">Error</span><span class="o">::</span><span class="n">syntax_error</span><span class="p">()),</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">impl</span> <span class="n">Deserialize</span> <span class="k">for</span> <span class="n">Field</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">fn</span> <span class="n">deserialize</span><span class="o">&lt;</span>
</span><span class='line'>                <span class="n">D</span><span class="o">:</span> <span class="n">Deserializer</span><span class="p">,</span>
</span><span class='line'>            <span class="o">&gt;</span><span class="p">(</span><span class="n">state</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">D</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Field</span><span class="p">,</span> <span class="n">D</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">state</span><span class="p">.</span><span class="n">visit</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="n">FieldVisitor</span><span class="p">)</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">struct</span> <span class="n">Visitor</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">impl</span> <span class="n">Visitor</span> <span class="k">for</span> <span class="n">Visitor</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">type</span> <span class="n">Value</span> <span class="o">=</span> <span class="n">Point</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>            <span class="k">fn</span> <span class="n">visit_map</span><span class="o">&lt;</span>
</span><span class='line'>                <span class="n">V</span><span class="o">:</span> <span class="n">MapVisitor</span><span class="p">,</span>
</span><span class='line'>            <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="k">mut</span> <span class="n">visitor</span><span class="o">:</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Point</span><span class="p">,</span> <span class="n">V</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="p">{</span>
</span><span class='line'>                    <span class="kd">let</span> <span class="k">mut</span> <span class="n">x</span> <span class="o">=</span> <span class="nb">None</span><span class="p">;</span>
</span><span class='line'>                    <span class="kd">let</span> <span class="k">mut</span> <span class="n">y</span> <span class="o">=</span> <span class="nb">None</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>                    <span class="k">while</span> <span class="kd">let</span> <span class="nb">Some</span><span class="p">(</span><span class="n">key</span><span class="p">)</span> <span class="o">=</span> <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">visitor</span><span class="p">.</span><span class="n">visit_key</span><span class="p">())</span> <span class="p">{</span>
</span><span class='line'>                        <span class="k">match</span> <span class="n">key</span> <span class="p">{</span>
</span><span class='line'>                            <span class="n">Field</span><span class="o">::</span><span class="n">x</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                                <span class="n">x</span> <span class="o">=</span> <span class="nb">Some</span><span class="p">(</span><span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">visitor</span><span class="p">.</span><span class="n">visit_value</span><span class="p">()));</span>
</span><span class='line'>                            <span class="p">}</span>
</span><span class='line'>                            <span class="n">Field</span><span class="o">::</span><span class="n">y</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                                <span class="n">y</span> <span class="o">=</span> <span class="nb">Some</span><span class="p">(</span><span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">visitor</span><span class="p">.</span><span class="n">visit_value</span><span class="p">()));</span>
</span><span class='line'>                            <span class="p">}</span>
</span><span class='line'>                        <span class="p">}</span>
</span><span class='line'>                    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>                    <span class="kd">let</span> <span class="n">x</span> <span class="o">=</span> <span class="k">match</span> <span class="n">x</span> <span class="p">{</span>
</span><span class='line'>                        <span class="nb">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="n">x</span><span class="p">,</span>
</span><span class='line'>                        <span class="nb">None</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                            <span class="k">return</span> <span class="nb">Err</span><span class="p">(</span><span class="n">Error</span><span class="o">::</span><span class="n">missing_field_error</span><span class="p">(</span><span class="s">&quot;x&quot;</span><span class="p">));</span>
</span><span class='line'>                        <span class="p">}</span>
</span><span class='line'>                    <span class="p">};</span>
</span><span class='line'>                    <span class="kd">let</span> <span class="n">y</span> <span class="o">=</span> <span class="k">match</span> <span class="n">y</span> <span class="p">{</span>
</span><span class='line'>                        <span class="nb">Some</span><span class="p">(</span><span class="n">y</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="n">y</span><span class="p">,</span>
</span><span class='line'>                        <span class="nb">None</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                            <span class="k">return</span> <span class="nb">Err</span><span class="p">(</span><span class="n">Error</span><span class="o">::</span><span class="n">missing_field_error</span><span class="p">(</span><span class="s">&quot;y&quot;</span><span class="p">));</span>
</span><span class='line'>                        <span class="p">}</span>
</span><span class='line'>                    <span class="p">};</span>
</span><span class='line'>
</span><span class='line'>                    <span class="nb">Ok</span><span class="p">(</span><span class="n">Point</span> <span class="p">{</span>
</span><span class='line'>                        <span class="n">x</span><span class="o">:</span> <span class="n">x</span><span class="p">,</span>
</span><span class='line'>                        <span class="n">y</span><span class="o">:</span> <span class="n">y</span><span class="p">,</span>
</span><span class='line'>                    <span class="p">})</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>            <span class="k">fn</span> <span class="n">visit_named_map</span><span class="o">&lt;</span>
</span><span class='line'>                <span class="n">V</span><span class="o">:</span> <span class="n">MapVisitor</span><span class="p">,</span>
</span><span class='line'>            <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">:</span> <span class="o">&amp;</span><span class="kt">str</span><span class="p">,</span> <span class="n">visitor</span><span class="o">:</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Point</span><span class="p">,</span> <span class="n">V</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">if</span> <span class="n">name</span> <span class="o">==</span> <span class="s">&quot;Point&quot;</span> <span class="p">{</span>
</span><span class='line'>                    <span class="bp">self</span><span class="p">.</span><span class="n">visit_map</span><span class="p">(</span><span class="n">visitor</span><span class="p">)</span>
</span><span class='line'>                <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>                    <span class="nb">Err</span><span class="p">(</span><span class="n">Error</span><span class="o">::</span><span class="n">syntax_error</span><span class="p">())</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="n">deserializer</span><span class="p">.</span><span class="n">visit</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="n">Visitor</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>It&rsquo;s a little more complicated, but once again there is
<code>#[derive_deserialize]</code>, which does all this work for you.</p>

<h3>Deserializer</h3>

<p>Deserializers then follow the same pattern as serializers. The one difference
is that we need to provide a special hook for <code>Option&lt;T&gt;</code> types so formats like
JSON can treat <code>null</code> types as options.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Deserializer</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">type</span> <span class="n">Error</span><span class="o">:</span> <span class="n">Error</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">Visitor</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">visitor</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">V</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="c-Doc">/// The `visit_option` method allows a `Deserialize` type to inform the</span>
</span><span class='line'>    <span class="c-Doc">/// `Deserializer` that it&#39;s expecting an optional value. This allows</span>
</span><span class='line'>    <span class="c-Doc">/// deserializers that encode an optional value as a nullable value to</span>
</span><span class='line'>    <span class="c-Doc">/// convert the null value into a `None`, and a regular value as</span>
</span><span class='line'>    <span class="c-Doc">/// `Some(value)`.</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">visit_option</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">Visitor</span><span class="p">,</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">visitor</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">V</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">V</span><span class="o">::</span><span class="n">Value</span><span class="p">,</span> <span class="n">Self</span><span class="o">::</span><span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">visit</span><span class="p">(</span><span class="n">visitor</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Performance</h2>

<p>So how does it perform? Here&rsquo;s the serialization benchmarks, with yet another
ordering. This time sorted by the performance:</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library                   </th>
<th> format                 </th>
<th> serialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> Rust     </td>
<td> capnproto-rust            </td>
<td> Cap&#8217;n Proto (unpacked) </td>
<td> 4226                 </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto              </td>
<td> Cap&#8217;n Proto            </td>
<td> 3824.20              </td>
</tr>
<tr>
<td> Rust     </td>
<td> bincode                   </td>
<td> Binary                 </td>
<td> 1020                 </td>
</tr>
<tr>
<td> Rust     </td>
<td> capnproto-rust            </td>
<td> Cap&#8217;n Proto (packed)   </td>
<td> 672                  </td>
</tr>
<tr>
<td> Go       </td>
<td> gogoprotobuf              </td>
<td> Protocol Buffers       </td>
<td> 596.78               </td>
</tr>
<tr>
<td> Rust     </td>
<td> rust-msgpack              </td>
<td> MessagePack            </td>
<td> 397                  </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>serde2::json</strong> (&amp;[u8])  </td>
<td> <strong>JSON</strong>               </td>
<td> <strong>373</strong>              </td>
</tr>
<tr>
<td> Rust     </td>
<td> rust-protobuf             </td>
<td> Protocol Buffers       </td>
<td> 357                  </td>
</tr>
<tr>
<td> C++      </td>
<td> rapidjson                 </td>
<td> JSON                   </td>
<td> 316                  </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>serde2::json</strong> (Custom) </td>
<td> <strong>JSON</strong>               </td>
<td> <strong>306</strong>              </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>serde2::json</strong> (Vec)    </td>
<td> <strong>JSON</strong>               </td>
<td> <strong>288</strong>              </td>
</tr>
<tr>
<td> Rust     </td>
<td> serde::json (Custom)      </td>
<td> JSON                   </td>
<td> 244                  </td>
</tr>
<tr>
<td> Rust     </td>
<td> serde::json (&amp;[u8])       </td>
<td> JSON                   </td>
<td> 222                  </td>
</tr>
<tr>
<td> Go       </td>
<td> goprotobuf                </td>
<td> Protocol Buffers       </td>
<td> 214.68               </td>
</tr>
<tr>
<td> Rust     </td>
<td> serde::json (Vec)         </td>
<td> JSON                   </td>
<td> 149                  </td>
</tr>
<tr>
<td> Go       </td>
<td> ffjson                    </td>
<td> JSON                   </td>
<td> 147.37               </td>
</tr>
<tr>
<td> Rust     </td>
<td> serialize::json           </td>
<td> JSON                   </td>
<td> 183                  </td>
</tr>
<tr>
<td> Go       </td>
<td> encoding/json             </td>
<td> JSON                   </td>
<td> 80.49                </td>
</tr>
</tbody>
</table>


<p>I think it&rsquo;s fair to say that on at least this benchmark we&rsquo;ve hit our
performance numbers. Writing to a preallocated buffer with <code>BufWriter</code> is 18%
<em>faster</em> than <a href="https://github.com/miloyip/rapidjson">rapidjson</a> (although to be
fair they are allocating). Our <code>Vec&lt;u8&gt;</code> writer comes in 12% slower. What&rsquo;s
interesting is this custom Writer. It turns out LLVM is still having trouble
lowering our generic <code>Vec::push_all</code> into a <code>memcpy</code>. This Writer variant
however is able to get us to rapidjson&rsquo;s level:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">fn</span> <span class="n">push_all_bytes</span><span class="p">(</span><span class="n">dst</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">Vec</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">src</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">dst_len</span> <span class="o">=</span> <span class="n">dst</span><span class="p">.</span><span class="n">len</span><span class="p">();</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">src_len</span> <span class="o">=</span> <span class="n">src</span><span class="p">.</span><span class="n">len</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">dst</span><span class="p">.</span><span class="n">reserve</span><span class="p">(</span><span class="n">src_len</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>        <span class="c1">// we would have failed if `reserve` overflowed.</span>
</span><span class='line'>        <span class="n">dst</span><span class="p">.</span><span class="n">set_len</span><span class="p">(</span><span class="n">dst_len</span> <span class="o">+</span> <span class="n">src_len</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="o">::</span><span class="n">std</span><span class="o">::</span><span class="n">ptr</span><span class="o">::</span><span class="n">copy_nonoverlapping_memory</span><span class="p">(</span>
</span><span class='line'>            <span class="n">dst</span><span class="p">.</span><span class="n">as_mut_ptr</span><span class="p">().</span><span class="n">offset</span><span class="p">(</span><span class="n">dst_len</span> <span class="k">as</span> <span class="n">isize</span><span class="p">),</span>
</span><span class='line'>            <span class="n">src</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span>
</span><span class='line'>            <span class="n">src_len</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">struct</span> <span class="n">MyMemWriter1</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">buf</span><span class="o">:</span> <span class="n">Vec</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span> <span class="nb">Writer</span> <span class="k">for</span> <span class="n">MyMemWriter1</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">write_all</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">buf</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">push_all_bytes</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">.</span><span class="n">buf</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span>
</span><span class='line'>        <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Deserialization we do much better than serde because we aren&rsquo;t passing around
all those tags, but we have a ways to catch up to rapidjson. Still, being just 37%
slower than the fastest JSON deserializer makes me feel pretty proud.</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library          </th>
<th> format                  </th>
<th> deserialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> Rust     </td>
<td> capnproto-rust   </td>
<td> Cap&#8217;n Proto (unpacked)  </td>
<td> 2123                   </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto     </td>
<td> Cap&#8217;n Proto (zero copy) </td>
<td> 1407.95                </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto     </td>
<td> Cap&#8217;n Proto             </td>
<td> 711.77                 </td>
</tr>
<tr>
<td> Rust     </td>
<td> capnproto-rust   </td>
<td> Cap&#8217;n Proto (packed)    </td>
<td> 529                    </td>
</tr>
<tr>
<td> Go       </td>
<td> gogoprotobuf     </td>
<td> Protocol Buffers        </td>
<td> 272.68                 </td>
</tr>
<tr>
<td> C++      </td>
<td> rapidjson        </td>
<td> JSON (sax)              </td>
<td> 189                    </td>
</tr>
<tr>
<td> C++      </td>
<td> rapidjson        </td>
<td> JSON (dom)              </td>
<td> 162                    </td>
</tr>
<tr>
<td> Rust     </td>
<td> bincode          </td>
<td> Binary                  </td>
<td> 142                    </td>
</tr>
<tr>
<td> Rust     </td>
<td> rust-protobuf    </td>
<td> Protocol Buffers        </td>
<td> 141                    </td>
</tr>
<tr>
<td> Rust     </td>
<td> rust-msgpack     </td>
<td> MessagePack             </td>
<td> 138                    </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>serde2::json</strong> </td>
<td> <strong>JSON</strong>                </td>
<td> <strong>122</strong>                </td>
</tr>
<tr>
<td> Go       </td>
<td> ffjson           </td>
<td> JSON                    </td>
<td> 95.06                  </td>
</tr>
<tr>
<td> Go       </td>
<td> goprotobuf       </td>
<td> Protocol Buffers        </td>
<td> 79.78                  </td>
</tr>
<tr>
<td> Rust     </td>
<td> serde::json      </td>
<td> JSON                    </td>
<td> 67                     </td>
</tr>
<tr>
<td> Rust     </td>
<td> serialize::json  </td>
<td> JSON                    </td>
<td> 25                     </td>
</tr>
<tr>
<td> Go       </td>
<td> encoding/json    </td>
<td> JSON                    </td>
<td> 22.79                  </td>
</tr>
</tbody>
</table>


<h2>Conclusion</h2>

<p>What a long trip it&rsquo;s been! I hope you enjoyed it. While there are still
a few things left to port over from serde1 to serde2 (like the JSON pretty
printer), and some things probably should be renamed, I&rsquo;m happy with the design
so I think it&rsquo;s in a place where people can start using it now. Please let me
know how it goes!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Syntex: Syntax Extensions for Rust 1.0]]></title>
    <link href="http://erickt.github.io/blog/2015/02/09/syntex-syntex-extensions-for-rust-1-dot-0/"/>
    <updated>2015-02-09T19:37:32-08:00</updated>
    <id>http://erickt.github.io/blog/2015/02/09/syntex-syntex-extensions-for-rust-1-dot-0</id>
    <content type="html"><![CDATA[<p>I use and love syntax extensions, and I&rsquo;m planning on using them to simplify
down how one interacts with a system like
<a href="https://github.com/erickt/rust-serde">serde</a>. Unfortunately though, to write
them you need to use Rust&rsquo;s <code>libsyntax</code>, which is not going to be exposed in
Rust 1.0 because we&rsquo;re not ready to stablize it&rsquo;s API. That would really hamper
future development of the compiler.</p>

<p>It would be so nice though, writing this for every type we want to serialize:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[derive_deserialize]</span>
</span><span class='line'><span class="k">struct</span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">x</span><span class="o">:</span> <span class="kt">int</span><span class="p">,</span>
</span><span class='line'>    <span class="n">y</span><span class="o">:</span> <span class="kt">int</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>instead of:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span> <span class="o">&lt;</span><span class="n">D</span><span class="o">:</span> <span class="n">Deserializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="n">Deserialize</span><span class="o">&lt;</span><span class="n">D</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="k">for</span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">deserialize_token</span><span class="p">(</span><span class="n">state</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">D</span><span class="p">,</span> <span class="n">token</span><span class="o">:</span> <span class="n">Token</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Point</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">state</span><span class="p">.</span><span class="n">expect_struct_start</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="s">&quot;Point&quot;</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="k">mut</span> <span class="n">x</span> <span class="o">=</span> <span class="nb">None</span><span class="p">;</span>
</span><span class='line'>        <span class="kd">let</span> <span class="k">mut</span> <span class="n">y</span> <span class="o">=</span> <span class="nb">None</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">loop</span> <span class="p">{</span>
</span><span class='line'>            <span class="kd">let</span> <span class="n">idx</span> <span class="o">=</span> <span class="k">match</span> <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">state</span><span class="p">.</span><span class="n">expect_struct_field_or_end</span><span class="p">(</span><span class="o">&amp;</span><span class="p">[</span><span class="s">&quot;x&quot;</span><span class="p">,</span> <span class="s">&quot;y&quot;</span><span class="p">]))</span> <span class="p">{</span>
</span><span class='line'>                <span class="nb">Some</span><span class="p">(</span><span class="n">idx</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="n">idx</span><span class="p">,</span>
</span><span class='line'>                <span class="nb">None</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="k">break</span> <span class="p">;</span> <span class="p">}</span>
</span><span class='line'>            <span class="p">};</span>
</span><span class='line'>
</span><span class='line'>            <span class="k">match</span> <span class="n">idx</span> <span class="p">{</span>
</span><span class='line'>                <span class="nb">Some</span><span class="p">(</span><span class="mi">0</span><span class="k">u</span><span class="n">s</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="n">x</span> <span class="o">=</span> <span class="nb">Some</span><span class="p">(</span><span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">state</span><span class="p">.</span><span class="n">expect_struct_value</span><span class="p">()));</span> <span class="p">}</span>
</span><span class='line'>                <span class="nb">Some</span><span class="p">(</span><span class="mi">1</span><span class="k">u</span><span class="n">s</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="n">y</span> <span class="o">=</span> <span class="nb">Some</span><span class="p">(</span><span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">state</span><span class="p">.</span><span class="n">expect_struct_value</span><span class="p">()));</span> <span class="p">}</span>
</span><span class='line'>                <span class="nb">None</span> <span class="o">|</span> <span class="nb">Some</span><span class="p">(</span><span class="n">_</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="n">panic</span><span class="o">!</span><span class="p">()</span> <span class="p">}</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="n">x</span> <span class="o">=</span> <span class="k">match</span> <span class="n">x</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="n">x</span><span class="p">,</span>
</span><span class='line'>            <span class="nb">None</span> <span class="o">=&gt;</span> <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">state</span><span class="p">.</span><span class="n">missing_field</span><span class="p">(</span><span class="s">&quot;x&quot;</span><span class="p">)),</span>
</span><span class='line'>        <span class="p">};</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="n">y</span> <span class="o">=</span> <span class="k">match</span> <span class="n">y</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Some</span><span class="p">(</span><span class="n">y</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="n">y</span><span class="p">,</span>
</span><span class='line'>            <span class="nb">None</span> <span class="o">=&gt;</span> <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">state</span><span class="p">.</span><span class="n">missing_field</span><span class="p">(</span><span class="s">&quot;y&quot;</span><span class="p">)),</span>
</span><span class='line'>        <span class="p">};</span>
</span><span class='line'>
</span><span class='line'>        <span class="nb">Ok</span><span class="p">(</span><span class="n">Point</span><span class="p">{</span><span class="n">x</span><span class="o">:</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="o">:</span> <span class="n">y</span><span class="p">,})</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>So I want to announce my plan on how to deal with this (and also publically
announce that everyone can blame me if this turns out to hurt Rust&rsquo;s future
development). I&rsquo;ve started <a href="https://github.com/erickt/rust-syntex">syntex</a>, a
library that enables code generation using an unofficial tracking fork of
<code>libsyntax</code>. In order to deal with the fact that <code>libsyntax</code> might make
breaking changes between minor Rust releases, we will just release a minor or
major release of <code>syntex</code>, depending on if there were any breaking changes in
<code>libsyntax</code>.  Ideally <code>syntex</code> will allow the community to experiment with
different code generation approaches to see what would be worth merging
upstream. Or even better, what hooks are needed in the compiler so it doesn&rsquo;t
have to think about syntax extensions at all.</p>

<p>I&rsquo;ve got the basic version working right now. Here&rsquo;s a simple
<code>hello_world_macros</code> syntax extension (you can see the actual code
<a href="https://github.com/erickt/rust-syntex/tree/master/hello_world">here</a>).
First, the <code>hello_world_macros/Cargo.toml</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='toml'><span class='line'><span class="p">[</span><span class="n">package</span><span class="p">]</span>
</span><span class='line'><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;hello_world_macros&quot;</span>
</span><span class='line'><span class="n">version</span> <span class="o">=</span> <span class="s">&quot;0.2.0&quot;</span>
</span><span class='line'><span class="n">authors</span> <span class="o">=</span> <span class="p">[</span> <span class="s">&quot;erick.tryzelaar@gmail.com&quot;</span> <span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="p">[</span><span class="n">dependencies</span><span class="p">]</span>
</span><span class='line'><span class="n">syntex</span> <span class="o">=</span> <span class="s">&quot;*&quot;</span>
</span><span class='line'><span class="n">syntex_syntax</span> <span class="o">=</span> <span class="s">&quot;*&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>The <code>syntex_syntax</code> is the crate for my fork of <code>libsyntax</code>, and <code>syntex</code>
provides some helper functions to ease registering syntax extensions.</p>

<p>Then the <code>src/lib.rs</code>, which declares a macro <code>hello_world</code> that just produces a
<code>"hello world"</code> string:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">syntex</span><span class="p">;</span>
</span><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">syntex_syntax</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kn">use</span> <span class="n">syntex</span><span class="o">::</span><span class="n">Registry</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kn">use</span> <span class="n">syntex_syntax</span><span class="o">::</span><span class="n">ast</span><span class="o">::</span><span class="n">TokenTree</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">syntex_syntax</span><span class="o">::</span><span class="n">codemap</span><span class="o">::</span><span class="n">Span</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">syntex_syntax</span><span class="o">::</span><span class="n">ext</span><span class="o">::</span><span class="n">base</span><span class="o">::</span><span class="p">{</span><span class="n">ExtCtxt</span><span class="p">,</span> <span class="n">MacExpr</span><span class="p">,</span> <span class="n">MacResult</span><span class="p">,</span> <span class="n">TTMacroExpander</span><span class="p">};</span>
</span><span class='line'><span class="kn">use</span> <span class="n">syntex_syntax</span><span class="o">::</span><span class="n">ext</span><span class="o">::</span><span class="n">build</span><span class="o">::</span><span class="n">AstBuilder</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">syntex_syntax</span><span class="o">::</span><span class="n">parse</span><span class="o">::</span><span class="n">token</span><span class="o">::</span><span class="n">InternedString</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">expand_hello_world</span><span class="o">&lt;</span><span class="nl">&#39;cx</span><span class="o">&gt;</span><span class="p">(</span>
</span><span class='line'>    <span class="n">cx</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;cx</span> <span class="k">mut</span> <span class="n">ExtCtxt</span><span class="p">,</span>
</span><span class='line'>    <span class="n">sp</span><span class="o">:</span> <span class="n">Span</span><span class="p">,</span>
</span><span class='line'>    <span class="n">tts</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="n">TokenTree</span><span class="p">]</span>
</span><span class='line'><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Box</span><span class="o">&lt;</span><span class="n">MacResult</span> <span class="o">+</span> <span class="nl">&#39;cx</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">expr</span> <span class="o">=</span> <span class="n">cx</span><span class="p">.</span><span class="n">expr_str</span><span class="p">(</span><span class="n">sp</span><span class="p">,</span> <span class="n">InternedString</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="s">&quot;hello world&quot;</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">MacExpr</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="n">expr</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">pub</span> <span class="k">fn</span> <span class="n">register</span><span class="p">(</span><span class="n">registry</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">Registry</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">registry</span><span class="p">.</span><span class="n">register_fn</span><span class="p">(</span><span class="s">&quot;hello_world&quot;</span><span class="p">,</span> <span class="n">expand_hello_world</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now to use it. This is a little more complicated because we have to do code
generation, but Cargo helps with that. Our strategy is use a <code>build.rs</code> script
to do code generation in a <code>main.rss</code> file, and then use the <code>include!()</code> macro
to include it into our dummy <code>main.rs</code> file. Here&rsquo;s the <code>Cargo.toml</code> we need:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="p">[</span><span class="n">package</span><span class="p">]</span>
</span><span class='line'><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;hello_world&quot;</span>
</span><span class='line'><span class="n">version</span> <span class="o">=</span> <span class="s">&quot;0.2.0&quot;</span>
</span><span class='line'><span class="n">authors</span> <span class="o">=</span> <span class="p">[</span> <span class="s">&quot;erick.tryzelaar@gmail.com&quot;</span> <span class="p">]</span>
</span><span class='line'><span class="n">build</span> <span class="o">=</span> <span class="s">&quot;build.rs&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="p">[</span><span class="n">build</span><span class="o">-</span><span class="n">dependencies</span><span class="p">]</span>
</span><span class='line'><span class="n">syntex</span> <span class="o">=</span> <span class="s">&quot;*&quot;</span>
</span><span class='line'><span class="n">syntex_syntax</span> <span class="o">=</span> <span class="s">&quot;*&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="p">[</span><span class="n">build</span><span class="o">-</span><span class="n">dependencies</span><span class="p">.</span><span class="n">hello_world_macros</span><span class="p">]</span>
</span><span class='line'><span class="n">path</span> <span class="o">=</span> <span class="s">&quot;hello_world_macros&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Here&rsquo;s the <code>build.rs</code>, which actually performs the code generation:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">syntex</span><span class="p">;</span>
</span><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">hello_world_macros</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">os</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">registry</span> <span class="o">=</span> <span class="n">syntex</span><span class="o">::</span><span class="n">Registry</span><span class="o">::</span><span class="n">new</span><span class="p">();</span>
</span><span class='line'>    <span class="n">hello_world_macros</span><span class="o">::</span><span class="n">register</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="n">registry</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">registry</span><span class="p">.</span><span class="n">expand</span><span class="p">(</span>
</span><span class='line'>        <span class="s">&quot;hello_world&quot;</span><span class="p">,</span>
</span><span class='line'>        <span class="o">&amp;</span><span class="nb">Path</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="s">&quot;src/main.rss&quot;</span><span class="p">),</span>
</span><span class='line'>        <span class="o">&amp;</span><span class="nb">Path</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="n">os</span><span class="o">::</span><span class="n">getenv</span><span class="p">(</span><span class="s">&quot;OUT_DIR&quot;</span><span class="p">).</span><span class="n">unwrap</span><span class="p">()).</span><span class="n">join</span><span class="p">(</span><span class="s">&quot;main.rs&quot;</span><span class="p">));</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Our <code>main.rs</code> driver script:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="c1">// Include the real main</span>
</span><span class='line'><span class="n">include</span><span class="o">!</span><span class="p">(</span><span class="n">concat</span><span class="o">!</span><span class="p">(</span><span class="n">env</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;OUT_DIR&quot;</span><span class="p">),</span> <span class="s">&quot;/main.rs&quot;</span><span class="p">));</span>
</span></code></pre></td></tr></table></div></figure>


<p>And finally the <code>main.rss</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">fn</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">s</span> <span class="o">=</span> <span class="n">hello_world</span><span class="o">!</span><span class="p">();</span>
</span><span class='line'>    <span class="nb">println</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;{}&quot;</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>One limitiation you can see above is that we unfortunately can&rsquo;t compose our
macros with the Rust macros is that <code>syntex</code> currently has no awareness of the
Rust macros, and since macros are parsed outside-in, we have to leave the
tokens inside a macro like <code>println!()</code> untouched.</p>

<hr />

<p>That&rsquo;s <code>syntex</code>. There is a bunch of more work left to be done in <code>syntex</code>
to make it really useable. There&rsquo;s also a lot of work in Rust and Cargo that
would help it be really effective:</p>

<ul>
<li>We need a way to inform Rust that this block of code is actually coming from
a different file than the one it&rsquo;s processing. This is roughly equivalent to
  the <a href="https://gcc.gnu.org/onlinedocs/cpp/Line-Control.html">#line</a> macros in
<code>C</code>.</li>
<li>We could upstream the &ldquo;ignore unknown macros&rdquo; patch to minimize
changes to <code>libsyntax</code>.</li>
<li>It would be nice if we could allow <code>#[path]</code> to reference an environment
variable. This would be a little cleaner than using <code>include!(...)</code>.</li>
<li>We need a way to extract macros from a crate.</li>
</ul>


<p>On Cargo&rsquo;s side:</p>

<ul>
<li>It would be nice if Cargo could be told to use a generated file as the
<code>main.rs</code>/<code>lib.rs</code>/etc.</li>
<li><code>Cargo.toml</code> could grow a plugin mechanism to remove the need to write a
<code>build.rs</code> script.</li>
</ul>


<p>I&rsquo;m sure there&rsquo;s plenty more that needs to get done! So, please help out!</p>

<p>edit: comments on <a href="https://www.reddit.com/r/rust/comments/2vdzd1/syntex_syntax_extensions_for_rust_10/">reddit</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rewriting Rust Serialization, Part 3.1: Another Performance Digression]]></title>
    <link href="http://erickt.github.io/blog/2014/12/13/performance-digression/"/>
    <updated>2014-12-13T18:35:08-08:00</updated>
    <id>http://erickt.github.io/blog/2014/12/13/performance-digression</id>
    <content type="html"><![CDATA[<p>Wow, home stretch! Here&rsquo;s the rest of the series if you want to catch up:
<a href="http://erickt.github.io/blog/2014/10/28/serialization/">part 1</a>,
<a href="http://erickt.github.io/blog/2014/11/03/performance/">part 2</a>,
<a href="http://erickt.github.io/blog/2014/11/03/performance/">part 2.1</a>,
<a href="http://erickt.github.io/blog/2014/11/03/performance/">part 2.2</a>, and
<a href="http://erickt.github.io/blog/2014/12/13/rewriting-rust-serialization/">part 3</a>.</p>

<p>Overall <code>serde</code>&rsquo;s approach for serialization works out pretty well. One thing I
forgot to include in the last post was that I also have two benchmarks that are
not using <code>serde</code>, but are just safely reading and writing values.  Assuming I
haven&rsquo;t missed anything, they should be the upper limit in performance we can
get out of any serialization framework: Here&rsquo;s
<a href="https://github.com/erickt/rust-serde/blob/master/benches/bench_log.rs#L1021">serialization</a>:</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library                        </th>
<th> serialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> <strong>rust</strong> </td>
<td> <strong>max without string escapes</strong> </td>
<td> <strong>353</strong>              </td>
</tr>
<tr>
<td> c++      </td>
<td> rapidjson                      </td>
<td> 304                  </td>
</tr>
<tr>
<td> <strong>rust</strong> </td>
<td> <strong>max with string escape</strong>     </td>
<td> <strong>234</strong>              </td>
</tr>
<tr>
<td> rust     </td>
<td> serde::json                    </td>
<td> 201                  </td>
</tr>
<tr>
<td> rust     </td>
<td> serialize::json                </td>
<td> 147                  </td>
</tr>
<tr>
<td> go       </td>
<td> ffjson                         </td>
<td> 147                  </td>
</tr>
</tbody>
</table>


<p>So beyond optimizing string escaping, <code>serde::json</code> is only 14% slower than the
zero-cost version and 34% slower than <code>rapidjson</code>.</p>

<p><a href="https://github.com/erickt/rust-serde/blob/master/benches/bench_log.rs#L1613">Deserialization</a>,
on the other hand, still has a ways to go:</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library                         </th>
<th> deserialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> rust     </td>
<td> rapidjson (SAX)                 </td>
<td> 189                    </td>
</tr>
<tr>
<td> c++      </td>
<td> rapidjson (DOM)                 </td>
<td> 162                    </td>
</tr>
<tr>
<td> <strong>rust</strong> </td>
<td> <strong>max with Iterator&lt;u8&gt;</strong> </td>
<td> <strong>152</strong>                </td>
</tr>
<tr>
<td> go       </td>
<td> ffjson                          </td>
<td> 95                     </td>
</tr>
<tr>
<td> <strong>rust</strong> </td>
<td> <strong>max with Reader</strong>             </td>
<td> <strong>78</strong>                 </td>
</tr>
<tr>
<td> rust     </td>
<td> serde::json                     </td>
<td> 73                     </td>
</tr>
<tr>
<td> rust     </td>
<td> serialize::json                 </td>
<td> 24                     </td>
</tr>
</tbody>
</table>


<p>There are a couple interesting things here:</p>

<p>First, <code>serde::json</code> is built upon consuming from an <code>Iterator&lt;u8&gt;</code>, so we&rsquo;re
48% slower than our theoretical max, and 58% slower than <code>rapidjson</code>. It looks
like tagged tokens, while faster than the closures in <code>libserialize</code>, are still
pretty expensive.</p>

<p>Second, <code>ffjson</code> is beating us and they compile dramatically faster too. The
<a href="https://github.com/cloudflare/goser">goser</a> test suite takes about 0.54
seconds to compile, whereas mine takes about 30 seconds at <code>--opt-level=3</code>
(!!). Rust itself is only taking 1.5 seconds, the rest is spent in LLVM. With
no optimization, it compiles &ldquo;only&rdquo; in 5.6 seconds, and is 96% slower.</p>

<p>Third, <code>Reader</code> is a surprisingly expensive trait when dealing with a format
like JSON that need to read a byte at a time. It turns out we&rsquo;re not
<a href="https://github.com/rust-lang/rust/issues/19864">generating great code</a> for
types with padding. aatch has been working on fixing this though.</p>

<hr />

<p>Since I wrote that last section, I did a little more experimentation to try to
figure out why our serialization upper bound is 23% slower than rapidjson. And,
well, maybe I found it?</p>

<table>
<thead>
<tr>
<th>                                </th>
<th> serialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> serde::json with a MyMemWriter </td>
<td> 346                  </td>
</tr>
<tr>
<td> serde::json with a Vec<u8>     </td>
<td> 247                  </td>
</tr>
</tbody>
</table>


<p>All I did with <code>MyMemWriter</code> is copy the <code>Vec::&lt;u8&gt;</code> implementation of <code>Writer</code>
into the local codebase:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">struct</span> <span class="n">MyMemWriter0</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">buf</span><span class="o">:</span> <span class="n">Vec</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span> <span class="n">MyMemWriter0</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">pub</span> <span class="k">fn</span> <span class="n">with_capacity</span><span class="p">(</span><span class="n">cap</span><span class="o">:</span> <span class="kt">uint</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">MyMemWriter0</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">MyMemWriter0</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">buf</span><span class="o">:</span> <span class="n">Vec</span><span class="o">::</span><span class="n">with_capacity</span><span class="p">(</span><span class="n">cap</span><span class="p">)</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span> <span class="nb">Writer</span> <span class="k">for</span> <span class="n">MyMemWriter0</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">write</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">buf</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">io</span><span class="o">::</span><span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">buf</span><span class="p">.</span><span class="n">push_all</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span>
</span><span class='line'>        <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[bench]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">bench_serializer_my_mem_writer0</span><span class="p">(</span><span class="n">b</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">Bencher</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">log</span> <span class="o">=</span> <span class="n">Log</span><span class="o">::</span><span class="n">new</span><span class="p">();</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">json</span> <span class="o">=</span> <span class="n">json</span><span class="o">::</span><span class="n">to_vec</span><span class="p">(</span><span class="o">&amp;</span><span class="n">log</span><span class="p">);</span>
</span><span class='line'>    <span class="n">b</span><span class="p">.</span><span class="n">bytes</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">len</span><span class="p">()</span> <span class="k">as</span> <span class="kt">u64</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">wr</span> <span class="o">=</span> <span class="n">MyMemWriter0</span><span class="o">::</span><span class="n">with_capacity</span><span class="p">(</span><span class="mi">1024</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">b</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="o">||</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">wr</span><span class="p">.</span><span class="n">buf</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="k">mut</span> <span class="n">serializer</span> <span class="o">=</span> <span class="n">json</span><span class="o">::</span><span class="n">Serializer</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="n">wr</span><span class="p">.</span><span class="n">by_ref</span><span class="p">());</span>
</span><span class='line'>        <span class="n">log</span><span class="p">.</span><span class="n">serialize</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="n">serializer</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">_json</span> <span class="o">=</span> <span class="n">serializer</span><span class="p">.</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>    <span class="p">});</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[bench]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">bench_serializer_vec</span><span class="p">(</span><span class="n">b</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">Bencher</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">log</span> <span class="o">=</span> <span class="n">Log</span><span class="o">::</span><span class="n">new</span><span class="p">();</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">json</span> <span class="o">=</span> <span class="n">json</span><span class="o">::</span><span class="n">to_vec</span><span class="p">(</span><span class="o">&amp;</span><span class="n">log</span><span class="p">);</span>
</span><span class='line'>    <span class="n">b</span><span class="p">.</span><span class="n">bytes</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">len</span><span class="p">()</span> <span class="k">as</span> <span class="kt">u64</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">wr</span> <span class="o">=</span> <span class="n">Vec</span><span class="o">::</span><span class="n">with_capacity</span><span class="p">(</span><span class="mi">1024</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">b</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="o">||</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">wr</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="k">mut</span> <span class="n">serializer</span> <span class="o">=</span> <span class="n">json</span><span class="o">::</span><span class="n">Serializer</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="n">wr</span><span class="p">.</span><span class="n">by_ref</span><span class="p">());</span>
</span><span class='line'>        <span class="n">log</span><span class="p">.</span><span class="n">serialize</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="n">serializer</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">_json</span> <span class="o">=</span> <span class="n">serializer</span><span class="p">.</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>    <span class="p">});</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Somehow it&rsquo;s not enough to just mark <code>Vec::write</code> as
<code>#[inline]</code>, having it in the same file gave LLVM enough information to
optimize it&rsquo;s overhead away. Even using <code>#[inline(always)]</code> on <code>Vec::write</code> and
<code>Vec::push_all</code> isn&rsquo;t able to get the same increase, so I&rsquo;m not sure how to
replicate this in the general case.</p>

<p>Also interesting is <code>bench_serializer_slice</code>, which uses <code>BufWriter</code>.</p>

<table>
<thead>
<tr>
<th>                                </th>
<th> serialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> serde::json with a BufWriter   </td>
<td> 342                  </td>
</tr>
</tbody>
</table>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[bench]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">bench_serializer_slice</span><span class="p">(</span><span class="n">b</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">Bencher</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">log</span> <span class="o">=</span> <span class="n">Log</span><span class="o">::</span><span class="n">new</span><span class="p">();</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">json</span> <span class="o">=</span> <span class="n">json</span><span class="o">::</span><span class="n">to_vec</span><span class="p">(</span><span class="o">&amp;</span><span class="n">log</span><span class="p">);</span>
</span><span class='line'>    <span class="n">b</span><span class="p">.</span><span class="n">bytes</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">len</span><span class="p">()</span> <span class="k">as</span> <span class="kt">u64</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">buf</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="p">..</span> <span class="mi">1024</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">b</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="o">||</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">for</span> <span class="n">item</span> <span class="k">in</span> <span class="n">buf</span><span class="p">.</span><span class="n">iter_mut</span><span class="p">(){</span> <span class="o">*</span><span class="n">item</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span>
</span><span class='line'>        <span class="kd">let</span> <span class="k">mut</span> <span class="n">wr</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">io</span><span class="o">::</span><span class="n">BufWriter</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="n">buf</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="k">mut</span> <span class="n">serializer</span> <span class="o">=</span> <span class="n">json</span><span class="o">::</span><span class="n">Serializer</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="n">wr</span><span class="p">.</span><span class="n">by_ref</span><span class="p">());</span>
</span><span class='line'>        <span class="n">log</span><span class="p">.</span><span class="n">serialize</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="n">serializer</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">_json</span> <span class="o">=</span> <span class="n">serializer</span><span class="p">.</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>    <span class="p">});</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<hr />

<p>Another digression. Since I wrote the above, aatch has put out some PRs that
should help speed up enums.
<a href="https://github.com/rust-lang/rust/pull/19898">19898</a> and
<a href="https://github.com/rust-lang/rust/pull/20060">#20060</a> and was able to optimize
the padding out of enums and fix an issue with returns generating bad code. In
my <a href="https://github.com/rust-lang/rust/issues/19864">bug from earlier</a>
his patches were able to speed up my benchmark returning an
<code>Result&lt;(), IoError&gt;</code> from running at 40MB/s to 88MB/s. However, if we&rsquo;re able
to reduce <code>IoError</code> down to a word, we get the performance up to 730MB/s! We
also might get enum compression, so a type like <code>Result&lt;(), IoError&gt;</code> then
would speed up to 1200MB/s! I think going in this direction is going to really
help speed things up.</p>

<hr />

<p>That was taking a while, so until next time!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rewriting Rust Serialization, Part 3: Introducing Serde]]></title>
    <link href="http://erickt.github.io/blog/2014/12/13/rewriting-rust-serialization/"/>
    <updated>2014-12-13T14:40:18-08:00</updated>
    <id>http://erickt.github.io/blog/2014/12/13/rewriting-rust-serialization</id>
    <content type="html"><![CDATA[<p>There&rsquo;s been a long digression over the past month
(<a href="http://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/">possible kernel bugs</a>,
<a href="http://erickt.github.io/blog/2014/11/22/benchmarking-is-confusing/">benchmarking Writers</a>,
and
<a href="https://github.com/rust-lang/rust/pull/19574">don&rsquo;t believe in magic, folks</a>), but I&rsquo;m back
into serialization. Woo! Here&rsquo;s
<a href="http://erickt.github.io/blog/2014/10/28/serialization/">part 1</a>
<a href="http://erickt.github.io/blog/2014/11/03/performance/">part 2</a>,
<a href="http://erickt.github.io/blog/2014/11/03/performance/">part 2.1</a>, and
<a href="http://erickt.github.io/blog/2014/11/03/performance/">part 2.2</a> if you need
to catch up.</p>

<p>So <code>libserialize</code> has some pretty serious downsides. It&rsquo;s slow, it&rsquo;s got this
weird recursive closure thing going on, and it can&rsquo;t even represent enum types
like a <code>serialize::json::Json</code>. We need a new solution, and while I was at it,
we ended up with two: <a href="https://github.com/erickt/rust-serde">serde</a> and
<a href="https://github.com/erickt/rust-serde/tree/master/serde2">serde2</a>. Both are
different approaches to trying to address these problems. The biggest one being
the type representation problem.</p>

<h2>Serde Version 1</h2>

<h3>Deserialization</h3>

<p>I want to start with deserialization first, as that&rsquo;s really the interesting
bit. To repeat myself a little bit from
<a href="https://erickt.github.io/blog/2014/10/28/serialization/">part 1</a>,
here is a generic json <code>Value</code> enum:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">enum</span> <span class="n">Value</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">I64</span><span class="p">(</span><span class="kt">i64</span><span class="p">),</span>
</span><span class='line'>    <span class="n">U64</span><span class="p">(</span><span class="kt">u64</span><span class="p">),</span>
</span><span class='line'>    <span class="n">F64</span><span class="p">(</span><span class="kt">f64</span><span class="p">),</span>
</span><span class='line'>    <span class="n">String</span><span class="p">(</span><span class="n">String</span><span class="p">),</span>
</span><span class='line'>    <span class="n">Boolean</span><span class="p">(</span><span class="kt">bool</span><span class="p">),</span>
</span><span class='line'>    <span class="n">Array</span><span class="p">(</span><span class="n">Vec</span><span class="o">&lt;</span><span class="n">Value</span><span class="o">&gt;</span><span class="p">),</span>
</span><span class='line'>    <span class="n">Object</span><span class="p">(</span><span class="n">TreeMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">Value</span><span class="o">&gt;</span><span class="p">),</span>
</span><span class='line'>    <span class="n">Null</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>To deserialize a string like <code>[1, true]</code> into
<code>Array(vec![I64(1), Boolean(true)])</code>, we need to peek at one character ahead
(ignoring whitespace) in order to discover what is the type of the next value.
We then can use that knowledge to pick the right variant, and parse the next
value correctly. While I haven&rsquo;t formally studied this stuff, I believe this
can be more formally stated as <code>Value</code> requires at least a LL(1) grammar,
but since <code>libserialize</code> supports no lookahead, so at most it can handle LL(0)
grammars.</p>

<p>Since I was thinking of this problem in terms of grammars, I wanted to take a
page out of their book and implement generic deserialization in this style.
<code>serde::de::Deserializer</code>s are then an <code>Iterator&lt;serde::de::Token&gt;</code> lexer that
produces a token stream, and <code>serde::de::Deserialize</code>s are a parser that
consumes this stream to produce a value. Here&rsquo;s <code>serde::de::Token</code>, which can
represent nearly all the rust types:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">enum</span> <span class="n">Token</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">Null</span><span class="p">,</span>
</span><span class='line'>    <span class="nb">Bool</span><span class="p">(</span><span class="kt">bool</span><span class="p">),</span>
</span><span class='line'>    <span class="nb">Int</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span>
</span><span class='line'>    <span class="n">I8</span><span class="p">(</span><span class="kt">i8</span><span class="p">),</span>
</span><span class='line'>    <span class="n">I16</span><span class="p">(</span><span class="kt">i16</span><span class="p">),</span>
</span><span class='line'>    <span class="n">I32</span><span class="p">(</span><span class="kt">i32</span><span class="p">),</span>
</span><span class='line'>    <span class="n">I64</span><span class="p">(</span><span class="kt">i64</span><span class="p">),</span>
</span><span class='line'>    <span class="n">Uint</span><span class="p">(</span><span class="kt">uint</span><span class="p">),</span>
</span><span class='line'>    <span class="n">U8</span><span class="p">(</span><span class="kt">u8</span><span class="p">),</span>
</span><span class='line'>    <span class="n">U16</span><span class="p">(</span><span class="kt">u16</span><span class="p">),</span>
</span><span class='line'>    <span class="n">U32</span><span class="p">(</span><span class="kt">u32</span><span class="p">),</span>
</span><span class='line'>    <span class="n">U64</span><span class="p">(</span><span class="kt">u64</span><span class="p">),</span>
</span><span class='line'>    <span class="n">F32</span><span class="p">(</span><span class="kt">f32</span><span class="p">),</span>
</span><span class='line'>    <span class="n">F64</span><span class="p">(</span><span class="kt">f64</span><span class="p">),</span>
</span><span class='line'>    <span class="nb">Char</span><span class="p">(</span><span class="n">char</span><span class="p">),</span>
</span><span class='line'>    <span class="nb">Str</span><span class="p">(</span><span class="o">&amp;</span><span class="n">&#39;static</span> <span class="kt">str</span><span class="p">),</span>
</span><span class='line'>    <span class="n">String</span><span class="p">(</span><span class="n">String</span><span class="p">),</span>
</span><span class='line'>
</span><span class='line'>    <span class="nb">Option</span><span class="p">(</span><span class="kt">bool</span><span class="p">),</span>     <span class="c1">// true if the option has a value</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">TupleStart</span><span class="p">(</span><span class="kt">uint</span><span class="p">),</span> <span class="c1">// estimate of the number of values</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">StructStart</span><span class="p">(</span>
</span><span class='line'>        <span class="o">&amp;</span><span class="n">&#39;static</span> <span class="kt">str</span><span class="p">,</span> <span class="c1">// the struct name</span>
</span><span class='line'>        <span class="kt">uint</span><span class="p">,</span>         <span class="c1">// estimate of the number of (string, value) pairs</span>
</span><span class='line'>    <span class="p">),</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">EnumStart</span><span class="p">(</span>
</span><span class='line'>        <span class="o">&amp;</span><span class="n">&#39;static</span> <span class="kt">str</span><span class="p">,</span> <span class="c1">// the enum name</span>
</span><span class='line'>        <span class="o">&amp;</span><span class="n">&#39;static</span> <span class="kt">str</span><span class="p">,</span> <span class="c1">// the variant name</span>
</span><span class='line'>        <span class="kt">uint</span>          <span class="c1">// estimate of the number of values</span>
</span><span class='line'>    <span class="p">),</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">SeqStart</span><span class="p">(</span><span class="kt">uint</span><span class="p">),</span> <span class="c1">// number of values</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">MapStart</span><span class="p">(</span><span class="kt">uint</span><span class="p">),</span> <span class="c1">// number of (value, value) pairs</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">End</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The <code>serde::de::Deserialize</code> stream must generate tokens that follow this
grammar:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='antlr'><span class='line'><span class="nl">value</span><span class="w"> </span><span class="p">::</span><span class="o">=</span><span class="w"> </span><span class="no">Null</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="o">|</span><span class="w"> </span><span class="no">Bool</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="o">|</span><span class="w"> </span><span class="no">Int</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="o">|</span><span class="w"> </span><span class="o">...</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="o">|</span><span class="w"> </span><span class="nv">option</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="o">|</span><span class="w"> </span><span class="nv">tuple</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="o">|</span><span class="w"> </span><span class="nv">struct</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="o">|</span><span class="w"> </span><span class="nv">enum</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="o">|</span><span class="w"> </span><span class="nv">sequence</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="o">|</span><span class="w"> </span><span class="nv">map</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="p">;</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="nl">option</span><span class="w"> </span><span class="p">::</span><span class="o">=</span><span class="w"> </span><span class="no">Option</span><span class="w"> </span><span class="nv">value</span><span class="w"></span>
</span><span class='line'><span class="w">         </span><span class="o">|</span><span class="w"> </span><span class="no">Option</span><span class="w"></span>
</span><span class='line'><span class="w">         </span><span class="p">;</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="nl">tuple</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="no">TupleStart</span><span class="w"> </span><span class="nv">value</span><span class="o">*</span><span class="w"> </span><span class="no">End</span><span class="p">;</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="nl">struct</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="no">StructStart</span><span class="w"> </span><span class="o">(</span><span class="no">Str</span><span class="w"> </span><span class="nv">value</span><span class="o">)*</span><span class="w"> </span><span class="no">End</span><span class="p">;</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="nl">enum</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="no">EnumStart</span><span class="w"> </span><span class="nv">value</span><span class="o">*</span><span class="w"> </span><span class="no">End</span><span class="p">;</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="nl">sequence</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="no">SeqStart</span><span class="w"> </span><span class="nv">value</span><span class="o">*</span><span class="w"> </span><span class="no">End</span><span class="p">;</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="nl">map</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="no">MapStart</span><span class="w"> </span><span class="o">(</span><span class="nv">value</span><span class="w"> </span><span class="nv">value</span><span class="o">)*</span><span class="w"> </span><span class="no">End</span><span class="p">;</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>


<p>For performance reasons, there is no separator in the compound grammar.</p>

<p>Finishing up this section are the actual traits, <code>Deserialize</code> and <code>Deserializer</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Deserialize</span><span class="o">&lt;</span><span class="n">D</span><span class="o">:</span> <span class="n">Deserializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">deserialize</span><span class="p">(</span><span class="n">d</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">D</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">token</span> <span class="o">=</span> <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">expect_token</span><span class="p">());</span>
</span><span class='line'>        <span class="n">Deserialize</span><span class="o">::</span><span class="n">deserialize_token</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">token</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">deserialize_token</span><span class="p">(</span><span class="n">d</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">D</span><span class="p">,</span> <span class="n">token</span><span class="o">:</span> <span class="n">Token</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Self</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Deserializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;:</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="nb">Result</span><span class="o">&lt;</span><span class="n">Token</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="c-Doc">/// Called when a `Deserialize` expected more tokens, but the</span>
</span><span class='line'>    <span class="c-Doc">/// `Deserializer` was empty.</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">end_of_stream_error</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="c-Doc">/// Called when a `Deserializer` was unable to properly parse the stream.</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">syntax_error</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="o">:</span> <span class="n">Token</span><span class="p">,</span> <span class="n">expected</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;static</span> <span class="p">[</span><span class="n">TokenKind</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="c-Doc">/// Called when a named structure or enum got a name that it didn&#39;t expect.</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">unexpected_name_error</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="o">:</span> <span class="n">Token</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="c-Doc">/// Called when a value was unable to be coerced into another value.</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">conversion_error</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="o">:</span> <span class="n">Token</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">E</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="c-Doc">/// Called when a `Deserialize` structure did not deserialize a field</span>
</span><span class='line'>    <span class="c-Doc">/// named `field`.</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">missing_field</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">T</span><span class="o">:</span> <span class="n">Deserialize</span><span class="o">&lt;</span><span class="n">Self</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;static</span> <span class="kt">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="c-Doc">/// Called when a `Deserialize` has decided to not consume this token.</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">ignore_field</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">_token</span><span class="o">:</span> <span class="n">Token</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">_</span><span class="o">:</span> <span class="n">IgnoreTokens</span> <span class="o">=</span> <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">Deserialize</span><span class="o">::</span><span class="n">deserialize</span><span class="p">(</span><span class="bp">self</span><span class="p">));</span>
</span><span class='line'>        <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">expect_token</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Token</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">next</span><span class="p">().</span><span class="n">unwrap_or_else</span><span class="p">(</span><span class="o">||</span> <span class="nb">Err</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">end_of_stream_error</span><span class="p">()))</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The <code>Deserialize</code> trait is kept pretty slim, and is how lookahead is
implemented. <code>Deserializer</code> is an enhanced <code>Iterator&lt;Result&lt;Token, E&gt;&gt;</code>, with
many helpful default methods. Here are them in action. First we&rsquo;ll start with
what&rsquo;s probably the simplest <code>Deserializer</code>, which just wraps a <code>Vec&lt;Token&gt;</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">enum</span> <span class="n">Error</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">EndOfStream</span><span class="p">,</span>
</span><span class='line'>    <span class="n">SyntaxError</span><span class="p">(</span><span class="n">Vec</span><span class="o">&lt;</span><span class="n">TokenKind</span><span class="o">&gt;</span><span class="p">),</span>
</span><span class='line'>    <span class="n">UnexpectedName</span><span class="p">,</span>
</span><span class='line'>    <span class="n">ConversionError</span><span class="p">,</span>
</span><span class='line'>    <span class="n">MissingField</span><span class="p">(</span><span class="o">&amp;</span><span class="n">&#39;static</span> <span class="kt">str</span><span class="p">),</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">struct</span> <span class="n">TokenDeserializer</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">tokens</span><span class="o">:</span> <span class="n">Iter</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">:</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Token</span><span class="o">&gt;&gt;</span> <span class="n">TokenDeserializer</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">new</span><span class="p">(</span><span class="n">tokens</span><span class="o">:</span> <span class="n">Iter</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">TokenDeserializer</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">TokenDeserializer</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">tokens</span><span class="o">:</span> <span class="n">tokens</span><span class="p">,</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">:</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Token</span><span class="o">&gt;&gt;</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="nb">Result</span><span class="o">&lt;</span><span class="n">Token</span><span class="p">,</span> <span class="n">Error</span><span class="o">&gt;&gt;</span> <span class="k">for</span> <span class="n">TokenDeserializer</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">next</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">option</span><span class="o">::</span><span class="nb">Option</span><span class="o">&lt;</span><span class="nb">Result</span><span class="o">&lt;</span><span class="n">Token</span><span class="p">,</span> <span class="n">Error</span><span class="o">&gt;&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">tokens</span><span class="p">.</span><span class="n">next</span><span class="p">().</span><span class="n">map</span><span class="p">(</span><span class="o">|</span><span class="n">token</span><span class="o">|</span> <span class="nb">Ok</span><span class="p">(</span><span class="n">token</span><span class="p">))</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">:</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Token</span><span class="o">&gt;&gt;</span> <span class="n">Deserializer</span><span class="o">&lt;</span><span class="n">Error</span><span class="o">&gt;</span> <span class="k">for</span> <span class="n">TokenDeserializer</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">end_of_stream_error</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Error</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">Error</span><span class="o">::</span><span class="n">EndOfStream</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">syntax_error</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">_token</span><span class="o">:</span> <span class="n">Token</span><span class="p">,</span> <span class="n">expected</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="n">TokenKind</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">Error</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">Error</span><span class="o">::</span><span class="n">SyntaxError</span><span class="p">(</span><span class="n">expected</span><span class="p">.</span><span class="n">to_vec</span><span class="p">())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">unexpected_name_error</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">_token</span><span class="o">:</span> <span class="n">Token</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Error</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">Error</span><span class="o">::</span><span class="n">UnexpectedName</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">conversion_error</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">_token</span><span class="o">:</span> <span class="n">Token</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Error</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">Error</span><span class="o">::</span><span class="n">ConversionError</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">missing_field</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">T</span><span class="o">:</span> <span class="n">Deserialize</span><span class="o">&lt;</span><span class="n">TokenDeserializer</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">Error</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;static</span> <span class="kt">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="nb">Err</span><span class="p">(</span><span class="n">Error</span><span class="o">::</span><span class="n">MissingField</span><span class="p">(</span><span class="n">field</span><span class="p">))</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Overall it should be pretty straight forward. As usual, error handling makes
things a bit noisier, but hopefully it&rsquo;s not too onerous. Next is a
<code>Deserialize</code> for <code>bool</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="n">D</span><span class="o">:</span> <span class="n">Deserializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="n">Deserialize</span><span class="o">&lt;</span><span class="n">D</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="k">for</span> <span class="kt">bool</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">deserialize_token</span><span class="p">(</span><span class="n">d</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">D</span><span class="p">,</span> <span class="n">token</span><span class="o">:</span> <span class="n">Token</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="kt">bool</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">d</span><span class="p">.</span><span class="n">expect_bool</span><span class="p">(</span><span class="n">token</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Deserializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;:</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="nb">Result</span><span class="o">&lt;</span><span class="n">Token</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">expect_bool</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="o">:</span> <span class="n">Token</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="kt">bool</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">match</span> <span class="n">token</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">Token</span><span class="o">::</span><span class="nb">Bool</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nb">Ok</span><span class="p">(</span><span class="n">value</span><span class="p">),</span>
</span><span class='line'>            <span class="n">token</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">static</span> <span class="n">EXPECTED_TOKENS</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;static</span> <span class="p">[</span><span class="n">TokenKind</span><span class="p">]</span> <span class="o">=</span> <span class="o">&amp;</span><span class="p">[</span>
</span><span class='line'>                    <span class="n">TokenKind</span><span class="o">::</span><span class="n">BoolKind</span><span class="p">,</span>
</span><span class='line'>                <span class="p">];</span>
</span><span class='line'>                <span class="nb">Err</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">syntax_error</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="n">EXPECTED_TOKENS</span><span class="p">))</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Simple! Sequences are a bit more tricky. Here&rsquo;s <code>Deserialize</code> a <code>Vec&lt;T&gt;</code>. We
use a helper adaptor <code>SeqDeserializer</code> to deserialize from all types that
implement <code>FromIterator</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span><span class="o">&lt;</span>
</span><span class='line'>    <span class="n">D</span><span class="o">:</span> <span class="n">Deserializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'>    <span class="n">E</span><span class="p">,</span>
</span><span class='line'>    <span class="n">T</span><span class="o">:</span> <span class="n">Deserialize</span><span class="o">&lt;</span><span class="n">D</span> <span class="p">,</span><span class="n">E</span><span class="o">&gt;</span>
</span><span class='line'><span class="o">&gt;</span> <span class="n">Deserialize</span><span class="o">&lt;</span><span class="n">D</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="k">for</span> <span class="n">Vec</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">deserialize_token</span><span class="p">(</span><span class="n">d</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">D</span><span class="p">,</span> <span class="n">token</span><span class="o">:</span> <span class="n">Token</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Vec</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">d</span><span class="p">.</span><span class="n">expect_seq</span><span class="p">(</span><span class="n">token</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Deserializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;:</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="nb">Result</span><span class="o">&lt;</span><span class="n">Token</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">expect_seq</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">T</span><span class="o">:</span> <span class="n">Deserialize</span><span class="o">&lt;</span><span class="n">Self</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'>        <span class="n">C</span><span class="o">:</span> <span class="nb">FromIterator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="o">:</span> <span class="n">Token</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">C</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">len</span> <span class="o">=</span> <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">expect_seq_start</span><span class="p">(</span><span class="n">token</span><span class="p">));</span>
</span><span class='line'>        <span class="kd">let</span> <span class="k">mut</span> <span class="n">err</span> <span class="o">=</span> <span class="nb">None</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="n">collection</span><span class="o">:</span> <span class="n">C</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'>            <span class="kd">let</span> <span class="n">d</span> <span class="o">=</span> <span class="n">SeqDeserializer</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">d</span><span class="o">:</span> <span class="bp">self</span><span class="p">,</span>
</span><span class='line'>                <span class="n">len</span><span class="o">:</span> <span class="n">len</span><span class="p">,</span>
</span><span class='line'>                <span class="n">err</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">err</span><span class="p">,</span>
</span><span class='line'>            <span class="p">};</span>
</span><span class='line'>
</span><span class='line'>            <span class="n">d</span><span class="p">.</span><span class="n">collect</span><span class="p">()</span>
</span><span class='line'>        <span class="p">};</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">match</span> <span class="n">err</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Some</span><span class="p">(</span><span class="n">err</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nb">Err</span><span class="p">(</span><span class="n">err</span><span class="p">),</span>
</span><span class='line'>            <span class="nb">None</span> <span class="o">=&gt;</span> <span class="nb">Ok</span><span class="p">(</span><span class="n">collection</span><span class="p">),</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">struct</span> <span class="n">SeqDeserializer</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="p">,</span> <span class="n">D</span><span class="o">:</span> <span class="nl">&#39;a</span><span class="p">,</span> <span class="n">E</span><span class="o">:</span> <span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">d</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="k">mut</span> <span class="n">D</span><span class="p">,</span>
</span><span class='line'>    <span class="n">len</span><span class="o">:</span> <span class="kt">uint</span><span class="p">,</span>
</span><span class='line'>    <span class="n">err</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="k">mut</span> <span class="nb">Option</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span>
</span><span class='line'>    <span class="nl">&#39;a</span><span class="p">,</span>
</span><span class='line'>    <span class="n">D</span><span class="o">:</span> <span class="n">Deserializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'>    <span class="n">E</span><span class="p">,</span>
</span><span class='line'>    <span class="n">T</span><span class="o">:</span> <span class="n">Deserialize</span><span class="o">&lt;</span><span class="n">D</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span>
</span><span class='line'><span class="o">&gt;</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="k">for</span> <span class="n">SeqDeserializer</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="p">,</span> <span class="n">D</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">next</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">option</span><span class="o">::</span><span class="nb">Option</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">match</span> <span class="bp">self</span><span class="p">.</span><span class="n">d</span><span class="p">.</span><span class="n">expect_seq_elt_or_end</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Ok</span><span class="p">(</span><span class="n">next</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="bp">self</span><span class="p">.</span><span class="n">len</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>                <span class="n">next</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="nb">Err</span><span class="p">(</span><span class="n">err</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="o">*</span><span class="bp">self</span><span class="p">.</span><span class="n">err</span> <span class="o">=</span> <span class="nb">Some</span><span class="p">(</span><span class="n">err</span><span class="p">);</span>
</span><span class='line'>                <span class="nb">None</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">size_hint</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="kt">uint</span><span class="p">,</span> <span class="n">option</span><span class="o">::</span><span class="nb">Option</span><span class="o">&lt;</span><span class="kt">uint</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">len</span><span class="p">,</span> <span class="nb">Some</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">len</span><span class="p">))</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Last is a struct deserializer. This relies on a simple state machine in order
to deserialize from out of order maps:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">struct</span> <span class="n">Foo</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">a</span><span class="o">:</span> <span class="p">(),</span>
</span><span class='line'>    <span class="n">b</span><span class="o">:</span> <span class="kt">uint</span><span class="p">,</span>
</span><span class='line'>    <span class="n">c</span><span class="o">:</span> <span class="n">TreeMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="nb">Option</span><span class="o">&lt;</span><span class="n">char</span><span class="o">&gt;&gt;</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span>
</span><span class='line'>    <span class="n">D</span><span class="o">:</span> <span class="n">Deserializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'>    <span class="n">E</span>
</span><span class='line'><span class="o">&gt;</span> <span class="n">Deserialize</span><span class="o">&lt;</span><span class="n">D</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="k">for</span> <span class="n">Foo</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">deserialize_token</span><span class="p">(</span><span class="n">d</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">D</span><span class="p">,</span> <span class="n">token</span><span class="o">:</span> <span class="n">Token</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Foo</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">expect_struct_start</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="s">&quot;Foo&quot;</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="k">mut</span> <span class="n">a</span> <span class="o">=</span> <span class="nb">None</span><span class="p">;</span>
</span><span class='line'>        <span class="kd">let</span> <span class="k">mut</span> <span class="n">b</span> <span class="o">=</span> <span class="nb">None</span><span class="p">;</span>
</span><span class='line'>        <span class="kd">let</span> <span class="k">mut</span> <span class="n">c</span> <span class="o">=</span> <span class="nb">None</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">static</span> <span class="n">FIELDS</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;static</span> <span class="p">[</span><span class="o">&amp;</span><span class="n">&#39;static</span> <span class="kt">str</span><span class="p">]</span> <span class="o">=</span> <span class="o">&amp;</span><span class="p">[</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">loop</span> <span class="p">{</span>
</span><span class='line'>            <span class="kd">let</span> <span class="n">idx</span> <span class="o">=</span> <span class="k">match</span> <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">expect_struct_field_or_end</span><span class="p">(</span><span class="n">FIELDS</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>                <span class="nb">Some</span><span class="p">(</span><span class="n">idx</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="n">idx</span><span class="p">,</span>
</span><span class='line'>                <span class="nb">None</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="k">break</span><span class="p">;</span> <span class="p">}</span>
</span><span class='line'>            <span class="p">};</span>
</span><span class='line'>
</span><span class='line'>            <span class="k">match</span> <span class="n">idx</span> <span class="p">{</span>
</span><span class='line'>                <span class="nb">Some</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="n">a</span> <span class="o">=</span> <span class="nb">Some</span><span class="p">(</span><span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">expect_struct_value</span><span class="p">()));</span> <span class="p">}</span>
</span><span class='line'>                <span class="nb">Some</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="n">b</span> <span class="o">=</span> <span class="nb">Some</span><span class="p">(</span><span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">expect_struct_value</span><span class="p">()));</span> <span class="p">}</span>
</span><span class='line'>                <span class="nb">Some</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="n">c</span> <span class="o">=</span> <span class="nb">Some</span><span class="p">(</span><span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">expect_struct_value</span><span class="p">()));</span> <span class="p">}</span>
</span><span class='line'>                <span class="nb">Some</span><span class="p">(</span><span class="n">_</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="n">unreachable</span><span class="o">!</span><span class="p">(),</span>
</span><span class='line'>                <span class="nb">None</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="kd">let</span> <span class="n">_</span><span class="o">:</span> <span class="n">IgnoreTokens</span> <span class="o">=</span> <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">Deserialize</span><span class="o">::</span><span class="n">deserialize</span><span class="p">(</span><span class="n">d</span><span class="p">));</span> <span class="p">}</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="nb">Ok</span><span class="p">(</span><span class="n">Foo</span> <span class="p">{</span> <span class="n">a</span><span class="o">:</span> <span class="n">a</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(),</span> <span class="n">b</span><span class="o">:</span> <span class="n">b</span><span class="p">.</span><span class="n">unwrap</span><span class="p">(),</span> <span class="n">c</span><span class="o">:</span> <span class="n">c</span><span class="p">.</span><span class="n">unwrap</span><span class="p">()</span> <span class="p">})</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>It&rsquo;s more complicated than <code>libserialize</code>&rsquo;s struct parsing, but it performs
much better because it can handle out of order maps without buffering tokens.</p>

<h3>Serialization</h3>

<p>Serialization&rsquo;s story is a much simpler one. Conceptually
<code>serde::ser::Serializer</code>/<code>serde::ser::Serialize</code> are inspired by the
deserialization story, but we don&rsquo;t need the tagged tokens because we already
know the types. Here are the traits:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Serialize</span><span class="o">&lt;</span><span class="n">S</span><span class="o">:</span> <span class="n">Serializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">S</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Serializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_null</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_bool</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">bool</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_int</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">serialize_i64</span><span class="p">(</span><span class="n">v</span> <span class="k">as</span> <span class="kt">i64</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_i8</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">i8</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">serialize_i64</span><span class="p">(</span><span class="n">v</span> <span class="k">as</span> <span class="kt">i64</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_i16</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">i16</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">serialize_i64</span><span class="p">(</span><span class="n">v</span> <span class="k">as</span> <span class="kt">i64</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_i32</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">i32</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">serialize_i64</span><span class="p">(</span><span class="n">v</span> <span class="k">as</span> <span class="kt">i64</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_i64</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">i64</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_uint</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">uint</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">serialize_u64</span><span class="p">(</span><span class="n">v</span> <span class="k">as</span> <span class="kt">u64</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_u8</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">u8</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">serialize_u64</span><span class="p">(</span><span class="n">v</span> <span class="k">as</span> <span class="kt">u64</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_u16</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">u16</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">serialize_u64</span><span class="p">(</span><span class="n">v</span> <span class="k">as</span> <span class="kt">u64</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_u32</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">u32</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">serialize_u64</span><span class="p">(</span><span class="n">v</span> <span class="k">as</span> <span class="kt">u64</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_u64</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">u64</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_f32</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">f32</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">serialize_f64</span><span class="p">(</span><span class="n">v</span> <span class="k">as</span> <span class="kt">f64</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_f64</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">f64</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_char</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="n">char</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_str</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="o">&amp;</span><span class="kt">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_tuple_start</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">len</span><span class="o">:</span> <span class="kt">uint</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_tuple_elt</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">T</span><span class="o">:</span> <span class="n">Serialize</span><span class="o">&lt;</span><span class="n">Self</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_tuple_end</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_struct_start</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">:</span> <span class="o">&amp;</span><span class="kt">str</span><span class="p">,</span> <span class="n">len</span><span class="o">:</span> <span class="kt">uint</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_struct_elt</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">T</span><span class="o">:</span> <span class="n">Serialize</span><span class="o">&lt;</span><span class="n">Self</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">:</span> <span class="o">&amp;</span><span class="kt">str</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_struct_end</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_enum_start</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">:</span> <span class="o">&amp;</span><span class="kt">str</span><span class="p">,</span> <span class="n">variant</span><span class="o">:</span> <span class="o">&amp;</span><span class="kt">str</span><span class="p">,</span> <span class="n">len</span><span class="o">:</span> <span class="kt">uint</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_enum_elt</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">T</span><span class="o">:</span> <span class="n">Serialize</span><span class="o">&lt;</span><span class="n">Self</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_enum_end</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_option</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">T</span><span class="o">:</span> <span class="n">Serialize</span><span class="o">&lt;</span><span class="n">Self</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="o">&amp;</span><span class="nb">Option</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_seq</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">T</span><span class="o">:</span> <span class="n">Serialize</span><span class="o">&lt;</span><span class="n">Self</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'>        <span class="n">Iter</span><span class="o">:</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">iter</span><span class="o">:</span> <span class="n">Iter</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_map</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">K</span><span class="o">:</span> <span class="n">Serialize</span><span class="o">&lt;</span><span class="n">Self</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">Serialize</span><span class="o">&lt;</span><span class="n">Self</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'>        <span class="n">Iter</span><span class="o">:</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="p">(</span><span class="n">K</span><span class="p">,</span> <span class="n">V</span><span class="p">)</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">iter</span><span class="o">:</span> <span class="n">Iter</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>There are many default methods, so only a handful of implementations need to be
specified. Now lets look at how they are used. Here&rsquo;s a simple
<code>AssertSerializer</code> that I use in my test suite to make sure I&rsquo;m serializing
properly:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">struct</span> <span class="n">AssertSerializer</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">iter</span><span class="o">:</span> <span class="n">Iter</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="p">,</span> <span class="n">Iter</span><span class="o">:</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Token</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;&gt;&gt;</span> <span class="n">AssertSerializer</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">new</span><span class="p">(</span><span class="n">iter</span><span class="o">:</span> <span class="n">Iter</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">AssertSerializer</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">AssertSerializer</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">iter</span><span class="o">:</span> <span class="n">iter</span><span class="p">,</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize</span><span class="o">&lt;</span><span class="nl">&#39;b</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="o">:</span> <span class="n">Token</span><span class="o">&lt;</span><span class="nl">&#39;b</span><span class="o">&gt;</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">t</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">iter</span><span class="p">.</span><span class="n">next</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="n">assert_eq</span><span class="o">!</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">token</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="p">,</span> <span class="n">Iter</span><span class="o">:</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">Token</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;&gt;&gt;</span> <span class="n">Serializer</span><span class="o">&lt;</span><span class="n">Error</span><span class="o">&gt;</span> <span class="k">for</span> <span class="n">AssertSerializer</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_null</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">serialize</span><span class="p">(</span><span class="n">Token</span><span class="o">::</span><span class="n">Null</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_bool</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">bool</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">serialize</span><span class="p">(</span><span class="n">Token</span><span class="o">::</span><span class="nb">Bool</span><span class="p">(</span><span class="n">v</span><span class="p">))</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_int</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="o">:</span> <span class="kt">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">serialize</span><span class="p">(</span><span class="n">Token</span><span class="o">::</span><span class="nb">Int</span><span class="p">(</span><span class="n">v</span><span class="p">))</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Implementing <code>Serialize</code> for values follows the same pattern. Here&rsquo;s <code>bool</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="n">S</span><span class="o">:</span> <span class="n">Serializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="n">Serialize</span><span class="o">&lt;</span><span class="n">S</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="k">for</span> <span class="kt">bool</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">S</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">s</span><span class="p">.</span><span class="n">serialize_bool</span><span class="p">(</span><span class="o">*</span><span class="bp">self</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>Vec&lt;T&gt;</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span><span class="o">&lt;</span>
</span><span class='line'>    <span class="n">S</span><span class="o">:</span> <span class="n">Serializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'>    <span class="n">E</span><span class="p">,</span>
</span><span class='line'>    <span class="n">T</span><span class="o">:</span> <span class="n">Serialize</span><span class="o">&lt;</span><span class="n">S</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span>
</span><span class='line'><span class="o">&gt;</span> <span class="n">Serialize</span><span class="o">&lt;</span><span class="n">S</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="k">for</span> <span class="n">Vec</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">S</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">s</span><span class="p">.</span><span class="n">serialize_seq</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">iter</span><span class="p">())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">Serializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize_seq</span><span class="o">&lt;</span>
</span><span class='line'>        <span class="n">T</span><span class="o">:</span> <span class="n">Serialize</span><span class="o">&lt;</span><span class="n">AssertSerializer</span><span class="o">&lt;</span><span class="n">Iter</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">Error</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'>        <span class="n">SeqIter</span><span class="o">:</span> <span class="nb">Iterator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="k">mut</span> <span class="n">iter</span><span class="o">:</span> <span class="n">SeqIter</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="p">(</span><span class="n">len</span><span class="p">,</span> <span class="n">_</span><span class="p">)</span> <span class="o">=</span> <span class="n">iter</span><span class="p">.</span><span class="n">size_hint</span><span class="p">();</span>
</span><span class='line'>        <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">serialize</span><span class="p">(</span><span class="n">Token</span><span class="o">::</span><span class="n">SeqStart</span><span class="p">(</span><span class="n">len</span><span class="p">)));</span>
</span><span class='line'>        <span class="k">for</span> <span class="n">elt</span> <span class="k">in</span> <span class="n">iter</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">elt</span><span class="p">.</span><span class="n">serialize</span><span class="p">(</span><span class="bp">self</span><span class="p">));</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">serialize</span><span class="p">(</span><span class="n">Token</span><span class="o">::</span><span class="n">SeqEnd</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And structs:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">struct</span> <span class="n">Foo</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">a</span><span class="o">:</span> <span class="p">(),</span>
</span><span class='line'>    <span class="n">b</span><span class="o">:</span> <span class="kt">uint</span><span class="p">,</span>
</span><span class='line'>    <span class="n">c</span><span class="o">:</span> <span class="n">TreeMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="nb">Option</span><span class="o">&lt;</span><span class="n">char</span><span class="o">&gt;&gt;</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span>
</span><span class='line'>  <span class="n">S</span><span class="o">:</span> <span class="n">Serializer</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'>  <span class="n">E</span>
</span><span class='line'><span class="o">&gt;</span> <span class="n">Serialize</span><span class="o">&lt;</span><span class="n">S</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="k">for</span> <span class="n">Foo</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">serialize</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">S</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">serialize_struct_start</span><span class="p">(</span><span class="s">&quot;Foo&quot;</span><span class="p">,</span> <span class="mi">2</span><span class="k">u</span><span class="p">));</span>
</span><span class='line'>        <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">serialize_struct_elt</span><span class="p">(</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">a</span><span class="p">));</span>
</span><span class='line'>        <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">serialize_struct_elt</span><span class="p">(</span><span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">b</span><span class="p">));</span>
</span><span class='line'>        <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">serialize_struct_elt</span><span class="p">(</span><span class="s">&quot;c&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">c</span><span class="p">));</span>
</span><span class='line'>        <span class="n">s</span><span class="p">.</span><span class="n">serialize_struct_end</span><span class="p">()</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Much simpler than deserialization.</p>

<h2>Performance</h2>

<p>So how does it perform? Here&rsquo;s the serialization benchmarks, with yet another
ordering. This time sorted by the performance:</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library         </th>
<th> format                 </th>
<th> serialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> Rust     </td>
<td> capnproto-rust  </td>
<td> Cap&#8217;n Proto (unpacked) </td>
<td> 4349                 </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto    </td>
<td> Cap&#8217;n Proto            </td>
<td> 3824.20              </td>
</tr>
<tr>
<td> Rust     </td>
<td> bincode         </td>
<td> Binary                 </td>
<td> 1020                 </td>
</tr>
<tr>
<td> Go       </td>
<td> gogoprotobuf    </td>
<td> Protocol Buffers       </td>
<td> 596.78               </td>
</tr>
<tr>
<td> Rust     </td>
<td> capnproto-rust  </td>
<td> Cap&#8217;n Proto (packed)   </td>
<td> 583                  </td>
</tr>
<tr>
<td> Rust     </td>
<td> rust-msgpack    </td>
<td> MessagePack            </td>
<td> 397                  </td>
</tr>
<tr>
<td> Rust     </td>
<td> rust-protobuf   </td>
<td> Protocol Buffers       </td>
<td> 357                  </td>
</tr>
<tr>
<td> C++      </td>
<td> rapidjson       </td>
<td> JSON                   </td>
<td> 304                  </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>serde::json</strong> </td>
<td> <strong>JSON</strong>               </td>
<td> <strong>222</strong>              </td>
</tr>
<tr>
<td> Go       </td>
<td> goprotobuf      </td>
<td> Protocol Buffers       </td>
<td> 214.68               </td>
</tr>
<tr>
<td> Go       </td>
<td> ffjson          </td>
<td> JSON                   </td>
<td> 147.37               </td>
</tr>
<tr>
<td> Rust     </td>
<td> serialize::json </td>
<td> JSON                   </td>
<td> 147                  </td>
</tr>
<tr>
<td> Go       </td>
<td> encoding/json   </td>
<td> JSON                   </td>
<td> 80.49                </td>
</tr>
</tbody>
</table>


<p><code>serde::json</code> is doing pretty good! It still has got a ways to go to catch up
to <a href="https://github.com/miloyip/rapidjson">rapidjson</a>, but it&rsquo;s pretty cool it&rsquo;s
beating <a href="https://github.com/golang/protobuf">goprotobuf</a> out of the box :)</p>

<p>Here are the deserialization numbers:</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library         </th>
<th> format                  </th>
<th> deserialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> Rust     </td>
<td> capnproto-rust  </td>
<td> Cap&#8217;n Proto (unpacked)  </td>
<td> 2185                   </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto    </td>
<td> Cap&#8217;n Proto (zero copy) </td>
<td> 1407.95                </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto    </td>
<td> Cap&#8217;n Proto             </td>
<td> 711.77                 </td>
</tr>
<tr>
<td> Rust     </td>
<td> capnproto-rust  </td>
<td> Cap&#8217;n Proto (packed)    </td>
<td> 351                    </td>
</tr>
<tr>
<td> Go       </td>
<td> gogoprotobuf    </td>
<td> Protocol Buffers        </td>
<td> 272.68                 </td>
</tr>
<tr>
<td> C++      </td>
<td> rapidjson       </td>
<td> JSON (sax)              </td>
<td> 189                    </td>
</tr>
<tr>
<td> C++      </td>
<td> rapidjson       </td>
<td> JSON (dom)              </td>
<td> 162                    </td>
</tr>
<tr>
<td> Rust     </td>
<td> rust-msgpack    </td>
<td> MessagePack             </td>
<td> 138                    </td>
</tr>
<tr>
<td> Rust     </td>
<td> rust-protobuf   </td>
<td> Protocol Buffers        </td>
<td> 129                    </td>
</tr>
<tr>
<td> Go       </td>
<td> ffjson          </td>
<td> JSON                    </td>
<td> 95.06                  </td>
</tr>
<tr>
<td> Rust     </td>
<td> bincode         </td>
<td> Binary                  </td>
<td> 80                     </td>
</tr>
<tr>
<td> Go       </td>
<td> goprotobuf      </td>
<td> Protocol Buffers        </td>
<td> 79.78                  </td>
</tr>
<tr>
<td> <strong>Rust</strong> </td>
<td> <strong>serde::json</strong> </td>
<td> <strong>JSON</strong>                </td>
<td> <strong>67</strong>                 </td>
</tr>
<tr>
<td> Rust     </td>
<td> serialize::json </td>
<td> JSON                    </td>
<td> 24                     </td>
</tr>
<tr>
<td> Go       </td>
<td> encoding/json   </td>
<td> JSON                    </td>
<td> 22.79                  </td>
</tr>
</tbody>
</table>


<p>Well on the plus side, <code>serde::json</code> nearly 3 times faster than
<code>libserialize::json</code>. On the downside rapidjson is nearly 3 times faster than
us in it&rsquo;s SAX style parsing. Even the newly added deserialization support in
<a href="https://github.com/pquerna/ffjson">ffjson</a> is 1.4 times faster than us. So we
got more work cut out for us!</p>

<p>Next time, serde2!</p>

<p>PS: I&rsquo;m definitely getting close to the end of my story, and while I have some
better numbers with serde2, nothing is quite putting me in the rapidjson
range. Anyone want to help optimize
<a href="https://github.com/erickt/rust-serde">serde</a>? I would greatly appreciate the help!</p>

<p>PPS: I&rsquo;ve gotten a number of requests for my
<a href="https://github.com/erickt/rust-serialization-benchmarks">serialization benchmarks</a>
to be ported over to other languages and libraries. Especially a C++ version
of Cap&#8217;n Proto. Unfortunately I don&rsquo;t really have the time to do it myself.
Would anyone be up for helping to implement it?</p>

<p>comments on <a href="https://www.reddit.com/r/rust/comments/2p85za/rewriting_rust_serialization_part_3_introducing/">reddit</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using Rust to Make a Safer Interface for Yahoo's Fast MDBM Database]]></title>
    <link href="http://erickt.github.io/blog/2014/12/13/rust-and-mdbm/"/>
    <updated>2014-12-13T11:09:19-08:00</updated>
    <id>http://erickt.github.io/blog/2014/12/13/rust-and-mdbm</id>
    <content type="html"><![CDATA[<p>I&rsquo;m really supposed to be working on my
<a href="http://erickt.github.io/blog/categories/serialization/">serialization series</a>,
 but I just saw a neat new library that was open sourced by Yahoo a couple days
ago called <a href="https://github.com/yahoo/mdbm">MDBM</a> on
<a href="https://news.ycombinator.com/item?id=8732891">Hacker News</a>. I know nothing
about the library, but there are some really neat claims:</p>

<ol>
<li>It&rsquo;s supposed to be fast, and that&rsquo;s always nice.</li>
<li>It&rsquo;s supposed to have a really slim interface.</li>
<li>It&rsquo;s so fast because it&rsquo;s passing around naked pointers to mmapped files,
which is terribly unsafe. Unless you got rust which can prove that those
pointers won&rsquo;t escape :)</li>
</ol>


<p>So I wanted to see how easy it&rsquo;d be to make a Rust binding for the project.
If you want to follow along, first make sure you have
 <a href="http://www.rust-lang.org/install.html">rust installed</a>. Unfortunately it
looks like MDBM only supports Linux and FreeBSD, so I had to build out a Fedora
VM to test this out on. I <em>think</em> this is all you need to build it:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>% git clone https://github.com/yahoo/mdbm
</span><span class='line'>% cd mdbm/redhat
</span><span class='line'>% make
</span><span class='line'>% rpm -Uvh ~/rpmbuild/RPMS/x86_64/mdbm-4.11.1-1.fc21.x86_64.rpm
</span><span class='line'>% rpm -Uvh ~/rpmbuild/RPMS/x86_64/mdbm-devel-4.11.1-1.fc21.x86_64.rpm</span></code></pre></td></tr></table></div></figure>


<p>Unfortunately it&rsquo;s only for linux, and I got a mac, but it turns out there&rsquo;s
plenty I can do to prep while VirtualBox and Fedora 21 download. Lets start out
by creating our project with <a href="https://crates.io">cargo</a>:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>% cargo new mdbm
</span><span class='line'>% cd rust-mdbm</span></code></pre></td></tr></table></div></figure>


<p>(Right now there&rsquo;s no way to have the name be different than the path, so edit
<code>Cargo.toml</code> to rename the project to <code>mdbm</code>. I filed
<a href="https://github.com/rust-lang/cargo/issues/1030">#1030</a> to get that
implemented).</p>

<p>By convention, we put bindgen packages into <code>$name-sys</code>, so make that crate as
well:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>% cargo new --no-git mdbm-sys
</span><span class='line'>% cd mdbm-sys</span></code></pre></td></tr></table></div></figure>


<p>We&rsquo;ve got a really cool tool called
<a href="https://github.com/crabtw/rust-bindgen">bindgen</a>, which uses clang to parse
header files and convert them into an unsafe rust interface. So lets check out
MDBM, and generate a crate to wrap it up in.</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>% cd ../..
</span><span class='line'>% git clone git@github.com:crabtw/rust-bindgen.git
</span><span class='line'>% cd rust-bindgen
</span><span class='line'>% cargo build
</span><span class='line'>% cd ..
</span><span class='line'>% git clone git@github.com:yahoo/mdbm.git
</span><span class='line'>% cd rust-mdbm/mdbm-sys
</span><span class='line'>% DYLD_LIBRARY_PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib \
</span><span class='line'>  ~/rust/rust-bindgen/target/bindgen \
</span><span class='line'>  -lmdbm \
</span><span class='line'>  -o src/lib.rs \
</span><span class='line'>  mdbm/include/mdbm.h</span></code></pre></td></tr></table></div></figure>


<p>Pretty magical. Make sure it builds:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>% cargo build
</span><span class='line'>/Users/erickt/rust-mdbm/mdbm-sys/src/lib.rs:3:21: 3:25 error: failed to resolve. Maybe a missing `extern crate libc`?
</span><span class='line'>/Users/erickt/rust-mdbm/mdbm-sys/src/lib.rs:3 pub type __int8_t = ::libc::c_char;
</span><span class='line'>                                                                  ^~~~
</span><span class='line'>/Users/erickt/rust-mdbm/mdbm-sys/src/lib.rs:3:21: 3:35 error: use of undeclared type name `libc::c_char`
</span><span class='line'>/Users/erickt/rust-mdbm/mdbm-sys/src/lib.rs:3 pub type __int8_t = ::libc::c_char;
</span><span class='line'>                                                                  ^~~~~~~~~~~~~~
</span><span class='line'>/Users/erickt/rust-mdbm/mdbm-sys/src/lib.rs:4:22: 4:26 error: failed to resolve. Maybe a missing `extern crate libc`?
</span><span class='line'>/Users/erickt/rust-mdbm/mdbm-sys/src/lib.rs:4 pub type __uint8_t = ::libc::c_uchar;
</span><span class='line'>                                                                   ^~~~
</span><span class='line'>...</span></code></pre></td></tr></table></div></figure>


<p>Nope! The problem is that we don&rsquo;t have the <code>libc</code> crate imported. We don&rsquo;t
have a convention yet for this, but I like to do is:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>mv src/lib.rs src/ffi.rs</span></code></pre></td></tr></table></div></figure>


<p>And create a <code>src/lib.rs</code> that contains:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">allow</span><span class="p">(</span><span class="n">non_camel_case_types</span><span class="p">)]</span>
</span><span class='line'><span class="err">#</span><span class="o">!</span><span class="p">[</span><span class="n">allow</span><span class="p">(</span><span class="n">non_snake_case</span><span class="p">)]</span>
</span><span class='line'>
</span><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">libc</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">type</span> <span class="n">__builtin_va_list</span> <span class="o">=</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_void</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="n">include</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;ffi.rs&quot;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>This lets me run bindgen later on without mucking up the library. This now
compiles. Next up is our high level interface. Add <code>mdbm-sys</code> to our high level
interface by adding this to the <code>rust-mdbm/Cargo.toml</code> file:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='toml'><span class='line'><span class="p">[</span><span class="n">dependencies</span><span class="p">.</span><span class="n">mdbm-sys</span><span class="p">]</span>
</span><span class='line'><span class="n">path</span> <span class="o">=</span> <span class="s">&quot;mdbm-sys&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>By now I got my VirtualBox setup working, so now to the actual code! Lets start
with a barebones wrapper around the database:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">struct</span> <span class="n">MDBM</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">db</span><span class="o">:</span> <span class="o">*</span><span class="k">mut</span> <span class="n">mdbm_sys</span><span class="o">::</span><span class="n">MDBM</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Next is the constructor and destructor. I&rsquo;m hardcoding things for now and using
IoError, since MDBM appears to log everything to the ERRNO:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span> <span class="n">MDBM</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">pub</span> <span class="k">fn</span> <span class="n">new</span><span class="p">(</span>
</span><span class='line'>        <span class="n">path</span><span class="o">:</span> <span class="o">&amp;</span><span class="nb">Path</span><span class="p">,</span>
</span><span class='line'>        <span class="n">flags</span><span class="o">:</span> <span class="kt">uint</span><span class="p">,</span>
</span><span class='line'>        <span class="n">mode</span><span class="o">:</span> <span class="kt">uint</span><span class="p">,</span>
</span><span class='line'>        <span class="n">psize</span><span class="o">:</span> <span class="kt">uint</span><span class="p">,</span>
</span><span class='line'>        <span class="n">presize</span><span class="o">:</span> <span class="kt">uint</span>
</span><span class='line'>    <span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">MDBM</span><span class="p">,</span> <span class="n">IoError</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>            <span class="kd">let</span> <span class="n">path</span> <span class="o">=</span> <span class="n">path</span><span class="p">.</span><span class="n">to_c_str</span><span class="p">();</span>
</span><span class='line'>            <span class="kd">let</span> <span class="n">db</span> <span class="o">=</span> <span class="n">mdbm_sys</span><span class="o">::</span><span class="n">mdbm_open</span><span class="p">(</span>
</span><span class='line'>                <span class="n">path</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span>
</span><span class='line'>                <span class="n">flags</span> <span class="k">as</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span><span class="p">,</span>
</span><span class='line'>                <span class="n">mode</span> <span class="k">as</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span><span class="p">,</span>
</span><span class='line'>                <span class="n">psize</span> <span class="k">as</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span><span class="p">,</span>
</span><span class='line'>                <span class="n">presize</span> <span class="k">as</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>            <span class="k">if</span> <span class="n">db</span><span class="p">.</span><span class="n">is_null</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>                <span class="nb">Err</span><span class="p">(</span><span class="n">IoError</span><span class="o">::</span><span class="n">last_error</span><span class="p">())</span>
</span><span class='line'>            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>                <span class="nb">Ok</span><span class="p">(</span><span class="n">MDBM</span> <span class="p">{</span> <span class="n">db</span><span class="o">:</span> <span class="n">db</span> <span class="p">})</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span> <span class="nb">Drop</span> <span class="k">for</span> <span class="n">MDBM</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="nb">drop</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">mdbm_sys</span><span class="o">::</span><span class="n">mdbm_sync</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">db</span><span class="p">);</span>
</span><span class='line'>            <span class="n">mdbm_sys</span><span class="o">::</span><span class="n">mdbm_close</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">db</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Pretty straightforward translation of the examples with some hardcoded values
to start out. Next up is a wrapper around MDBM&rsquo;s <code>datum</code> type, which is the
type used for both keys and values. <code>datum</code> is just a simple struct containing
a pointer and length, pretty much analogous to our <code>&amp;[u8]</code> slices. However our
slices are much more powerful because our type system can guarantee that in
safe Rust, these slices can never outlive where they are derived from:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">struct</span> <span class="n">Datum</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">bytes</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="p">[</span><span class="kt">u8</span><span class="p">],</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="n">Datum</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">pub</span> <span class="k">fn</span> <span class="n">new</span><span class="p">(</span><span class="n">bytes</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">Datum</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">Datum</span> <span class="p">{</span> <span class="n">bytes</span><span class="o">:</span> <span class="n">bytes</span> <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">to_raw_datum</span><span class="p">(</span><span class="n">datum</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">Datum</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">mdbm_sys</span><span class="o">::</span><span class="n">datum</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">mdbm_sys</span><span class="o">::</span><span class="n">datum</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">dptr</span><span class="o">:</span> <span class="n">datum</span><span class="p">.</span><span class="n">bytes</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">()</span> <span class="k">as</span> <span class="o">*</span><span class="k">mut</span> <span class="n">_</span><span class="p">,</span>
</span><span class='line'>        <span class="n">dsize</span><span class="o">:</span> <span class="n">datum</span><span class="p">.</span><span class="n">bytes</span><span class="p">.</span><span class="n">len</span><span class="p">()</span> <span class="k">as</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span><span class="p">,</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And for convenience, lets add a <code>AsDatum</code> conversion method:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">trait</span> <span class="n">AsDatum</span> <span class="k">for</span> <span class="nb">Sized</span><span class="o">?</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">as_datum</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">&#39;a</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Datum</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="p">,</span> <span class="nb">Sized</span><span class="o">?</span> <span class="n">T</span><span class="o">:</span> <span class="n">AsDatum</span><span class="o">&gt;</span> <span class="n">AsDatum</span> <span class="k">for</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="n">T</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">as_datum</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">&#39;a</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Datum</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span> <span class="p">(</span><span class="o">**</span><span class="bp">self</span><span class="p">).</span><span class="n">as_datum</span><span class="p">()</span> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span> <span class="n">AsDatum</span> <span class="k">for</span> <span class="p">[</span><span class="kt">u8</span><span class="p">]</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">as_datum</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">&#39;a</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Datum</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">Datum</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span> <span class="n">AsDatum</span> <span class="k">for</span> <span class="kt">str</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">as_datum</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">&#39;a</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Datum</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">as_bytes</span><span class="p">().</span><span class="n">as_datum</span><span class="p">()</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And finally, we got setting and getting a key-value. Setting is pretty
straightforward. The only fun thing is using the <code>AsDatum</code> constraints so we
can do <code>db.set(&amp;"foo", &amp;"bar", 0)</code> instead of
<code>db.set(Datum::new(&amp;"foo".as_slice()), Datum::new("bar".as_slice()), 0)</code>.
we&rsquo;re copying into the database, we don&rsquo;t have to worry about lifetimes yet:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span> <span class="n">MDBM</span> <span class="p">{</span>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'>
</span><span class='line'>    <span class="c-Doc">/// Set a key.</span>
</span><span class='line'>    <span class="k">pub</span> <span class="k">fn</span> <span class="n">set</span><span class="o">&lt;</span><span class="n">K</span><span class="p">,</span> <span class="n">V</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">K</span><span class="p">,</span> <span class="n">value</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">V</span><span class="p">,</span> <span class="n">flags</span><span class="o">:</span> <span class="kt">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">IoError</span><span class="o">&gt;</span> <span class="n">where</span>
</span><span class='line'>        <span class="n">K</span><span class="o">:</span> <span class="n">AsDatum</span><span class="p">,</span>
</span><span class='line'>        <span class="n">V</span><span class="o">:</span> <span class="n">AsDatum</span><span class="p">,</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>            <span class="kd">let</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">mdbm_sys</span><span class="o">::</span><span class="n">mdbm_store</span><span class="p">(</span>
</span><span class='line'>                <span class="bp">self</span><span class="p">.</span><span class="n">db</span><span class="p">,</span>
</span><span class='line'>                <span class="n">to_raw_datum</span><span class="p">(</span><span class="o">&amp;</span><span class="n">key</span><span class="p">.</span><span class="n">as_datum</span><span class="p">()),</span>
</span><span class='line'>                <span class="n">to_raw_datum</span><span class="p">(</span><span class="o">&amp;</span><span class="n">value</span><span class="p">.</span><span class="n">as_datum</span><span class="p">()),</span>
</span><span class='line'>                <span class="n">flags</span> <span class="k">as</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>            <span class="k">if</span> <span class="n">rc</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span> <span class="p">{</span>
</span><span class='line'>                <span class="nb">Err</span><span class="p">(</span><span class="n">IoError</span><span class="o">::</span><span class="n">last_error</span><span class="p">())</span>
</span><span class='line'>            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>                <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">...</span>
</span></code></pre></td></tr></table></div></figure>


<p>MDBM requires the database to be locked in order to get the keys. This os
where things get fun in order to prevent those interior pointers from escaping.
We&rsquo;ll create another wrapper type that manages the lock, and uses RAII to
unlock when we&rsquo;re done. We tie the lifetime of the <code>Lock</code> to the lifetime of
the database and key, which prevents it from outliving either object:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span> <span class="n">MDBM</span> <span class="p">{</span>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'>
</span><span class='line'>    <span class="c-Doc">/// Lock a key.</span>
</span><span class='line'>    <span class="k">pub</span> <span class="k">fn</span> <span class="n">lock</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="p">,</span> <span class="n">K</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">&#39;a</span> <span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="n">K</span><span class="p">,</span> <span class="n">flags</span><span class="o">:</span> <span class="kt">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Lock</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">IoError</span><span class="o">&gt;</span> <span class="n">where</span>
</span><span class='line'>        <span class="n">K</span><span class="o">:</span> <span class="n">AsDatum</span><span class="p">,</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">rc</span> <span class="o">=</span> <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">mdbm_sys</span><span class="o">::</span><span class="n">mdbm_lock_smart</span><span class="p">(</span>
</span><span class='line'>                <span class="bp">self</span><span class="p">.</span><span class="n">db</span><span class="p">,</span>
</span><span class='line'>                <span class="o">&amp;</span><span class="n">to_raw_datum</span><span class="p">(</span><span class="o">&amp;</span><span class="n">key</span><span class="p">.</span><span class="n">as_datum</span><span class="p">()),</span>
</span><span class='line'>                <span class="n">flags</span> <span class="k">as</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span><span class="p">)</span>
</span><span class='line'>        <span class="p">};</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="n">rc</span> <span class="o">==</span> <span class="mi">1</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Ok</span><span class="p">(</span><span class="n">Lock</span> <span class="p">{</span> <span class="n">db</span><span class="o">:</span> <span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="o">:</span> <span class="n">key</span><span class="p">.</span><span class="n">as_datum</span><span class="p">()</span> <span class="p">})</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Err</span><span class="p">(</span><span class="n">IoError</span><span class="o">::</span><span class="n">last_error</span><span class="p">())</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">...</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">pub</span> <span class="k">struct</span> <span class="n">Lock</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">db</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="n">MDBM</span><span class="p">,</span>
</span><span class='line'>    <span class="n">key</span><span class="o">:</span> <span class="n">Datum</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[unsafe_destructor]</span>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="nb">Drop</span> <span class="k">for</span> <span class="n">Lock</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="nb">drop</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>            <span class="kd">let</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">mdbm_sys</span><span class="o">::</span><span class="n">mdbm_unlock_smart</span><span class="p">(</span>
</span><span class='line'>                <span class="bp">self</span><span class="p">.</span><span class="n">db</span><span class="p">.</span><span class="n">db</span><span class="p">,</span>
</span><span class='line'>                <span class="o">&amp;</span><span class="n">to_raw_datum</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">key</span><span class="p">),</span>
</span><span class='line'>                <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>            <span class="n">assert_eq</span><span class="o">!</span><span class="p">(</span><span class="n">rc</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>(Note that I&rsquo;ve heard <code>#[unsafe_destrutor]</code> as used here may become unnecessary
in 1.0).</p>

<p>Finally, let&rsquo;s get our value! Assuming the value exists, we tie the lifetime of
the <code>Lock</code> to the lifetime of the returned <code>&amp;[u8]</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="n">Lock</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="c-Doc">/// Fetch a key.</span>
</span><span class='line'>    <span class="k">pub</span> <span class="k">fn</span> <span class="n">get</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">&#39;a</span> <span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Option</span><span class="o">&lt;&amp;</span><span class="n">&#39;a</span> <span class="p">[</span><span class="kt">u8</span><span class="p">]</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>            <span class="kd">let</span> <span class="n">value</span> <span class="o">=</span> <span class="n">mdbm_sys</span><span class="o">::</span><span class="n">mdbm_fetch</span><span class="p">(</span>
</span><span class='line'>                <span class="bp">self</span><span class="p">.</span><span class="n">db</span><span class="p">.</span><span class="n">db</span><span class="p">,</span>
</span><span class='line'>                <span class="n">to_raw_datum</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">key</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'>            <span class="k">if</span> <span class="n">value</span><span class="p">.</span><span class="n">dptr</span><span class="p">.</span><span class="n">is_null</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>                <span class="nb">None</span>
</span><span class='line'>            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>                <span class="c1">// we want to constrain the ptr to our lifetime.</span>
</span><span class='line'>                <span class="kd">let</span> <span class="n">ptr</span><span class="o">:</span> <span class="o">&amp;*</span><span class="kr">const</span> <span class="kt">u8</span> <span class="o">=</span> <span class="n">mem</span><span class="o">::</span><span class="n">transmute</span><span class="p">(</span><span class="o">&amp;</span><span class="n">value</span><span class="p">.</span><span class="n">dptr</span><span class="p">);</span>
</span><span class='line'>                <span class="nb">Some</span><span class="p">(</span><span class="n">slice</span><span class="o">::</span><span class="n">from_raw_buf</span><span class="p">(</span><span class="n">ptr</span><span class="p">,</span> <span class="n">value</span><span class="p">.</span><span class="n">dsize</span> <span class="k">as</span> <span class="kt">uint</span><span class="p">))</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now to verify it works:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[test]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">test</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">db</span> <span class="o">=</span> <span class="n">MDBM</span><span class="o">::</span><span class="n">new</span><span class="p">(</span>
</span><span class='line'>        <span class="o">&amp;</span><span class="nb">Path</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="s">&quot;test.db&quot;</span><span class="p">),</span>
</span><span class='line'>        <span class="n">super</span><span class="o">::</span><span class="n">MDBM_O_RDWR</span> <span class="o">|</span> <span class="n">super</span><span class="o">::</span><span class="n">MDBM_O_CREAT</span><span class="p">,</span>
</span><span class='line'>        <span class="mo">0o644</span><span class="p">,</span>
</span><span class='line'>        <span class="mi">0</span><span class="p">,</span>
</span><span class='line'>        <span class="mi">0</span>
</span><span class='line'>    <span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">db</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="o">&amp;</span><span class="s">&quot;hello&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="s">&quot;world&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="c1">// key needs to be an lvalue so the lock can hold a reference to</span>
</span><span class='line'>        <span class="c1">// it.</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">key</span> <span class="o">=</span> <span class="s">&quot;hello&quot;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// Lock the key. RAII will unlock it when we exit this scope.</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">value</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="n">lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">key</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">// Convert the value into a string. The lock is still live at this</span>
</span><span class='line'>        <span class="c1">// point.</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">value</span> <span class="o">=</span> <span class="kt">str</span><span class="o">::</span><span class="n">from_utf8</span><span class="p">(</span><span class="n">value</span><span class="p">.</span><span class="n">get</span><span class="p">().</span><span class="n">unwrap</span><span class="p">()).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>        <span class="n">assert_eq</span><span class="o">!</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s">&quot;world&quot;</span><span class="p">);</span>
</span><span class='line'>        <span class="nb">println</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;hello: {}&quot;</span><span class="p">,</span> <span class="n">value</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Which when run with <code>cargo test</code>, produces:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'>   <span class="n">Compiling</span> <span class="n">rust</span><span class="o">-</span><span class="n">mdbm</span> <span class="n">v0</span><span class="p">.</span><span class="mf">0.1</span> <span class="p">(</span><span class="n">file</span><span class="o">:</span><span class="c-Doc">///home/erickt/Projects/rust-mdbm)</span>
</span><span class='line'>     <span class="n">Running</span> <span class="n">target</span><span class="o">/</span><span class="n">rust</span><span class="o">-</span><span class="n">mdbm</span><span class="o">-</span><span class="mi">98</span><span class="n">b81ab156dc1e5f</span>
</span><span class='line'>
</span><span class='line'><span class="n">running</span> <span class="mi">1</span> <span class="n">test</span>
</span><span class='line'><span class="n">test</span> <span class="n">tests</span><span class="o">::</span><span class="n">test_set_get</span> <span class="p">...</span> <span class="n">ok</span>
</span><span class='line'>
</span><span class='line'><span class="n">test</span> <span class="n">result</span><span class="o">:</span> <span class="n">ok</span><span class="p">.</span> <span class="mi">1</span> <span class="n">passed</span><span class="p">;</span> <span class="mi">0</span> <span class="n">failed</span><span class="p">;</span> <span class="mi">0</span> <span class="n">ignored</span><span class="p">;</span> <span class="mi">0</span> <span class="n">measured</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">Doc</span><span class="o">-</span><span class="n">tests</span> <span class="n">rust</span><span class="o">-</span><span class="n">mdbm</span>
</span><span class='line'>
</span><span class='line'><span class="n">running</span> <span class="mi">0</span> <span class="n">tests</span>
</span><span class='line'>
</span><span class='line'><span class="n">test</span> <span class="n">result</span><span class="o">:</span> <span class="n">ok</span><span class="p">.</span> <span class="mi">0</span> <span class="n">passed</span><span class="p">;</span> <span class="mi">0</span> <span class="n">failed</span><span class="p">;</span> <span class="mi">0</span> <span class="n">ignored</span><span class="p">;</span> <span class="mi">0</span> <span class="n">measured</span>
</span></code></pre></td></tr></table></div></figure>


<p>Next we want to make sure invalid behavior is a compile-time error. First, make
sure we don&rsquo;t leak the keys:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[test]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">test_keys_cannot_escape</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">db</span> <span class="o">=</span> <span class="n">MDBM</span><span class="o">::</span><span class="n">new</span><span class="p">(</span>
</span><span class='line'>        <span class="o">&amp;</span><span class="nb">Path</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="s">&quot;test.db&quot;</span><span class="p">),</span>
</span><span class='line'>        <span class="n">super</span><span class="o">::</span><span class="n">MDBM_O_RDWR</span> <span class="o">|</span> <span class="n">super</span><span class="o">::</span><span class="n">MDBM_O_CREAT</span><span class="p">,</span>
</span><span class='line'>        <span class="mo">0o644</span><span class="p">,</span>
</span><span class='line'>        <span class="mi">0</span><span class="p">,</span>
</span><span class='line'>        <span class="mi">0</span>
</span><span class='line'>    <span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">db</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="o">&amp;</span><span class="s">&quot;hello&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="s">&quot;world&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="n">_</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">key</span> <span class="o">=</span> <span class="n">vec</span><span class="o">!</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
</span><span class='line'>        <span class="n">db</span><span class="p">.</span><span class="n">lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">key</span><span class="p">.</span><span class="n">as_slice</span><span class="p">(),</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">()</span>
</span><span class='line'>    <span class="p">};</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Which errors with:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">217</span><span class="o">:</span><span class="mi">22</span><span class="o">:</span> <span class="mi">217</span><span class="o">:</span><span class="mi">25</span> <span class="n">error</span><span class="o">:</span> <span class="err">`</span><span class="n">key</span><span class="err">`</span> <span class="n">does</span> <span class="n">not</span> <span class="n">live</span> <span class="n">long</span> <span class="n">enough</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">217</span>             <span class="n">db</span><span class="p">.</span><span class="n">lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">key</span><span class="p">.</span><span class="n">as_slice</span><span class="p">(),</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">()</span>
</span><span class='line'>                                    <span class="o">^~~</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">215</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span> <span class="mi">218</span><span class="o">:</span><span class="mi">10</span> <span class="n">note</span><span class="o">:</span> <span class="n">reference</span> <span class="n">must</span> <span class="kr">be</span> <span class="n">valid</span> <span class="k">for</span> <span class="n">the</span> <span class="n">expression</span> <span class="n">at</span> <span class="mi">215</span><span class="o">:</span><span class="mf">16.</span><span class="p">..</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">215</span>         <span class="kd">let</span> <span class="n">_</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">216</span>             <span class="kd">let</span> <span class="n">key</span> <span class="o">=</span> <span class="n">vec</span><span class="o">!</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">217</span>             <span class="n">db</span><span class="p">.</span><span class="n">lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">key</span><span class="p">.</span><span class="n">as_slice</span><span class="p">(),</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">()</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">218</span>         <span class="p">};</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">215</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span> <span class="mi">218</span><span class="o">:</span><span class="mi">10</span> <span class="n">note</span><span class="o">:</span> <span class="p">...</span><span class="n">but</span> <span class="n">borrowed</span> <span class="n">value</span> <span class="n">is</span> <span class="n">only</span> <span class="n">valid</span> <span class="k">for</span> <span class="n">the</span> <span class="n">block</span> <span class="n">at</span> <span class="mi">215</span><span class="o">:</span><span class="mi">16</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">215</span>         <span class="kd">let</span> <span class="n">_</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">216</span>             <span class="kd">let</span> <span class="n">key</span> <span class="o">=</span> <span class="n">vec</span><span class="o">!</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">217</span>             <span class="n">db</span><span class="p">.</span><span class="n">lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">key</span><span class="p">.</span><span class="n">as_slice</span><span class="p">(),</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">()</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">218</span>         <span class="p">};</span>
</span><span class='line'><span class="n">error</span><span class="o">:</span> <span class="n">aborting</span> <span class="n">due</span> <span class="n">to</span> <span class="n">previous</span> <span class="n">error</span>
</span></code></pre></td></tr></table></div></figure>


<p>And confirm the value doesn&rsquo;t leak either:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[test]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">test_values_cannot_escape</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">db</span> <span class="o">=</span> <span class="n">MDBM</span><span class="o">::</span><span class="n">new</span><span class="p">(</span>
</span><span class='line'>        <span class="o">&amp;</span><span class="nb">Path</span><span class="o">::</span><span class="n">new</span><span class="p">(</span><span class="s">&quot;test.db&quot;</span><span class="p">),</span>
</span><span class='line'>        <span class="n">super</span><span class="o">::</span><span class="n">MDBM_O_RDWR</span> <span class="o">|</span> <span class="n">super</span><span class="o">::</span><span class="n">MDBM_O_CREAT</span><span class="p">,</span>
</span><span class='line'>        <span class="mo">0o644</span><span class="p">,</span>
</span><span class='line'>        <span class="mi">0</span><span class="p">,</span>
</span><span class='line'>        <span class="mi">0</span>
</span><span class='line'>    <span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="n">_</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">db</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="o">&amp;</span><span class="s">&quot;hello&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="s">&quot;world&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="n">key</span> <span class="o">=</span> <span class="s">&quot;hello&quot;</span><span class="p">;</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">value</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="n">lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">key</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>        <span class="kt">str</span><span class="o">::</span><span class="n">from_utf8</span><span class="p">(</span><span class="n">value</span><span class="p">.</span><span class="n">get</span><span class="p">().</span><span class="n">unwrap</span><span class="p">()).</span><span class="n">unwrap</span><span class="p">()</span>
</span><span class='line'>    <span class="p">};</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Which errors with:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">237</span><span class="o">:</span><span class="mi">34</span><span class="o">:</span> <span class="mi">237</span><span class="o">:</span><span class="mi">37</span> <span class="n">error</span><span class="o">:</span> <span class="err">`</span><span class="n">key</span><span class="err">`</span> <span class="n">does</span> <span class="n">not</span> <span class="n">live</span> <span class="n">long</span> <span class="n">enough</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">237</span>             <span class="kd">let</span> <span class="n">value</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="n">lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">key</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>                                                <span class="o">^~~</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">233</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span> <span class="mi">239</span><span class="o">:</span><span class="mi">10</span> <span class="n">note</span><span class="o">:</span> <span class="n">reference</span> <span class="n">must</span> <span class="kr">be</span> <span class="n">valid</span> <span class="k">for</span> <span class="n">the</span> <span class="n">expression</span> <span class="n">at</span> <span class="mi">233</span><span class="o">:</span><span class="mf">16.</span><span class="p">..</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">233</span>         <span class="kd">let</span> <span class="n">_</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">234</span>             <span class="n">db</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="o">&amp;</span><span class="s">&quot;hello&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="s">&quot;world&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">235</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">236</span>             <span class="kd">let</span> <span class="n">key</span> <span class="o">=</span> <span class="s">&quot;hello&quot;</span><span class="p">;</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">237</span>             <span class="kd">let</span> <span class="n">value</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="n">lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">key</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">238</span>             <span class="kt">str</span><span class="o">::</span><span class="n">from_utf8</span><span class="p">(</span><span class="n">value</span><span class="p">.</span><span class="n">get</span><span class="p">().</span><span class="n">unwrap</span><span class="p">()).</span><span class="n">unwrap</span><span class="p">()</span>
</span><span class='line'>               <span class="p">...</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">233</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span> <span class="mi">239</span><span class="o">:</span><span class="mi">10</span> <span class="n">note</span><span class="o">:</span> <span class="p">...</span><span class="n">but</span> <span class="n">borrowed</span> <span class="n">value</span> <span class="n">is</span> <span class="n">only</span> <span class="n">valid</span> <span class="k">for</span> <span class="n">the</span> <span class="n">block</span> <span class="n">at</span> <span class="mi">233</span><span class="o">:</span><span class="mi">16</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">233</span>         <span class="kd">let</span> <span class="n">_</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">234</span>             <span class="n">db</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="o">&amp;</span><span class="s">&quot;hello&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="s">&quot;world&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">235</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">236</span>             <span class="kd">let</span> <span class="n">key</span> <span class="o">=</span> <span class="s">&quot;hello&quot;</span><span class="p">;</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">237</span>             <span class="kd">let</span> <span class="n">value</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="n">lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">key</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">238</span>             <span class="kt">str</span><span class="o">::</span><span class="n">from_utf8</span><span class="p">(</span><span class="n">value</span><span class="p">.</span><span class="n">get</span><span class="p">().</span><span class="n">unwrap</span><span class="p">()).</span><span class="n">unwrap</span><span class="p">()</span>
</span><span class='line'>               <span class="p">...</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">238</span><span class="o">:</span><span class="mi">28</span><span class="o">:</span> <span class="mi">238</span><span class="o">:</span><span class="mi">33</span> <span class="n">error</span><span class="o">:</span> <span class="err">`</span><span class="n">value</span><span class="err">`</span> <span class="n">does</span> <span class="n">not</span> <span class="n">live</span> <span class="n">long</span> <span class="n">enough</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">238</span>             <span class="kt">str</span><span class="o">::</span><span class="n">from_utf8</span><span class="p">(</span><span class="n">value</span><span class="p">.</span><span class="n">get</span><span class="p">().</span><span class="n">unwrap</span><span class="p">()).</span><span class="n">unwrap</span><span class="p">()</span>
</span><span class='line'>                                          <span class="o">^~~~~</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">233</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span> <span class="mi">239</span><span class="o">:</span><span class="mi">10</span> <span class="n">note</span><span class="o">:</span> <span class="n">reference</span> <span class="n">must</span> <span class="kr">be</span> <span class="n">valid</span> <span class="k">for</span> <span class="n">the</span> <span class="n">expression</span> <span class="n">at</span> <span class="mi">233</span><span class="o">:</span><span class="mf">16.</span><span class="p">..</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">233</span>         <span class="kd">let</span> <span class="n">_</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">234</span>             <span class="n">db</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="o">&amp;</span><span class="s">&quot;hello&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="s">&quot;world&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">235</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">236</span>             <span class="kd">let</span> <span class="n">key</span> <span class="o">=</span> <span class="s">&quot;hello&quot;</span><span class="p">;</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">237</span>             <span class="kd">let</span> <span class="n">value</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="n">lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">key</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">238</span>             <span class="kt">str</span><span class="o">::</span><span class="n">from_utf8</span><span class="p">(</span><span class="n">value</span><span class="p">.</span><span class="n">get</span><span class="p">().</span><span class="n">unwrap</span><span class="p">()).</span><span class="n">unwrap</span><span class="p">()</span>
</span><span class='line'>               <span class="p">...</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">233</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span> <span class="mi">239</span><span class="o">:</span><span class="mi">10</span> <span class="n">note</span><span class="o">:</span> <span class="p">...</span><span class="n">but</span> <span class="n">borrowed</span> <span class="n">value</span> <span class="n">is</span> <span class="n">only</span> <span class="n">valid</span> <span class="k">for</span> <span class="n">the</span> <span class="n">block</span> <span class="n">at</span> <span class="mi">233</span><span class="o">:</span><span class="mi">16</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">233</span>         <span class="kd">let</span> <span class="n">_</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">234</span>             <span class="n">db</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="o">&amp;</span><span class="s">&quot;hello&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="s">&quot;world&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">235</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">236</span>             <span class="kd">let</span> <span class="n">key</span> <span class="o">=</span> <span class="s">&quot;hello&quot;</span><span class="p">;</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">237</span>             <span class="kd">let</span> <span class="n">value</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="n">lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">key</span><span class="p">,</span> <span class="mi">0</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'><span class="n">src</span><span class="o">/</span><span class="n">lib</span><span class="p">.</span><span class="n">rs</span><span class="o">:</span><span class="mi">238</span>             <span class="kt">str</span><span class="o">::</span><span class="n">from_utf8</span><span class="p">(</span><span class="n">value</span><span class="p">.</span><span class="n">get</span><span class="p">().</span><span class="n">unwrap</span><span class="p">()).</span><span class="n">unwrap</span><span class="p">()</span>
</span><span class='line'>                                                     <span class="p">...</span>
</span></code></pre></td></tr></table></div></figure>


<p>Success! Not too bad for 2 hours of work. Baring bugs, this <code>mdbm</code>
library should perform at roughly the same speed as the C library, but
eliminate many very painful bug opportunities that require tools like Valgrind
to debug.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Benchmarking Is Confusing in Low Level Rust]]></title>
    <link href="http://erickt.github.io/blog/2014/11/22/benchmarking-is-confusing/"/>
    <updated>2014-11-22T12:10:29-08:00</updated>
    <id>http://erickt.github.io/blog/2014/11/22/benchmarking-is-confusing</id>
    <content type="html"><![CDATA[<p>Edit: you can find all the code in this post
<a href="https://github.com/erickt/rust-serialization-benchmarks/blob/master/rust/src/writer.rs">here</a>,
and I filed <a href="https://github.com/rust-lang/rust/issues/19281">19281</a> for the
regression I mentioned at the end of the post.</p>

<hr />

<p>Low level benchmarking is confusing and non-intuitive.</p>

<p>The end.</p>

<hr />

<p>Or not. Whatever. So I&rsquo;m trying to get my
implement-<code>Reader</code>-and-<code>Writer</code>-for-<code>&amp;[u8]</code> type PR
<a href="https://github.com/rust-lang/rust/pull/18980">#18980</a> landed. But
<a href="https://github.com/rust-lang/rust/pull/18980#issuecomment-63925495">Steven Fackler</a>
obnixously and correctly pointed out that this won&rsquo;t play that nicely with the
new <code>Reader</code> and <code>Writer</code> implementation for <code>Vec&lt;u8&gt;</code>. Grumble grumble. And then
<a href="https://github.com/rust-lang/rust/pull/18980#issuecomment-63927659">Alex Crichton</a>
had the gall to mention that a <code>Writer</code> for <code>mut &amp;[u8]</code> also probably won&rsquo;t be
that common either. Sure, he&rsquo;s write and all, but but I got it working without
needing an index! That means that the <code>&amp;mut [u8]</code> <code>Writer</code> only needs 2
pointers instead of <code>BufWriter</code>&rsquo;s three, so it just has to be faster! Well,
doesn&rsquo;t it?</p>

<p>Stupid benchmarks.</p>

<p>I got to say it&rsquo;s pretty addicting writing micro-benchmarks. It&rsquo;s a lot of fun
seeing how sensitive low-level code can be to just the smallest of tweaks. It&rsquo;s
also really annoying when you write something you think is pretty neat, then
you find it&rsquo;s chock-full of false dependencies between cache lines, or other
mean things CPUs like to impose on poor programmers.</p>

<p>Anyway, to start lets look at what should be the fastest way to write to a
buffer. Completely unsafely with no checks.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">unsafe</span> <span class="k">fn</span> <span class="n">do_copy_nonoverlapping_memory</span><span class="p">(</span>
</span><span class='line'>  <span class="k">mut</span> <span class="n">dst</span><span class="o">:</span> <span class="o">*</span><span class="k">mut</span> <span class="kt">u8</span><span class="p">,</span>
</span><span class='line'>  <span class="n">src</span><span class="o">:</span> <span class="o">*</span><span class="kr">const</span> <span class="kt">u8</span><span class="p">,</span>
</span><span class='line'>  <span class="n">len</span><span class="o">:</span> <span class="kt">uint</span><span class="p">,</span>
</span><span class='line'>  <span class="n">batches</span><span class="o">:</span> <span class="kt">uint</span>
</span><span class='line'><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">for</span> <span class="n">_</span> <span class="k">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">batches</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">ptr</span><span class="o">::</span><span class="n">copy_nonoverlapping_memory</span><span class="p">(</span><span class="n">dst</span><span class="p">,</span> <span class="n">src</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
</span><span class='line'>        <span class="n">dst</span> <span class="o">=</span> <span class="n">dst</span><span class="p">.</span><span class="n">offset</span><span class="p">(</span><span class="n">len</span> <span class="k">as</span> <span class="kt">int</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[test]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">test_copy_nonoverlapping_memory</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">dst</span> <span class="o">=</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="p">[</span><span class="mi">0_</span><span class="k">u8</span><span class="p">,</span> <span class="p">..</span> <span class="n">BATCHES</span> <span class="o">*</span> <span class="n">SRC_LEN</span><span class="p">];</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">src</span> <span class="o">=</span> <span class="o">&amp;</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="p">..</span> <span class="n">SRC_LEN</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">do_copy_nonoverlapping_memory</span><span class="p">(</span>
</span><span class='line'>            <span class="n">dst</span><span class="p">.</span><span class="n">as_mut_ptr</span><span class="p">(),</span>
</span><span class='line'>            <span class="n">src</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span>
</span><span class='line'>            <span class="n">src</span><span class="p">.</span><span class="n">len</span><span class="p">(),</span>
</span><span class='line'>            <span class="n">BATCHES</span>
</span><span class='line'>        <span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="n">assert</span><span class="o">!</span><span class="p">(</span><span class="n">dst</span><span class="p">.</span><span class="n">iter</span><span class="p">().</span><span class="n">all</span><span class="p">(</span><span class="o">|</span><span class="n">c</span><span class="o">|</span> <span class="o">*</span><span class="n">c</span> <span class="o">==</span> <span class="mi">1</span><span class="p">));</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>With <code>SRC_LEN=4</code> and <code>BATCHES=128</code>, we get this. For fun I added the new
<code>libtest</code> from <a href="https://github.com/rust-lang/rust/pull/19233">#19233</a> that will
hopefully land soon. I also added also ran variations that explicitly inlined
and not inlined the inner function:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">test</span> <span class="n">bench_copy_nonoverlapping_memory</span>               <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">50</span> <span class="o">|</span>   <span class="p">[</span><span class="o">-***</span><span class="err">#</span><span class="o">**------</span><span class="p">]</span>                        <span class="o">|</span> <span class="mi">200</span><span class="o">:</span>        <span class="mi">72</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">45</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">bench_copy_nonoverlapping_memory_inline_always</span> <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">50</span> <span class="o">|</span>       <span class="p">[</span><span class="o">---***</span><span class="err">#</span><span class="o">****************----------</span><span class="p">]</span><span class="o">|</span> <span class="mi">100</span><span class="o">:</span>        <span class="mi">65</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">39</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">bench_copy_nonoverlapping_memory_inline_never</span>  <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">500</span> <span class="o">|</span>      <span class="p">[</span><span class="o">------********</span><span class="err">#</span><span class="o">*********-------</span><span class="p">]</span> <span class="o">|</span> <span class="mi">1000</span><span class="o">:</span>       <span class="mi">747</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">393</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>So overall it does quite well. Now lets compare with the code I wrote:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="nb">Writer</span> <span class="k">for</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="k">mut</span> <span class="p">[</span><span class="kt">u8</span><span class="p">]</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">write</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">src</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="n">is_empty</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="nb">Err</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">standard_error</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">EndOfFile</span><span class="p">));</span> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="n">dst_len</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">len</span><span class="p">();</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">src_len</span> <span class="o">=</span> <span class="n">src</span><span class="p">.</span><span class="n">len</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="n">write_len</span> <span class="o">=</span> <span class="n">min</span><span class="p">(</span><span class="n">dst_len</span><span class="p">,</span> <span class="n">src_len</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="n">slice</span><span class="o">::</span><span class="n">bytes</span><span class="o">::</span><span class="n">copy_memory</span><span class="p">(</span><span class="o">*</span><span class="bp">self</span><span class="p">,</span> <span class="n">src</span><span class="p">.</span><span class="n">slice_to</span><span class="p">(</span><span class="n">write_len</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>            <span class="o">*</span><span class="bp">self</span> <span class="o">=</span> <span class="n">mem</span><span class="o">::</span><span class="n">transmute</span><span class="p">(</span><span class="n">raw</span><span class="o">::</span><span class="n">Slice</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">data</span><span class="o">:</span> <span class="bp">self</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">().</span><span class="n">offset</span><span class="p">(</span><span class="n">write_len</span> <span class="k">as</span> <span class="kt">int</span><span class="p">),</span>
</span><span class='line'>                <span class="n">len</span><span class="o">:</span> <span class="n">dst_len</span> <span class="o">-</span> <span class="n">write_len</span><span class="p">,</span>
</span><span class='line'>            <span class="p">});</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="n">src_len</span> <span class="o">&gt;</span> <span class="n">dst_len</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Err</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">standard_error</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">ShortWrite</span><span class="p">(</span><span class="n">write_len</span><span class="p">)))</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And. Well. It didn&rsquo;t do that well.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_slice_writer</span>                             <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">500</span> <span class="o">|</span>   <span class="p">[</span><span class="o">------**</span><span class="err">#</span><span class="o">**--</span><span class="p">]</span>                      <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>       <span class="mi">920</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">448</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_slice_writer_inline_always</span>               <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">600</span> <span class="o">|</span> <span class="p">[</span><span class="o">-**</span><span class="err">#</span><span class="o">*****---</span><span class="p">]</span>                         <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>       <span class="mi">711</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">405</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_slice_writer_inline_never</span>                <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">600</span> <span class="o">|</span>   <span class="p">[</span><span class="o">-***</span><span class="err">#</span><span class="o">******---</span><span class="p">]</span>                     <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>       <span class="mi">838</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">474</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Wow. That&rsquo;s pretty bad compared to the ideal.</p>

<p>Crud. So not only did I add an implementation that&rsquo;s probably going to not work
with <code>write!</code> and now it turns out the performance is pretty terrible. Inlining
isn&rsquo;t helping like it did in the unsafe case. So how&rsquo;s
<a href="https://github.com/rust-lang/rust/blob/master/src/libstd/io/mem.rs#L219">std::io::BufWriter</a>
compare?</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">struct</span> <span class="n">BufWriter</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">buf</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">&#39;a</span> <span class="k">mut</span> <span class="p">[</span><span class="kt">u8</span><span class="p">],</span>
</span><span class='line'>    <span class="n">pos</span><span class="o">:</span> <span class="kt">uint</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="nb">Writer</span> <span class="k">for</span> <span class="n">BufWriter</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">write</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">buf</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="c1">// return an error if the entire write does not fit in the buffer</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">cap</span> <span class="o">=</span> <span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="n">pos</span> <span class="o">&gt;=</span> <span class="bp">self</span><span class="p">.</span><span class="n">buf</span><span class="p">.</span><span class="n">len</span><span class="p">()</span> <span class="p">{</span> <span class="mi">0</span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="bp">self</span><span class="p">.</span><span class="n">buf</span><span class="p">.</span><span class="n">len</span><span class="p">()</span> <span class="o">-</span> <span class="bp">self</span><span class="p">.</span><span class="n">pos</span> <span class="p">};</span>
</span><span class='line'>        <span class="k">if</span> <span class="n">buf</span><span class="p">.</span><span class="n">len</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">cap</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">return</span> <span class="nb">Err</span><span class="p">(</span><span class="n">IoError</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">kind</span><span class="o">:</span> <span class="n">io</span><span class="o">::</span><span class="n">OtherIoError</span><span class="p">,</span>
</span><span class='line'>                <span class="n">desc</span><span class="o">:</span> <span class="s">&quot;Trying to write past end of buffer&quot;</span><span class="p">,</span>
</span><span class='line'>                <span class="n">detail</span><span class="o">:</span> <span class="nb">None</span>
</span><span class='line'>            <span class="p">})</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="n">slice</span><span class="o">::</span><span class="n">bytes</span><span class="o">::</span><span class="n">copy_memory</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">buf</span><span class="p">[</span><span class="k">mut</span> <span class="bp">self</span><span class="p">.</span><span class="n">pos</span><span class="p">..],</span> <span class="n">buf</span><span class="p">);</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">pos</span> <span class="o">+=</span> <span class="n">buf</span><span class="p">.</span><span class="n">len</span><span class="p">();</span>
</span><span class='line'>        <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Here&rsquo;s how it does:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_std_buf_writer</span>                           <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">50</span> <span class="o">|</span>     <span class="p">[</span><span class="o">------**************</span><span class="err">#</span><span class="o">******-------</span><span class="p">]</span> <span class="o">|</span> <span class="mi">100</span><span class="o">:</span>        <span class="mi">79</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">40</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_std_buf_writer_inline_always</span>             <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">50</span> <span class="o">|</span>    <span class="p">[</span><span class="o">-----************</span><span class="err">#</span><span class="o">*********-------</span><span class="p">]</span>  <span class="o">|</span> <span class="mi">100</span><span class="o">:</span>        <span class="mi">75</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">40</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_std_buf_writer_inline_never</span>              <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">600</span> <span class="o">|</span>   <span class="p">[</span><span class="err">#</span><span class="o">****-----</span><span class="p">]</span>                         <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>       <span class="mi">705</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">337</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>That&rsquo;s just cruel. The optimization gods obviously hate me. So I started
playing with a lot of
<a href="https://github.com/erickt/rust-serialization-benchmarks/blob/master/rust/src/writer.rs">variations</a>
(it&rsquo;s my yeah yeah it&rsquo;s my serialization benchmark suite, I&rsquo;m planning on
making it more general purpose. Besides it&rsquo;s my suite and I can do whatever I
want with it, so there):</p>

<ul>
<li>(BufWriter0): Turning this <code>Writer</code> into a struct wrapper shouldn&rsquo;t do anything, and it
didn&rsquo;t.</li>
<li>(BufWriter1): There&rsquo;s error handling, does removing it help? Nope!</li>
<li>(BufWriter5): There&rsquo;s an implied branch in <code>let write_len = min(dst_len, src_len)</code>. We can
turn that into the branch-predictor-friendly:</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="kd">let</span> <span class="n">x</span> <span class="o">=</span> <span class="p">(</span><span class="n">dst_len</span> <span class="o">&lt;</span> <span class="n">buf_len</span><span class="p">)</span> <span class="k">as</span> <span class="kt">uint</span><span class="p">;</span>
</span><span class='line'><span class="kd">let</span> <span class="n">write_len</span> <span class="o">=</span> <span class="n">dst_len</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="n">src_len</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">x</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>Doesn&rsquo;t matter, still performs the same.</p>

<ul>
<li>(BufWriter2): Fine then, optimization gods! Lets remove the branch altogether and just
  always advance the slice <code>src.len()</code> bytes! Damn the safety! That, of course,
works. I can hear them giggle.</li>
<li>(BufWriter3): Maybe, just maybe there&rsquo;s something weird going on with
  inlining across crates? Lets copy <code>std::io::BufWriter</code> and make sure that
  it&rsquo;s still nearly optimal. It still is.</li>
<li>(BufWriter6): Technically the <code>min(dst_len, src_len)</code> is a bounds check, so
we could switch from the bounds checked <code>std.slice::bytes::copy_memory</code> to
  the unsafe <code>std::ptr::copy_nonoverlapping_memory</code>, but that also doesn&rsquo;t
  help.</li>
<li>(BufWriter7): Might as well and apply the last trick to <code>std::io::BufWriter</code>,
  and it does shave a couple nanoseconds off. It might be worth pushing it
  upstream:</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_7</span>                             <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">50</span> <span class="o">|</span>   <span class="p">[</span><span class="o">-*</span><span class="err">#</span><span class="o">********--------------------------</span><span class="p">]</span><span class="o">|</span> <span class="mi">100</span><span class="o">:</span>        <span class="mi">55</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">44</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_7_inline_always</span>               <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">50</span> <span class="o">|</span>     <span class="p">[</span><span class="o">---------********</span><span class="err">#</span><span class="o">*********-------</span><span class="p">]</span> <span class="o">|</span> <span class="mi">100</span><span class="o">:</span>        <span class="mi">76</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">39</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_7_inline_never</span>                <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">600</span> <span class="o">|</span>   <span class="p">[</span><span class="o">-***</span><span class="err">#</span><span class="o">****----</span><span class="p">]</span>                      <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>       <span class="mi">828</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">417</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>(BufWriter4): While I&rsquo;m using one less <code>uint</code> than <code>std::io::BufWriter</code>, I&rsquo;m
  doing two writes to advance my slice, one to advance the pointer, and one to
  shrink the length. <code>std::io::BufWriter</code> only has to advance it&rsquo;s <code>pos</code> index.
  But in this case if instead of treating the slice as a <code>(ptr, length)</code>, we
  can convert it into a <code>(start_ptr, end_ptr)</code>, where <code>start_ptr=ptr</code>, and
  <code>end_ptr=ptr+length</code>. This works! Ish:</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_4</span>                             <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">80</span> <span class="o">|</span>   <span class="p">[</span><span class="o">--******</span><span class="err">#</span><span class="o">*******-----</span><span class="p">]</span>                <span class="o">|</span> <span class="mi">200</span><span class="o">:</span>       <span class="mi">109</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">59</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_4_inline_always</span>               <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">100</span> <span class="o">|</span>     <span class="p">[</span><span class="o">------***</span><span class="err">#</span><span class="o">******---</span><span class="p">]</span>               <span class="o">|</span> <span class="mi">200</span><span class="o">:</span>       <span class="mi">133</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">44</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_4_inline_never</span>                <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">500</span> <span class="o">|</span>      <span class="p">[</span><span class="o">-----***********</span><span class="err">#</span><span class="o">***********----</span><span class="p">]</span><span class="o">|</span> <span class="mi">1000</span><span class="o">:</span>       <span class="mi">778</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">426</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>I know when I&rsquo;m defeated. Oh well. I guess I can at least update
<code>std::io::BufWriter</code> to support the new error handling approach:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="n">MyWriter</span> <span class="k">for</span> <span class="n">BufWriter10</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">my_write</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">src</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">dst_len</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">dst</span><span class="p">.</span><span class="n">len</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="n">pos</span> <span class="o">==</span> <span class="n">dst_len</span> <span class="p">{</span> <span class="k">return</span> <span class="nb">Err</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">standard_error</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">EndOfFile</span><span class="p">));</span> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="n">src_len</span> <span class="o">=</span> <span class="n">src</span><span class="p">.</span><span class="n">len</span><span class="p">();</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">cap</span> <span class="o">=</span> <span class="n">dst_len</span> <span class="o">-</span> <span class="bp">self</span><span class="p">.</span><span class="n">pos</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="n">write_len</span> <span class="o">=</span> <span class="n">min</span><span class="p">(</span><span class="n">cap</span><span class="p">,</span> <span class="n">src_len</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="n">slice</span><span class="o">::</span><span class="n">bytes</span><span class="o">::</span><span class="n">copy_memory</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">dst</span><span class="p">[</span><span class="k">mut</span> <span class="bp">self</span><span class="p">.</span><span class="n">pos</span><span class="p">..],</span> <span class="n">src</span><span class="p">[..</span><span class="n">write_len</span><span class="p">]);</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="n">src_len</span> <span class="o">&gt;</span> <span class="n">dst_len</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">return</span> <span class="nb">Err</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">standard_error</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">ShortWrite</span><span class="p">(</span><span class="n">write_len</span><span class="p">)));</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">pos</span> <span class="o">+=</span> <span class="n">write_len</span><span class="p">;</span>
</span><span class='line'>        <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>How&rsquo;s it do?</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_10</span>                            <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">600</span> <span class="o">|</span> <span class="p">[</span><span class="o">----**</span><span class="err">#</span><span class="o">***--</span><span class="p">]</span>                         <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>       <span class="mi">841</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">413</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_10_inline_always</span>              <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">600</span> <span class="o">|</span>  <span class="p">[</span><span class="o">----**</span><span class="err">#</span><span class="o">***--</span><span class="p">]</span>                        <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>       <span class="mi">872</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">387</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_10_inline_never</span>               <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">600</span> <span class="o">|</span>   <span class="p">[</span><span class="o">--******</span><span class="err">#</span><span class="o">**---</span><span class="p">]</span>                     <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>       <span class="mi">960</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">486</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Grumble grumble. It turns out that if we tweak the <code>copy_memory</code> line to:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'>    <span class="n">slice</span><span class="o">::</span><span class="n">bytes</span><span class="o">::</span><span class="n">copy_memory</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">dst</span><span class="p">[</span><span class="k">mut</span> <span class="bp">self</span><span class="p">.</span><span class="n">pos</span><span class="p">..],</span> <span class="n">src</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>It shaves 674 nanoseconds off the run:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_10</span>                            <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">200</span> <span class="o">|</span><span class="p">[</span><span class="o">---***</span><span class="err">#</span><span class="o">************------------</span><span class="p">]</span>        <span class="o">|</span> <span class="mi">400</span><span class="o">:</span>       <span class="mi">230</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">147</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_10_inline_always</span>              <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">200</span> <span class="o">|</span>   <span class="p">[</span><span class="o">-----********</span><span class="err">#</span><span class="o">*******------</span><span class="p">]</span>         <span class="o">|</span> <span class="mi">400</span><span class="o">:</span>       <span class="mi">280</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">128</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_10_inline_never</span>               <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">600</span> <span class="o">|</span>   <span class="p">[</span><span class="o">--***</span><span class="err">#</span><span class="o">****----</span><span class="p">]</span>                     <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>       <span class="mi">885</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">475</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>But still no where near where we need to be. That suggests though that always
cutting down the <code>src</code>, which triggers another bounds check has some measurable
impact. So maybe I should only shrink the <code>src</code> slice when we know it needs to
be shrunk?</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="n">MyWriter</span> <span class="k">for</span> <span class="n">BufWriter11</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">my_write</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">src</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">dst</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">dst</span><span class="p">[</span><span class="k">mut</span> <span class="bp">self</span><span class="p">.</span><span class="n">pos</span><span class="p">..];</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">dst_len</span> <span class="o">=</span> <span class="n">dst</span><span class="p">.</span><span class="n">len</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="n">dst_len</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">return</span> <span class="nb">Err</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">standard_error</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">EndOfFile</span><span class="p">));</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="n">src_len</span> <span class="o">=</span> <span class="n">src</span><span class="p">.</span><span class="n">len</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="n">dst_len</span> <span class="o">&gt;=</span> <span class="n">src_len</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">ptr</span><span class="o">::</span><span class="n">copy_nonoverlapping_memory</span><span class="p">(</span>
</span><span class='line'>                    <span class="n">dst</span><span class="p">.</span><span class="n">as_mut_ptr</span><span class="p">(),</span>
</span><span class='line'>                    <span class="n">src</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span>
</span><span class='line'>                    <span class="n">src_len</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>              <span class="bp">self</span><span class="p">.</span><span class="n">pos</span> <span class="o">+=</span> <span class="n">src_len</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>            <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">ptr</span><span class="o">::</span><span class="n">copy_nonoverlapping_memory</span><span class="p">(</span>
</span><span class='line'>                    <span class="n">dst</span><span class="p">.</span><span class="n">as_mut_ptr</span><span class="p">(),</span>
</span><span class='line'>                    <span class="n">src</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span>
</span><span class='line'>                    <span class="n">dst_len</span><span class="p">);</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>              <span class="bp">self</span><span class="p">.</span><span class="n">pos</span> <span class="o">+=</span> <span class="n">dst_len</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>            <span class="nb">Err</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">standard_error</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">ShortWrite</span><span class="p">(</span><span class="n">dst_len</span><span class="p">)))</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Lets see how it failed this time&hellip;</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_11</span>                            <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">60</span> <span class="o">|</span>      <span class="p">[</span><span class="o">------********</span><span class="err">#</span><span class="o">*********-----</span><span class="p">]</span>     <span class="o">|</span> <span class="mi">100</span><span class="o">:</span>        <span class="mi">79</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">28</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_11_inline_always</span>              <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">60</span> <span class="o">|</span><span class="p">[</span><span class="o">-------******</span><span class="err">#</span><span class="o">*************-----------</span><span class="p">]</span>  <span class="o">|</span> <span class="mi">100</span><span class="o">:</span>        <span class="mi">72</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">35</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_11_inline_never</span>               <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">600</span> <span class="o">|</span>  <span class="p">[</span><span class="o">--***</span><span class="err">#</span><span class="o">***----</span><span class="p">]</span>                       <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>       <span class="mi">835</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">423</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>No way. That actually worked?! That&rsquo;s awesome! I&rsquo;ll carve that out into another
PR. Maybe it&rsquo;ll work for my original version that doesn&rsquo;t use a <code>pos</code>?</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="n">MyWriter</span> <span class="k">for</span> <span class="n">BufWriter12</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">my_write</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">src</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">dst_len</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">dst</span><span class="p">.</span><span class="n">len</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="n">dst_len</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">return</span> <span class="nb">Err</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">standard_error</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">EndOfFile</span><span class="p">));</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="n">src_len</span> <span class="o">=</span> <span class="n">src</span><span class="p">.</span><span class="n">len</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="n">dst_len</span> <span class="o">&gt;=</span> <span class="n">src_len</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">ptr</span><span class="o">::</span><span class="n">copy_nonoverlapping_memory</span><span class="p">(</span>
</span><span class='line'>                    <span class="bp">self</span><span class="p">.</span><span class="n">dst</span><span class="p">.</span><span class="n">as_mut_ptr</span><span class="p">(),</span>
</span><span class='line'>                    <span class="n">src</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span>
</span><span class='line'>                    <span class="n">src_len</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>                <span class="bp">self</span><span class="p">.</span><span class="n">dst</span> <span class="o">=</span> <span class="n">mem</span><span class="o">::</span><span class="n">transmute</span><span class="p">(</span><span class="n">raw</span><span class="o">::</span><span class="n">Slice</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">data</span><span class="o">:</span> <span class="bp">self</span><span class="p">.</span><span class="n">dst</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">().</span><span class="n">offset</span><span class="p">(</span><span class="n">src_len</span> <span class="k">as</span> <span class="kt">int</span><span class="p">),</span>
</span><span class='line'>                    <span class="n">len</span><span class="o">:</span> <span class="n">dst_len</span> <span class="o">-</span> <span class="n">src_len</span><span class="p">,</span>
</span><span class='line'>                <span class="p">});</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>            <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">ptr</span><span class="o">::</span><span class="n">copy_nonoverlapping_memory</span><span class="p">(</span>
</span><span class='line'>                    <span class="bp">self</span><span class="p">.</span><span class="n">dst</span><span class="p">.</span><span class="n">as_mut_ptr</span><span class="p">(),</span>
</span><span class='line'>                    <span class="n">src</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span>
</span><span class='line'>                    <span class="n">dst_len</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>                <span class="bp">self</span><span class="p">.</span><span class="n">dst</span> <span class="o">=</span> <span class="n">mem</span><span class="o">::</span><span class="n">transmute</span><span class="p">(</span><span class="n">raw</span><span class="o">::</span><span class="n">Slice</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">data</span><span class="o">:</span> <span class="bp">self</span><span class="p">.</span><span class="n">dst</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">().</span><span class="n">offset</span><span class="p">(</span><span class="n">dst_len</span> <span class="k">as</span> <span class="kt">int</span><span class="p">),</span>
</span><span class='line'>                    <span class="n">len</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
</span><span class='line'>                <span class="p">});</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>            <span class="nb">Err</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">standard_error</span><span class="p">(</span><span class="n">io</span><span class="o">::</span><span class="n">ShortWrite</span><span class="p">(</span><span class="n">dst_len</span><span class="p">)))</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And yep, just as fast!</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_12</span>                            <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">50</span> <span class="o">|</span><span class="p">[</span><span class="o">**</span><span class="err">#</span><span class="o">*----------------------------------</span><span class="p">]</span>   <span class="o">|</span> <span class="mi">80</span><span class="o">:</span>        <span class="mi">51</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">26</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_12_inline_always</span>              <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">50</span> <span class="o">|</span>  <span class="p">[</span><span class="o">--------**********</span><span class="err">#</span><span class="o">********------------</span><span class="p">]</span><span class="o">|</span> <span class="mi">90</span><span class="o">:</span>        <span class="mi">69</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">36</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_buf_writer_12_inline_never</span>               <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">800</span> <span class="o">|</span>  <span class="p">[</span><span class="o">---**</span><span class="err">#</span><span class="o">***-</span><span class="p">]</span>                          <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>      <span class="mi">1000</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">263</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>At this point, both solutions are approximately just as fast as the unsafe
<code>ptr::copy_nonoverlapping_memory</code>! So that&rsquo;s awesome. Now would anyone really
care enough about the extra <code>uint</code>?  There may be a few very specialized cases
where that extra <code>uint</code> could cause a problem, but I&rsquo;m not sure if it&rsquo;s worth
it. What do you all think?</p>

<hr />

<p>I thought that was good, but since I&rsquo;m already here, how&rsquo;s the new <code>Vec&lt;u8&gt;</code>
writer doing? Here&rsquo;s the driver:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span> <span class="nb">Writer</span> <span class="k">for</span> <span class="n">Vec</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">write</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">buf</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">push_all</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span>
</span><span class='line'>        <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span> <span class="nb">Writer</span> <span class="k">for</span> <span class="n">Vec</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">write</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">buf</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">push_all</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span>
</span><span class='line'>        <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[bench]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">bench_std_vec_writer</span><span class="p">(</span><span class="n">b</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">test</span><span class="o">::</span><span class="n">Bencher</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">dst</span> <span class="o">=</span> <span class="n">Vec</span><span class="o">::</span><span class="n">with_capacity</span><span class="p">(</span><span class="n">BATCHES</span> <span class="o">*</span> <span class="n">SRC_LEN</span><span class="p">);</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">src</span> <span class="o">=</span> <span class="o">&amp;</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="p">..</span> <span class="n">SRC_LEN</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">b</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="o">||</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">dst</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="n">do_std_writes</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="n">dst</span><span class="p">,</span> <span class="n">src</span><span class="p">,</span> <span class="n">BATCHES</span><span class="p">);</span>
</span><span class='line'>    <span class="p">})</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And the results:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_std_vec_writer</span>                           <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">1000</span> <span class="o">|</span> <span class="p">[</span><span class="o">----*****</span><span class="err">#</span><span class="o">*****--------</span><span class="p">]</span>             <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>      <span class="mi">1248</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">588</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_std_vec_writer_inline_always</span>             <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">900</span> <span class="o">|</span>   <span class="p">[</span><span class="o">----*</span><span class="err">#</span><span class="o">***--</span><span class="p">]</span>                        <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>      <span class="mi">1125</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">282</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_std_vec_writer_inline_never</span>              <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">1000</span> <span class="o">|</span>  <span class="p">[</span><span class="o">----***</span><span class="err">#</span><span class="o">*****--------</span><span class="p">]</span>              <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>      <span class="mi">1227</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">516</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Wow. That&rsquo;s pretty terrible. Something weird must be going on with
<code>Vec::push_all</code>. (Maybe that&rsquo;s what caused my serialization benchmarks to slow
1/3?). Lets skip it:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="n">MyWriter</span> <span class="k">for</span> <span class="n">VecWriter1</span><span class="o">&lt;</span><span class="nl">&#39;a</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="cp">#[inline]</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">my_write</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="bp">self</span><span class="p">,</span> <span class="n">src</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">IoResult</span><span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">src_len</span> <span class="o">=</span> <span class="n">src</span><span class="p">.</span><span class="n">len</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="bp">self</span><span class="p">.</span><span class="n">dst</span><span class="p">.</span><span class="n">reserve</span><span class="p">(</span><span class="n">src_len</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="n">dst</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">dst</span><span class="p">.</span><span class="n">as_mut_slice</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>            <span class="c1">// we reserved enough room in `dst` to store `src`.</span>
</span><span class='line'>            <span class="n">ptr</span><span class="o">::</span><span class="n">copy_nonoverlapping_memory</span><span class="p">(</span>
</span><span class='line'>                <span class="n">dst</span><span class="p">.</span><span class="n">as_mut_ptr</span><span class="p">(),</span>
</span><span class='line'>                <span class="n">src</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span>
</span><span class='line'>                <span class="n">src_len</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And it looks a bit better, but not perfect:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_vec_writer_1</span>                             <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">100</span> <span class="o">|</span>         <span class="p">[</span><span class="o">------*********</span><span class="err">#</span><span class="o">*****--------</span><span class="p">]</span> <span class="o">|</span> <span class="mi">200</span><span class="o">:</span>       <span class="mi">160</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">68</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_vec_writer_1_inline_always</span>               <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">100</span> <span class="o">|</span>     <span class="p">[</span><span class="o">--------****</span><span class="err">#</span><span class="o">**--</span><span class="p">]</span>                 <span class="o">|</span> <span class="mi">300</span><span class="o">:</span>       <span class="mi">182</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">79</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_vec_writer_1_inline_never</span>                <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">600</span> <span class="o">|</span>   <span class="p">[</span><span class="o">---****</span><span class="err">#</span><span class="o">**--</span><span class="p">]</span>                       <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>       <span class="mi">952</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">399</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>There&rsquo;s even less going on here than before. The only difference is that
reserve call. Commenting it out gets us back to <code>copy_nonoverlapping_memory</code>
territory:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_vec_writer_1</span>                             <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">70</span> <span class="o">|</span> <span class="p">[</span><span class="o">----------------*********</span><span class="err">#</span><span class="o">******-------</span><span class="p">]</span><span class="o">|</span> <span class="mi">100</span><span class="o">:</span>        <span class="mi">89</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">27</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_vec_writer_1_inline_always</span>               <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">50</span> <span class="o">|</span>   <span class="p">[</span><span class="o">-***</span><span class="err">#</span><span class="o">******--</span><span class="p">]</span>                        <span class="o">|</span> <span class="mi">200</span><span class="o">:</span>        <span class="mi">75</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">46</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">writer</span><span class="o">::</span><span class="n">bench_vec_writer_1_inline_never</span>                <span class="p">...</span> <span class="n">bench</span><span class="o">:</span> <span class="mi">500</span> <span class="o">|</span>   <span class="p">[</span><span class="o">--***</span><span class="err">#</span><span class="o">***---</span><span class="p">]</span>                       <span class="o">|</span> <span class="mi">2000</span><span class="o">:</span>       <span class="mi">775</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">433</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Unfortunately it&rsquo;s getting pretty late, so rather than wait until the next time
to dive into this, I&rsquo;ll leave it up to you all. Does anyone know why <code>reserve</code>
is causing so much trouble here?</p>

<hr />

<p>PS: While I was working on this, I saw
<a href="https://github.com/erickt/rust-serialization-benchmarks/pull/2">stevencheg</a>
submitted a patch to speed up the protocol buffer support. But when I ran the
tests, everything was about 40% slower than the last benchmark
<a href="http://erickt.github.io/blog/2014/11/13/benchmarks-2/">post</a>! Something
happened with Rust&rsquo;s performance over these past couple weeks!</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">bincode</span><span class="o">::</span><span class="n">bench_decoder</span>                          <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>      <span class="mi">7682</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">3680</span><span class="p">)</span> <span class="o">=</span> <span class="mi">52</span> <span class="n">MB</span><span class="o">/</span><span class="n">s</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">bincode</span><span class="o">::</span><span class="n">bench_encoder</span>                          <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>       <span class="mi">516</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">265</span><span class="p">)</span> <span class="o">=</span> <span class="mi">775</span> <span class="n">MB</span><span class="o">/</span><span class="n">s</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">bincode</span><span class="o">::</span><span class="n">bench_populate</span>                         <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>      <span class="mi">1504</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">324</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">capnp</span><span class="o">::</span><span class="n">bench_deserialize</span>                        <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>       <span class="mi">251</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">140</span><span class="p">)</span> <span class="o">=</span> <span class="mi">1784</span> <span class="n">MB</span><span class="o">/</span><span class="n">s</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">capnp</span><span class="o">::</span><span class="n">bench_deserialize_packed_unbuffered</span>      <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>      <span class="mi">1344</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">533</span><span class="p">)</span> <span class="o">=</span> <span class="mi">250</span> <span class="n">MB</span><span class="o">/</span><span class="n">s</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">capnp</span><span class="o">::</span><span class="n">bench_populate</span>                           <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>       <span class="mi">663</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">236</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">capnp</span><span class="o">::</span><span class="n">bench_serialize</span>                          <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>       <span class="mi">144</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">37</span><span class="p">)</span> <span class="o">=</span> <span class="mi">3111</span> <span class="n">MB</span><span class="o">/</span><span class="n">s</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">capnp</span><span class="o">::</span><span class="n">bench_serialize_packed_unbuffered</span>        <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>       <span class="mi">913</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">436</span><span class="p">)</span> <span class="o">=</span> <span class="mi">369</span> <span class="n">MB</span><span class="o">/</span><span class="n">s</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">msgpack</span><span class="o">::</span><span class="n">bench_decoder</span>                          <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>      <span class="mi">3411</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">1837</span><span class="p">)</span> <span class="o">=</span> <span class="mi">84</span> <span class="n">MB</span><span class="o">/</span><span class="n">s</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">msgpack</span><span class="o">::</span><span class="n">bench_encoder</span>                          <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>       <span class="mi">961</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">477</span><span class="p">)</span> <span class="o">=</span> <span class="mi">298</span> <span class="n">MB</span><span class="o">/</span><span class="n">s</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">msgpack</span><span class="o">::</span><span class="n">bench_populate</span>                         <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>      <span class="mi">1564</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">453</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">protobuf</span><span class="o">::</span><span class="n">bench_decoder</span>                         <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>      <span class="mi">3116</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">1485</span><span class="p">)</span> <span class="o">=</span> <span class="mi">91</span> <span class="n">MB</span><span class="o">/</span><span class="n">s</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">protobuf</span><span class="o">::</span><span class="n">bench_encoder</span>                         <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>      <span class="mi">1220</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">482</span><span class="p">)</span> <span class="o">=</span> <span class="mi">234</span> <span class="n">MB</span><span class="o">/</span><span class="n">s</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">protobuf</span><span class="o">::</span><span class="n">bench_populate</span>                        <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>       <span class="mi">942</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">836</span><span class="p">)</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">serialize_json</span><span class="o">::</span><span class="n">bench_decoder</span>                   <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>     <span class="mi">31934</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">16186</span><span class="p">)</span> <span class="o">=</span> <span class="mi">18</span> <span class="n">MB</span><span class="o">/</span><span class="n">s</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">serialize_json</span><span class="o">::</span><span class="n">bench_encoder</span>                   <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>      <span class="mi">8481</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">3392</span><span class="p">)</span> <span class="o">=</span> <span class="mi">71</span> <span class="n">MB</span><span class="o">/</span><span class="n">s</span>
</span><span class='line'><span class="n">test</span> <span class="n">goser</span><span class="o">::</span><span class="n">serialize_json</span><span class="o">::</span><span class="n">bench_populate</span>                  <span class="p">...</span> <span class="n">bench</span><span class="o">:</span>      <span class="mi">1471</span> <span class="n">ns</span><span class="o">/</span><span class="n">iter</span> <span class="p">(</span><span class="o">+/-</span> <span class="mi">426</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Chasing an EPROTOTYPE Through Rust, Sendto, and the OSX Kernel With C-Reduce]]></title>
    <link href="http://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/"/>
    <updated>2014-11-19T07:35:04-08:00</updated>
    <id>http://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug</id>
    <content type="html"><![CDATA[<p>A slight diversion from my serialization series. Last week, strcat submitted
<a href="https://github.com/rust-lang/rust/pull/18885">#18885</a> pull request, which adds
support for using a <code>Vec</code> as a <code>Writer</code>. Over the weekend I submitted
<a href="https://github.com/rust-lang/rust/pull/18980">#18980</a>, which allows a <code>&amp;[u8]</code>
to be used as a <code>Reader</code>. Overall a pretty simple change. However, when I was
running the test suite, I found that the <code>std::io::net::tcp::write_close_ip4()</code>
test was occasionally failing:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="cp">#[test]</span>
</span><span class='line'><span class="k">fn</span> <span class="n">write_close_ip4</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">next_test_ip4</span><span class="p">();</span>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">acceptor</span> <span class="o">=</span> <span class="n">TcpListener</span><span class="o">::</span><span class="n">bind</span><span class="p">(</span><span class="n">addr</span><span class="p">).</span><span class="n">listen</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="nb">spawn</span><span class="p">(</span><span class="k">proc</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">_stream</span> <span class="o">=</span> <span class="n">TcpStream</span><span class="o">::</span><span class="n">connect</span><span class="p">(</span><span class="n">addr</span><span class="p">);</span>
</span><span class='line'>        <span class="c1">// Close</span>
</span><span class='line'>    <span class="p">});</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="k">mut</span> <span class="n">stream</span> <span class="o">=</span> <span class="n">acceptor</span><span class="p">.</span><span class="n">accept</span><span class="p">();</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">buf</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">];</span>
</span><span class='line'>    <span class="k">loop</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">match</span> <span class="n">stream</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">buf</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Ok</span><span class="p">(..)</span> <span class="o">=&gt;</span> <span class="p">{}</span>
</span><span class='line'>            <span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">assert</span><span class="o">!</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">kind</span> <span class="o">==</span> <span class="n">ConnectionReset</span> <span class="o">||</span>
</span><span class='line'>                        <span class="n">e</span><span class="p">.</span><span class="n">kind</span> <span class="o">==</span> <span class="n">BrokenPipe</span> <span class="o">||</span>
</span><span class='line'>                        <span class="n">e</span><span class="p">.</span><span class="n">kind</span> <span class="o">==</span> <span class="n">ConnectionAborted</span><span class="p">,</span>
</span><span class='line'>                        <span class="s">&quot;unknown error: {}&quot;</span><span class="p">,</span> <span class="n">e</span><span class="p">);</span>
</span><span class='line'>                <span class="k">break</span><span class="p">;</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The <code>write</code> would succeed a few times, then occasionally error with the
<code>unknown error: Protocol wrong type for socket</code>, or the <code>EPROTOTYPE</code> errno.
This is a really surprising error. As far as I know, the only functions that
return that errno are <code>socket</code>, <code>socketpair</code>, and <code>connect</code>. I searched
everywhere, but I couldn&rsquo;t find any documentation suggesting that <code>write</code> would
ever produce that error.</p>

<p>I wasn&rsquo;t the only one who ran into it. bjz opened
<a href="https://github.com/rust-lang/rust/issues/18900">#18900</a> describing the same
problem. One interesting thing to note is they were also on OSX Yosemite.  So I
took a little bit of time to extract out that test from the Rust test suite
into this <a href="https://gist.github.com/erickt/ac1f35e20834aa5d1972">gist</a> and got
someone on #rust-internals to run it on linux for me with this little driver
script:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="c">#!/bin/sh</span>
</span><span class='line'>
</span><span class='line'><span class="nb">set</span> -e
</span><span class='line'>
</span><span class='line'>rustc test.rs
</span><span class='line'>
</span><span class='line'><span class="k">for</span> i in <span class="k">$(</span>seq <span class="m">1</span> 1000<span class="k">)</span><span class="p">;</span> <span class="k">do</span>
</span><span class='line'>  ./test tcp::test::write_close_ip4
</span><span class='line'><span class="k">done</span>
</span></code></pre></td></tr></table></div></figure>


<p>and it didn&rsquo;t error out. So it seems to be system dependent. Further
experimentation showed that if we introduced sleeps or a mutex synchronization
appeared to fix the problem as well. At this point I wasn&rsquo;t sure if this was a
non-issue, a bug in our code, or a bug in the OS. One things for sure though,
if there is a bug, it could be scattered somewhere across the Rust codebase,
which just <code>std::io</code> alone is 20 files at around 12522 lines. It&rsquo;d be a pain to
cut that down to a self contained test case.</p>

<p>Fortunately we&rsquo;ve got <a href="http://embed.cs.utah.edu/creduce/">C-Reduce</a> to help us
out. Back in May <a href="http://www.cs.utah.edu/~regehr/">Professor John Regehr</a> from
the University of Utah came to our
<a href="http://www.meetup.com/Rust-Bay-Area/events/169434302/">Bay Area Rust meetup</a>
 to talk about compiler testing and fuzzing. We recorded the talk, so if you
want to watch it, you can find it
<a href="https://air.mozilla.org/rust-meetup-may-2014/">here</a>. One of the things he
talked about was the tool C-Reduce his research group developed to
automatically cut
out unnecessary lines of code that can still reproduce a bug you&rsquo;re looking
for. While it&rsquo;s written to target C files, it turns out Rust is syntatically
close enough to C that it works out pretty well for it too. All you need is a
single source file and driver script that&rsquo;ll report if the compiled source file
reproduced the bug.</p>

<p>Aside 1: By the way, one of the other things I did this weekend was I put
together a Homebrew
<a href="https://github.com/Homebrew/homebrew/pull/34220">pull request for C-Reduce</a>.
It hasn&rsquo;t landed yet, but you want to use it, you can do:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>% brew install https://raw.githubusercontent.com/erickt/homebrew/delta-and-creduce/Library/Formula/delta.rb
</span><span class='line'>% brew install https://raw.githubusercontent.com/erickt/homebrew/delta-and-creduce/Library/Formula/creduce.rb
</span></code></pre></td></tr></table></div></figure>


<p>Hopefully it&rsquo;ll land soon so you&rsquo;ll be able to do:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>% brew install creduce
</span></code></pre></td></tr></table></div></figure>


<p>Anyway, back to the story. So we&rsquo;ve got a rather large code base to cover, and
while C-reduce does a pretty good job of trimming away lines, just pointing it
at the entire <code>std</code> module is a bit too much for it to handle in a reasonable
amount of time. It probably needs some more semantic information about Rust to
do a better job of cutting out broad swaths of code.</p>

<p>So I needed to do at least a rough pass to slim down the files. I figured the
problem was probably contained in <code>std::io</code> or <code>std::sys</code>, so I wrote a simple
<code>test.rs</code> that explicitly included those modules as part of the crate (see
this <a href="https://gist.github.com/erickt/ac1f35e20834aa5d1972">gist</a> if you are
interested), and used the pretty printer to merge it into one file:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>% rustc --pretty normal test.rs &gt; test.rs
</span></code></pre></td></tr></table></div></figure>


<p>Aside 2: Our pretty printer still has some bugs in it, which I filed:
<a href="https://github.com/rust-lang/rust/issues/19075">19075</a> and
<a href="https://github.com/rust-lang/rust/issues/19077">19077</a>.  Fortunately it was
pretty simple to fix those cases by hand in the generated <code>std.rs</code>, and odds
are good they&rsquo;ll be fixed by the time you might use this process.</p>

<p>Next up, we need a driver script. We can adapt our one from before. The only
special consideration is that we need to make sure to only exit with a return
code of 0 if the version of <code>std.rs</code> we&rsquo;re compiling errors with <code>EPROTOTYPE</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c">#!/bin/sh</span>
</span><span class='line'>
</span><span class='line'>rustc <span class="se">\</span>
</span><span class='line'>  -A unused_imports <span class="se">\</span>
</span><span class='line'>  -A unused_unsafe <span class="se">\</span>
</span><span class='line'>  -A non_camel_case_types <span class="se">\</span>
</span><span class='line'>  -A unused_variables <span class="se">\</span>
</span><span class='line'>  --test <span class="se">\</span>
</span><span class='line'>  -o <span class="nb">test</span> <span class="se">\</span>
</span><span class='line'>  test.rs &gt;/dev/null 2&gt;<span class="p">&amp;</span>1
</span><span class='line'><span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$?&quot;</span> -ne <span class="s2">&quot;0&quot;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span><span class='line'>  <span class="nb">exit </span>1
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="nv">root</span><span class="o">=</span><span class="sb">`</span>dirname <span class="nv">$0</span><span class="sb">`</span>
</span><span class='line'>
</span><span class='line'><span class="k">for</span> i in <span class="k">$(</span>seq <span class="m">1</span> 1000<span class="k">)</span><span class="p">;</span> <span class="k">do</span>
</span><span class='line'>  <span class="nv">$root</span>/timeout.sh <span class="m">5</span> ./test --nocapture tcp::test::write_close_ip4 2&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="p">|</span> tee log
</span><span class='line'>  grep <span class="s2">&quot;Protocol wrong type for socket&quot;</span> log
</span><span class='line'>  <span class="nv">RET</span><span class="o">=</span><span class="s2">&quot;$?&quot;</span>
</span><span class='line'>  <span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$RET&quot;</span> -eq <span class="s2">&quot;0&quot;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span><span class='line'>          <span class="nb">exit </span>0
</span><span class='line'>  <span class="k">elif</span> <span class="o">[</span> <span class="s2">&quot;$RET&quot;</span> -eq <span class="s2">&quot;143&quot;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span><span class='line'>          <span class="nb">exit </span>1
</span><span class='line'>  <span class="k">fi</span>
</span><span class='line'>  <span class="nb">echo</span>
</span><span class='line'><span class="k">done</span>
</span><span class='line'>
</span><span class='line'><span class="nb">exit </span>1
</span></code></pre></td></tr></table></div></figure>


<p>I used the helper script
<a href="http://www.ict.griffith.edu.au/anthony/software/timeout.sh">timeout.sh</a> to
time out tests in case C-Reduce accidentally made us an infinite loop.</p>

<p>Finally we&rsquo;re ready to start running C-Reduce:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>% creduce ./driver.sh test.rs
</span><span class='line'><span class="o">===</span>&lt; <span class="m">30598</span> &gt;<span class="o">===</span>
</span><span class='line'>running <span class="m">8</span> interestingness <span class="nb">test</span><span class="o">(</span>s<span class="o">)</span> in <span class="nv">parallel</span>
</span><span class='line'><span class="o">===</span>&lt; pass_blank :: <span class="m">0</span> &gt;<span class="o">===</span>
</span><span class='line'><span class="o">(</span>0.0 %, <span class="m">156170</span> bytes<span class="o">)</span>
</span><span class='line'><span class="o">===</span>&lt; pass_clang_binsrch :: replace-function-def-with-decl &gt;<span class="o">===</span>
</span><span class='line'><span class="o">===</span>&lt; pass_clang_binsrch :: remove-unused-function &gt;<span class="o">===</span>
</span><span class='line'><span class="o">===</span>&lt; pass_lines :: <span class="m">0</span> &gt;<span class="o">===</span>
</span><span class='line'><span class="o">(</span>-0.6 %, <span class="m">157231</span> bytes<span class="o">)</span>
</span><span class='line'><span class="o">(</span>1.2 %, <span class="m">154323</span> bytes<span class="o">)</span>
</span><span class='line'><span class="o">(</span>3.7 %, <span class="m">150455</span> bytes<span class="o">)</span>
</span><span class='line'><span class="o">(</span>4.6 %, <span class="m">149074</span> bytes<span class="o">)</span>
</span><span class='line'><span class="o">(</span>5.5 %, <span class="m">147639</span> bytes<span class="o">)</span>
</span><span class='line'><span class="o">(</span>6.4 %, <span class="m">146172</span> bytes<span class="o">)</span>
</span><span class='line'><span class="o">(</span>7.3 %, <span class="m">144881</span> bytes<span class="o">)</span>
</span><span class='line'><span class="o">(</span>7.7 %, <span class="m">144187</span> bytes<span class="o">)</span>
</span><span class='line'><span class="o">(</span>9.1 %, <span class="m">141936</span> bytes<span class="o">)</span>
</span><span class='line'><span class="o">(</span>9.9 %, <span class="m">140706</span> bytes<span class="o">)</span>
</span><span class='line'><span class="o">(</span>10.3 %, <span class="m">140104</span> bytes<span class="o">)</span>
</span><span class='line'><span class="o">(</span>10.4 %, <span class="m">139998</span> bytes<span class="o">)</span>
</span><span class='line'>...
</span></code></pre></td></tr></table></div></figure>


<p>I let it run in the background for sometime in the background while I did some
other things. When I got back, C-Reduce automatically reduced the file from
153KB to a slim 22KB. I then reran rust with the lints enabled to manually cut
out the dead code C-Reduce failed to remove, and flattened away some
unnecessary structs and methods. I was finally left with:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
<span class='line-number'>106</span>
<span class='line-number'>107</span>
<span class='line-number'>108</span>
<span class='line-number'>109</span>
<span class='line-number'>110</span>
<span class='line-number'>111</span>
<span class='line-number'>112</span>
<span class='line-number'>113</span>
<span class='line-number'>114</span>
<span class='line-number'>115</span>
<span class='line-number'>116</span>
<span class='line-number'>117</span>
<span class='line-number'>118</span>
<span class='line-number'>119</span>
<span class='line-number'>120</span>
<span class='line-number'>121</span>
<span class='line-number'>122</span>
<span class='line-number'>123</span>
<span class='line-number'>124</span>
<span class='line-number'>125</span>
<span class='line-number'>126</span>
<span class='line-number'>127</span>
<span class='line-number'>128</span>
<span class='line-number'>129</span>
<span class='line-number'>130</span>
<span class='line-number'>131</span>
<span class='line-number'>132</span>
<span class='line-number'>133</span>
<span class='line-number'>134</span>
<span class='line-number'>135</span>
<span class='line-number'>136</span>
<span class='line-number'>137</span>
<span class='line-number'>138</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">libc</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">io</span><span class="o">::</span><span class="n">net</span><span class="o">::</span><span class="n">ip</span><span class="o">::</span><span class="n">Ipv4Addr</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">io</span><span class="o">::</span><span class="n">net</span><span class="o">::</span><span class="n">ip</span><span class="o">::</span><span class="n">SocketAddr</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">io</span><span class="o">::</span><span class="n">net</span><span class="o">::</span><span class="n">ip</span><span class="o">::</span><span class="n">ToSocketAddr</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">io</span><span class="o">::</span><span class="n">net</span><span class="o">::</span><span class="n">ip</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">io</span><span class="o">::</span><span class="n">test</span><span class="o">::</span><span class="n">next_test_ip4</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">mem</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">num</span><span class="o">::</span><span class="nb">Int</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">os</span><span class="o">::</span><span class="n">errno</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">os</span><span class="o">::</span><span class="n">error_string</span><span class="p">;</span>
</span><span class='line'><span class="kn">use</span> <span class="n">std</span><span class="o">::</span><span class="n">ptr</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">bind</span><span class="p">(</span><span class="n">addr</span><span class="o">:</span> <span class="n">ip</span><span class="o">::</span><span class="n">SocketAddr</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">fd</span> <span class="o">=</span> <span class="k">match</span> <span class="n">libc</span><span class="o">::</span><span class="n">socket</span><span class="p">(</span><span class="n">libc</span><span class="o">::</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">libc</span><span class="o">::</span><span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="o">-</span><span class="mi">1</span> <span class="o">=&gt;</span> <span class="n">panic</span><span class="o">!</span><span class="p">(),</span>
</span><span class='line'>            <span class="n">fd</span> <span class="o">=&gt;</span> <span class="n">fd</span><span class="p">,</span>
</span><span class='line'>        <span class="p">};</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="k">mut</span> <span class="n">storage</span> <span class="o">=</span> <span class="n">mem</span><span class="o">::</span><span class="n">zeroed</span><span class="p">();</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">len</span> <span class="o">=</span> <span class="n">addr_to_sockaddr</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">storage</span><span class="p">);</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">addrp</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">storage</span> <span class="k">as</span> <span class="o">*</span><span class="kr">const</span> <span class="n">_</span> <span class="k">as</span> <span class="o">*</span><span class="kr">const</span> <span class="n">libc</span><span class="o">::</span><span class="n">sockaddr</span><span class="p">;</span>
</span><span class='line'>        <span class="k">match</span> <span class="n">libc</span><span class="o">::</span><span class="n">bind</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">addrp</span><span class="p">,</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="o">-</span><span class="mi">1</span> <span class="o">=&gt;</span> <span class="n">panic</span><span class="o">!</span><span class="p">(),</span>
</span><span class='line'>            <span class="n">_</span> <span class="o">=&gt;</span> <span class="n">fd</span><span class="p">,</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">listen</span><span class="p">(</span><span class="n">fd</span><span class="o">:</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span><span class="p">,</span> <span class="n">backlog</span><span class="o">:</span> <span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">match</span> <span class="n">libc</span><span class="o">::</span><span class="n">listen</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">backlog</span> <span class="k">as</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="o">-</span><span class="mi">1</span> <span class="o">=&gt;</span> <span class="n">panic</span><span class="o">!</span><span class="p">(),</span>
</span><span class='line'>            <span class="n">_</span> <span class="o">=&gt;</span> <span class="p">{}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">accept</span><span class="p">(</span><span class="n">fd</span><span class="o">:</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">x</span> <span class="o">=</span> <span class="n">libc</span><span class="o">::</span><span class="n">accept</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">ptr</span><span class="o">::</span><span class="n">null_mut</span><span class="p">(),</span> <span class="n">ptr</span><span class="o">::</span><span class="n">null_mut</span><span class="p">());</span>
</span><span class='line'>        <span class="k">match</span> <span class="n">x</span> <span class="p">{</span>
</span><span class='line'>            <span class="o">-</span><span class="mi">1</span> <span class="o">=&gt;</span> <span class="n">panic</span><span class="o">!</span><span class="p">(),</span>
</span><span class='line'>            <span class="n">fd</span> <span class="o">=&gt;</span> <span class="n">fd</span><span class="p">,</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">connect</span><span class="p">(</span><span class="n">addr</span><span class="o">:</span> <span class="n">SocketAddr</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">fd</span> <span class="o">=</span> <span class="k">match</span> <span class="n">libc</span><span class="o">::</span><span class="n">socket</span><span class="p">(</span><span class="n">libc</span><span class="o">::</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">libc</span><span class="o">::</span><span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="o">-</span><span class="mi">1</span> <span class="o">=&gt;</span> <span class="n">panic</span><span class="o">!</span><span class="p">(),</span>
</span><span class='line'>            <span class="n">fd</span> <span class="o">=&gt;</span> <span class="n">fd</span><span class="p">,</span>
</span><span class='line'>        <span class="p">};</span>
</span><span class='line'>
</span><span class='line'>        <span class="kd">let</span> <span class="k">mut</span> <span class="n">storage</span> <span class="o">=</span> <span class="n">mem</span><span class="o">::</span><span class="n">zeroed</span><span class="p">();</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">len</span> <span class="o">=</span> <span class="n">addr_to_sockaddr</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">storage</span><span class="p">);</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">addrp</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">storage</span> <span class="k">as</span> <span class="o">*</span><span class="kr">const</span> <span class="n">_</span> <span class="k">as</span> <span class="o">*</span><span class="kr">const</span> <span class="n">libc</span><span class="o">::</span><span class="n">sockaddr</span><span class="p">;</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">x</span> <span class="o">=</span> <span class="n">libc</span><span class="o">::</span><span class="n">connect</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">addrp</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
</span><span class='line'>        <span class="n">fd</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">write</span><span class="p">(</span><span class="n">fd</span><span class="o">:</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span><span class="p">,</span> <span class="n">buf</span><span class="o">:</span> <span class="o">&amp;</span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="kt">uint</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">len</span> <span class="o">=</span> <span class="n">buf</span><span class="p">.</span><span class="n">len</span><span class="p">();</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">ret</span> <span class="o">=</span> <span class="n">libc</span><span class="o">::</span><span class="n">send</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">()</span> <span class="k">as</span> <span class="o">*</span><span class="kr">const</span> <span class="n">_</span><span class="p">,</span> <span class="n">len</span> <span class="k">as</span> <span class="n">libc</span><span class="o">::</span><span class="n">size_t</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="k">as</span> <span class="kt">i64</span><span class="p">;</span>
</span><span class='line'>        <span class="k">if</span> <span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Err</span><span class="p">(</span><span class="n">errno</span><span class="p">())</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Ok</span><span class="p">(())</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="o">:</span> <span class="n">libc</span><span class="o">::</span><span class="n">c_int</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">x</span> <span class="o">=</span> <span class="n">libc</span><span class="o">::</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>
</span><span class='line'>        <span class="n">assert_eq</span><span class="o">!</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">addr_to_sockaddr</span><span class="p">(</span><span class="n">addr</span><span class="o">:</span> <span class="n">SocketAddr</span><span class="p">,</span> <span class="n">storage</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">libc</span><span class="o">::</span><span class="n">sockaddr_storage</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">libc</span><span class="o">::</span><span class="n">socklen_t</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">inaddr</span> <span class="o">=</span> <span class="k">match</span> <span class="n">addr</span><span class="p">.</span><span class="n">ip</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">Ipv4Addr</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>            <span class="kd">let</span> <span class="n">ip</span> <span class="o">=</span> <span class="n">a</span> <span class="k">as</span> <span class="kt">u32</span> <span class="o">&lt;&lt;</span> <span class="mi">24</span> <span class="o">|</span> <span class="n">b</span> <span class="k">as</span> <span class="kt">u32</span> <span class="o">&lt;&lt;</span> <span class="mi">16</span> <span class="o">|</span> <span class="n">c</span> <span class="k">as</span> <span class="kt">u32</span> <span class="o">&lt;&lt;</span> <span class="mi">8</span> <span class="o">|</span> <span class="n">d</span> <span class="k">as</span> <span class="kt">u32</span> <span class="o">&lt;&lt;</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>            <span class="n">libc</span><span class="o">::</span><span class="n">in_addr</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">s_addr</span><span class="o">:</span> <span class="nb">Int</span><span class="o">::</span><span class="n">from_be</span><span class="p">(</span><span class="n">ip</span><span class="p">),</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="n">_</span> <span class="o">=&gt;</span> <span class="n">panic</span><span class="o">!</span><span class="p">(),</span>
</span><span class='line'>    <span class="p">};</span>
</span><span class='line'>    <span class="k">unsafe</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">storage</span> <span class="o">=</span> <span class="n">storage</span> <span class="k">as</span> <span class="o">*</span><span class="k">mut</span> <span class="n">_</span> <span class="k">as</span> <span class="o">*</span><span class="k">mut</span> <span class="n">libc</span><span class="o">::</span><span class="n">sockaddr_in</span><span class="p">;</span>
</span><span class='line'>        <span class="p">(</span><span class="o">*</span><span class="n">storage</span><span class="p">).</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">libc</span><span class="o">::</span><span class="n">AF_INET</span> <span class="k">as</span> <span class="n">libc</span><span class="o">::</span><span class="n">sa_family_t</span><span class="p">;</span>
</span><span class='line'>        <span class="p">(</span><span class="o">*</span><span class="n">storage</span><span class="p">).</span><span class="n">sin_port</span> <span class="o">=</span> <span class="n">addr</span><span class="p">.</span><span class="n">port</span><span class="p">.</span><span class="n">to_be</span><span class="p">();</span>
</span><span class='line'>        <span class="p">(</span><span class="o">*</span><span class="n">storage</span><span class="p">).</span><span class="n">sin_addr</span> <span class="o">=</span> <span class="n">inaddr</span><span class="p">;</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">len</span> <span class="o">=</span> <span class="n">mem</span><span class="o">::</span><span class="n">size_of</span><span class="o">::&lt;</span><span class="n">libc</span><span class="o">::</span><span class="n">sockaddr_in</span><span class="o">&gt;</span><span class="p">();</span>
</span><span class='line'>        <span class="n">len</span> <span class="k">as</span> <span class="n">libc</span><span class="o">::</span><span class="n">socklen_t</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">next_test_ip4</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="n">listener</span> <span class="o">=</span> <span class="n">bind</span><span class="p">(</span><span class="n">addr</span><span class="p">);</span>
</span><span class='line'>    <span class="n">listen</span><span class="p">(</span><span class="n">listener</span><span class="p">,</span> <span class="mi">128</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="nb">spawn</span><span class="p">(</span><span class="k">proc</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">addresses</span> <span class="o">=</span> <span class="n">addr</span><span class="p">.</span><span class="n">to_socket_addr_all</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'>        <span class="k">for</span> <span class="n">addr</span> <span class="k">in</span> <span class="n">addresses</span><span class="p">.</span><span class="n">into_iter</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>            <span class="kd">let</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">connect</span><span class="p">(</span><span class="n">addr</span><span class="p">);</span>
</span><span class='line'>            <span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>
</span><span class='line'>            <span class="k">return</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">});</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="n">stream</span> <span class="o">=</span> <span class="n">accept</span><span class="p">(</span><span class="n">listener</span><span class="p">);</span>
</span><span class='line'>    <span class="k">loop</span> <span class="p">{</span>
</span><span class='line'>        <span class="kd">let</span> <span class="n">x</span> <span class="o">=</span> <span class="n">write</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
</span><span class='line'>        <span class="k">match</span> <span class="n">x</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Ok</span><span class="p">(..)</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="p">}</span>
</span><span class='line'>            <span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="kd">let</span> <span class="n">e</span> <span class="o">=</span> <span class="n">e</span> <span class="k">as</span> <span class="kt">i32</span><span class="p">;</span>
</span><span class='line'>                <span class="n">assert</span><span class="o">!</span><span class="p">(</span>
</span><span class='line'>                    <span class="n">e</span> <span class="o">==</span> <span class="n">libc</span><span class="o">::</span><span class="n">ECONNREFUSED</span> <span class="o">||</span>
</span><span class='line'>                    <span class="n">e</span> <span class="o">==</span> <span class="n">libc</span><span class="o">::</span><span class="n">EPIPE</span> <span class="o">||</span>
</span><span class='line'>                    <span class="n">e</span> <span class="o">==</span> <span class="n">libc</span><span class="o">::</span><span class="n">ECONNABORTED</span><span class="p">,</span>
</span><span class='line'>                    <span class="s">&quot;unknown error: {} {}&quot;</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">error_string</span><span class="p">(</span><span class="n">e</span> <span class="k">as</span> <span class="kt">uint</span><span class="p">));</span>
</span><span class='line'>                <span class="k">break</span><span class="p">;</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">close</span><span class="p">(</span><span class="n">stream</span><span class="p">);</span>
</span><span class='line'>    <span class="n">close</span><span class="p">(</span><span class="n">listener</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>This snippet reproduces the same <code>EPROTOTYPE</code> that we started with at the top
of the post. Pretty cool that we got here without much effort?</p>

<p>Now At this point you might say to yourself that couldn&rsquo;t I have extracted this
out myself?  And yeah, you would be right. This is a pretty much a c-in-rust
implementation of this bug. But what&rsquo;s great about using C-Reduce here is that
I only had to make some very rough guesses about what files were and were not
important to include in my <code>test.rs</code>. Eventually when we get some rust plugins
written for C-Reduce I probably could just point it at the whole <code>libstd</code> let
C-Reduce do it&rsquo;s thing. Doing this by hand can be a pretty long and painful
manual process, especially if we&rsquo;re trying to debug a codegen or runtime bug.
In the past I&rsquo;ve spent hours reducing some codegen bugs down into a small
snippet that C-Reduce was also able to produce in a couple minutes.</p>

<p>The last step with this code was to eliminate Rust from the picture, and
translate this code into C:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
<span class='line-number'>106</span>
<span class='line-number'>107</span>
<span class='line-number'>108</span>
<span class='line-number'>109</span>
<span class='line-number'>110</span>
<span class='line-number'>111</span>
<span class='line-number'>112</span>
<span class='line-number'>113</span>
<span class='line-number'>114</span>
<span class='line-number'>115</span>
<span class='line-number'>116</span>
<span class='line-number'>117</span>
<span class='line-number'>118</span>
<span class='line-number'>119</span>
<span class='line-number'>120</span>
<span class='line-number'>121</span>
<span class='line-number'>122</span>
<span class='line-number'>123</span>
<span class='line-number'>124</span>
<span class='line-number'>125</span>
<span class='line-number'>126</span>
<span class='line-number'>127</span>
<span class='line-number'>128</span>
<span class='line-number'>129</span>
<span class='line-number'>130</span>
<span class='line-number'>131</span>
<span class='line-number'>132</span>
<span class='line-number'>133</span>
<span class='line-number'>134</span>
<span class='line-number'>135</span>
<span class='line-number'>136</span>
<span class='line-number'>137</span>
<span class='line-number'>138</span>
<span class='line-number'>139</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="cp">#include &lt;stdio.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;unistd.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;stdlib.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;strings.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;sys/socket.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;netinet/in.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;pthread.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;errno.h&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="nf">do_server</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="kt">int</span> <span class="n">fd</span><span class="p">;</span>
</span><span class='line'>  <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">server_addr</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">fd</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">perror</span><span class="p">(</span><span class="s">&quot;error socket server&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">bzero</span><span class="p">((</span><span class="kt">char</span><span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">));</span>
</span><span class='line'>  <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span>
</span><span class='line'>  <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="n">INADDR_ANY</span><span class="p">;</span>
</span><span class='line'>  <span class="n">server_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="n">htons</span><span class="p">(</span><span class="mi">9600</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">bind</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">server_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">server_addr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">perror</span><span class="p">(</span><span class="s">&quot;error binding&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="n">fd</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kt">void</span><span class="o">*</span> <span class="nf">do_child_thread</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">unused</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">client_addr</span><span class="p">;</span>
</span><span class='line'>  <span class="kt">int</span> <span class="n">fd</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">fd</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">perror</span><span class="p">(</span><span class="s">&quot;error socket client&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">bzero</span><span class="p">((</span><span class="kt">char</span><span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">client_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">client_addr</span><span class="p">));</span>
</span><span class='line'>  <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_family</span> <span class="o">=</span> <span class="n">AF_INET</span><span class="p">;</span>
</span><span class='line'>  <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_addr</span><span class="p">.</span><span class="n">s_addr</span> <span class="o">=</span> <span class="n">INADDR_ANY</span><span class="p">;</span>
</span><span class='line'>  <span class="n">client_addr</span><span class="p">.</span><span class="n">sin_port</span> <span class="o">=</span> <span class="n">htons</span><span class="p">(</span><span class="mi">9600</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">connect</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">client_addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">client_addr</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">perror</span><span class="p">(</span><span class="s">&quot;error connect&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;closing client socket</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">perror</span><span class="p">(</span><span class="s">&quot;error close client socket&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;closed client socket</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">**</span> <span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kt">int</span> <span class="n">server_fd</span><span class="p">,</span> <span class="n">client_fd</span><span class="p">;</span>
</span><span class='line'>  <span class="kt">socklen_t</span> <span class="n">client_len</span><span class="p">;</span>
</span><span class='line'>  <span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="n">client_addr</span><span class="p">;</span>
</span><span class='line'>  <span class="kt">char</span> <span class="n">buf</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="sc">&#39;a&#39;</span><span class="p">,</span> <span class="sc">&#39;\n&#39;</span> <span class="p">};</span>
</span><span class='line'>  <span class="kt">pthread_t</span> <span class="n">child_thread</span><span class="p">;</span>
</span><span class='line'>  <span class="kt">int</span> <span class="n">rc</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">signal</span><span class="p">(</span><span class="n">SIGPIPE</span><span class="p">,</span> <span class="n">SIG_IGN</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">server_fd</span> <span class="o">=</span> <span class="n">do_server</span><span class="p">();</span>
</span><span class='line'>  <span class="n">rc</span> <span class="o">=</span> <span class="n">listen</span><span class="p">(</span><span class="n">server_fd</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">perror</span><span class="p">(</span><span class="s">&quot;error listen&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">rc</span> <span class="o">=</span> <span class="n">pthread_create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">child_thread</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">do_child_thread</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">perror</span><span class="p">(</span><span class="s">&quot;error pthread_create&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">client_len</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">client_addr</span><span class="p">);</span>
</span><span class='line'>  <span class="n">client_fd</span> <span class="o">=</span> <span class="n">accept</span><span class="p">(</span><span class="n">server_fd</span><span class="p">,</span> <span class="p">(</span><span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">client_addr</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">client_len</span><span class="p">);</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">client_fd</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">perror</span><span class="p">(</span><span class="s">&quot;error accept&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">while</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;before send</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="n">rc</span> <span class="o">=</span> <span class="n">send</span><span class="p">(</span><span class="n">client_fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">),</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;after send: %d</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">rc</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="n">errno</span> <span class="o">==</span> <span class="n">EPIPE</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>        <span class="kt">int</span> <span class="n">so_type</span><span class="p">;</span>
</span><span class='line'>        <span class="kt">socklen_t</span> <span class="n">so_len</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">so_type</span><span class="p">);</span>
</span><span class='line'>        <span class="n">getsockopt</span><span class="p">(</span><span class="n">client_fd</span><span class="p">,</span> <span class="n">SOL_SOCKET</span><span class="p">,</span> <span class="n">SO_TYPE</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">so_type</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">so_len</span><span class="p">);</span>
</span><span class='line'>        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;type: %d %d</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">so_type</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="n">perror</span><span class="p">(</span><span class="s">&quot;error send&quot;</span><span class="p">);</span>
</span><span class='line'>        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;before server closing client fd</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">close</span><span class="p">(</span><span class="n">client_fd</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">perror</span><span class="p">(</span><span class="s">&quot;error close client&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;after server closing client fd</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>  <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;before server closing fd</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">close</span><span class="p">(</span><span class="n">server_fd</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">perror</span><span class="p">(</span><span class="s">&quot;error close server&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;after server closing fd</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">rc</span> <span class="o">=</span> <span class="n">pthread_join</span><span class="p">(</span><span class="n">child_thread</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">rc</span> <span class="o">!=</span> <span class="n">ESRCH</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;error pthread_join: %d</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">rc</span><span class="p">);</span>
</span><span class='line'>    <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>This also produces <code>EPROTOTYPE</code>, so we can eliminate Rust altogther. But lets
keep digging. What exactly is producing this error? If I was on Linux, I&rsquo;d use
<code>strace</code>, but that program isn&rsquo;t on Macs. There&rsquo;s a similar tool called
<code>dtruss</code>, but that seemed to slow things down enough that the <code>EPROTOTYPE</code>
never happened. Fortunately though there is another program called <code>errinfo</code>,
that just prints the <code>errno</code> along with every syscall. In one terminal I ran
<code>while ./test; do sleep 0.1; done</code>. In the other:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="o">%</span> <span class="n">sudo</span> <span class="n">errinfo</span> <span class="o">-</span><span class="n">n</span> <span class="n">test</span>
</span><span class='line'><span class="p">...</span>
</span><span class='line'>           <span class="n">a</span><span class="p">.</span><span class="n">out</span>           <span class="n">stat64</span>    <span class="mi">0</span>
</span><span class='line'>           <span class="n">a</span><span class="p">.</span><span class="n">out</span>             <span class="n">open</span>    <span class="mi">0</span>
</span><span class='line'>           <span class="n">a</span><span class="p">.</span><span class="n">out</span> <span class="n">psynch_mutexwait</span>    <span class="mi">0</span>
</span><span class='line'>           <span class="n">a</span><span class="p">.</span><span class="n">out</span>   <span class="n">write_nocancel</span>    <span class="mi">0</span>
</span><span class='line'>           <span class="n">a</span><span class="p">.</span><span class="n">out</span>           <span class="n">sendto</span>    <span class="mi">0</span>
</span><span class='line'>           <span class="n">a</span><span class="p">.</span><span class="n">out</span>   <span class="n">write_nocancel</span>    <span class="mi">0</span>
</span><span class='line'>           <span class="n">a</span><span class="p">.</span><span class="n">out</span>   <span class="n">write_nocancel</span>    <span class="mi">0</span>
</span><span class='line'>           <span class="n">a</span><span class="p">.</span><span class="n">out</span>           <span class="n">sendto</span>   <span class="mi">41</span>  <span class="n">Protocol</span> <span class="n">wrong</span> <span class="n">type</span> <span class="k">for</span> <span class="n">socket</span>
</span><span class='line'>           <span class="n">a</span><span class="p">.</span><span class="n">out</span>   <span class="n">write_nocancel</span>    <span class="mi">0</span>
</span><span class='line'>           <span class="n">a</span><span class="p">.</span><span class="n">out</span>       <span class="n">getsockopt</span>    <span class="mi">0</span>
</span><span class='line'><span class="p">...</span>
</span></code></pre></td></tr></table></div></figure>


<p>Right there we see our <code>sendto</code> syscall is actually returning the <code>EPROTOTYPE</code>.
This <code>errno</code> then is definitely being created inside the OSX kernel, not in any
userspace code. Fortunately, most of the Apple kernel, XNU, is open sourced, so
we can dig down to what&rsquo;ll be the my last layer. You can find the tarballs at
<a href="http://www.opensource.apple.com/.">http://www.opensource.apple.com/.</a> But I&rsquo;d rather use the
<a href="https://github.com/opensource-apple/xnu">unoffical GitHub repository</a>. Using GitHub&rsquo;s
search tools, We can find all 17 instances of
<a href="https://github.com/opensource-apple/xnu/search?l=c&amp;q=EPROTOTYPE&amp;utf8=%E2%9C%93">EPROTOTYPE</a>
in the codebase. Now I don&rsquo;t know the XNU codebase, but there are still some
really interesting things we can find. The first is in
<a href="https://github.com/opensource-apple/xnu/blob/bb7368935f659ada117c0889612e379c97eb83b3/bsd/kern/uipc_usrreq.c#L408">bsd/kern/uipc_usrreq.c</a>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="cm">/*</span>
</span><span class='line'><span class="cm"> * Returns:  0      Success</span>
</span><span class='line'><span class="cm"> *    EINVAL</span>
</span><span class='line'><span class="cm"> *    EOPNOTSUPP</span>
</span><span class='line'><span class="cm"> *    EPIPE</span>
</span><span class='line'><span class="cm"> *    ENOTCONN</span>
</span><span class='line'><span class="cm"> *    EISCONN</span>
</span><span class='line'><span class="cm"> *  unp_internalize:EINVAL</span>
</span><span class='line'><span class="cm"> *  unp_internalize:EBADF</span>
</span><span class='line'><span class="cm"> *  unp_connect:EAFNOSUPPORT  Address family not supported</span>
</span><span class='line'><span class="cm"> *  unp_connect:EINVAL        Invalid argument</span>
</span><span class='line'><span class="cm"> *  unp_connect:ENOTSOCK      Not a socket</span>
</span><span class='line'><span class="cm"> *  unp_connect:ECONNREFUSED  Connection refused</span>
</span><span class='line'><span class="cm"> *  unp_connect:EISCONN       Socket is connected</span>
</span><span class='line'><span class="cm"> *  unp_connect:EPROTOTYPE    Protocol wrong type for socket</span>
</span><span class='line'><span class="cm"> *  unp_connect:???</span>
</span><span class='line'><span class="cm"> *  sbappendaddr:ENOBUFS      [5th argument, contents modified]</span>
</span><span class='line'><span class="cm"> *  sbappendaddr:???          [whatever a filter author chooses]</span>
</span><span class='line'><span class="cm"> */</span>
</span><span class='line'><span class="k">static</span> <span class="kt">int</span>
</span><span class='line'><span class="nf">uipc_send</span><span class="p">(</span><span class="k">struct</span> <span class="n">socket</span> <span class="o">*</span><span class="n">so</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">mbuf</span> <span class="o">*</span><span class="n">m</span><span class="p">,</span> <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">nam</span><span class="p">,</span>
</span><span class='line'>    <span class="k">struct</span> <span class="n">mbuf</span> <span class="o">*</span><span class="n">control</span><span class="p">,</span> <span class="kt">proc_t</span> <span class="n">p</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'><span class="p">...</span>
</span></code></pre></td></tr></table></div></figure>


<p>Hey look at that! There&rsquo;s handler for the <code>send</code> syscall (although for IPC, not
TCP) that actually documents that it can return <code>EPROTOTYPE</code>! While it doesn&rsquo;t
explain exactly how this can happen, the fact it mentions <code>unp_connect</code> hints
that <code>uipc_send</code> may trigger a connect, and that&rsquo;s exactly what we find a
couple lines into the function:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="p">...</span>
</span><span class='line'>    <span class="cm">/* Connect if not connected yet. */</span>
</span><span class='line'>    <span class="cm">/*</span>
</span><span class='line'><span class="cm">     * Note: A better implementation would complain</span>
</span><span class='line'><span class="cm">     * if not equal to the peer&#39;s address.</span>
</span><span class='line'><span class="cm">     */</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">((</span><span class="n">so</span><span class="o">-&gt;</span><span class="n">so_state</span> <span class="o">&amp;</span> <span class="n">SS_ISCONNECTED</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="n">nam</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">error</span> <span class="o">=</span> <span class="n">unp_connect</span><span class="p">(</span><span class="n">so</span><span class="p">,</span> <span class="n">nam</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="n">error</span><span class="p">)</span>
</span><span class='line'>          <span class="k">break</span><span class="p">;</span>  <span class="cm">/* XXX */</span>
</span><span class='line'>      <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">error</span> <span class="o">=</span> <span class="n">ENOTCONN</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">...</span>
</span></code></pre></td></tr></table></div></figure>


<p>The fact that the comment says the socket might not be connected yet when we&rsquo;re
doing a <code>send</code> hints that Apple may have introduced some level of asynchrony
and preemption to sockets. So if we trigger the actual connect here, it could
then return <code>EPROTOTYPE</code>, which makes sense. Unfortunately that&rsquo;s still not
quite the behavior we&rsquo;re seeing. We&rsquo;re not getting <code>EPROTOTYPE</code> on our first
write, but after we&rsquo;ve done a couple.</p>

<p>I believe we find that behavior in the actual TCP syscall file,
<a href="https://github.com/opensource-apple/xnu/blob/bb7368935f659ada117c0889612e379c97eb83b3/bsd/netinet/tcp_usrreq.c#L914-L948">bsd/netinet/tcp_usrreq.c</a>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="k">static</span> <span class="kt">int</span>
</span><span class='line'><span class="nf">tcp_usr_send</span><span class="p">(</span><span class="k">struct</span> <span class="n">socket</span> <span class="o">*</span><span class="n">so</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="k">struct</span> <span class="n">mbuf</span> <span class="o">*</span><span class="n">m</span><span class="p">,</span>
</span><span class='line'>     <span class="k">struct</span> <span class="n">sockaddr</span> <span class="o">*</span><span class="n">nam</span><span class="p">,</span> <span class="k">struct</span> <span class="n">mbuf</span> <span class="o">*</span><span class="n">control</span><span class="p">,</span> <span class="k">struct</span> <span class="n">proc</span> <span class="o">*</span><span class="n">p</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>  <span class="kt">int</span> <span class="n">error</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>  <span class="k">struct</span> <span class="n">inpcb</span> <span class="o">*</span><span class="n">inp</span> <span class="o">=</span> <span class="n">sotoinpcb</span><span class="p">(</span><span class="n">so</span><span class="p">);</span>
</span><span class='line'>  <span class="k">struct</span> <span class="n">tcpcb</span> <span class="o">*</span><span class="n">tp</span><span class="p">;</span>
</span><span class='line'>  <span class="kt">uint32_t</span> <span class="n">msgpri</span> <span class="o">=</span> <span class="n">MSG_PRI_DEFAULT</span><span class="p">;</span>
</span><span class='line'><span class="cp">#if INET6</span>
</span><span class='line'>  <span class="kt">int</span> <span class="n">isipv6</span><span class="p">;</span>
</span><span class='line'><span class="cp">#endif</span>
</span><span class='line'>  <span class="n">TCPDEBUG0</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">inp</span> <span class="o">==</span> <span class="nb">NULL</span> <span class="o">||</span> <span class="n">inp</span><span class="o">-&gt;</span><span class="n">inp_state</span> <span class="o">==</span> <span class="n">INPCB_STATE_DEAD</span>
</span><span class='line'><span class="cp">#if NECP</span>
</span><span class='line'>    <span class="o">||</span> <span class="p">(</span><span class="n">necp_socket_should_use_flow_divert</span><span class="p">(</span><span class="n">inp</span><span class="p">))</span>
</span><span class='line'><span class="cp">#endif </span><span class="cm">/* NECP */</span><span class="cp"></span>
</span><span class='line'>    <span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="cm">/*</span>
</span><span class='line'><span class="cm">     * OOPS! we lost a race, the TCP session got reset after</span>
</span><span class='line'><span class="cm">     * we checked SS_CANTSENDMORE, eg: while doing uiomove or a</span>
</span><span class='line'><span class="cm">     * network interrupt in the non-splnet() section of sosend().</span>
</span><span class='line'><span class="cm">     */</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="n">m</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span>
</span><span class='line'>      <span class="n">m_freem</span><span class="p">(</span><span class="n">m</span><span class="p">);</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="n">control</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="n">m_freem</span><span class="p">(</span><span class="n">control</span><span class="p">);</span>
</span><span class='line'>      <span class="n">control</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="n">inp</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
</span><span class='line'>      <span class="n">error</span> <span class="o">=</span> <span class="n">ECONNRESET</span><span class="p">;</span>  <span class="cm">/* XXX EPIPE? */</span>
</span><span class='line'>    <span class="k">else</span>
</span><span class='line'>      <span class="n">error</span> <span class="o">=</span> <span class="n">EPROTOTYPE</span><span class="p">;</span>
</span><span class='line'>    <span class="n">tp</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span><span class='line'>    <span class="n">TCPDEBUG1</span><span class="p">();</span>
</span><span class='line'>    <span class="k">goto</span> <span class="n">out</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">...</span>
</span></code></pre></td></tr></table></div></figure>


<p>I believe that comment explains everything we&rsquo;re seeing. If we trigger a <code>send</code>
while the kernel is in the middle of tearing down the socket, it returns
<code>EPROTOTYPE</code>. This then looks to be an error we could retry. Once the socket is
fully torn down, it should eventually return the proper <code>EPIPE</code>. This is also
pretty easy to test. So I modified the inner loop of our C test:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'>  <span class="k">while</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;before send</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="n">rc</span> <span class="o">=</span> <span class="n">send</span><span class="p">(</span><span class="n">client_fd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">),</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;after send: %d</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">rc</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="n">errno</span> <span class="o">==</span> <span class="n">EPIPE</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">errno</span> <span class="o">==</span> <span class="n">EPROTOTYPE</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">continue</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>        <span class="kt">int</span> <span class="n">so_type</span><span class="p">;</span>
</span><span class='line'>        <span class="kt">socklen_t</span> <span class="n">so_len</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">so_type</span><span class="p">);</span>
</span><span class='line'>        <span class="n">getsockopt</span><span class="p">(</span><span class="n">client_fd</span><span class="p">,</span> <span class="n">SOL_SOCKET</span><span class="p">,</span> <span class="n">SO_TYPE</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">so_type</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">so_len</span><span class="p">);</span>
</span><span class='line'>        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;type: %d %d</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">so_type</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="n">perror</span><span class="p">(</span><span class="s">&quot;error send&quot;</span><span class="p">);</span>
</span><span class='line'>        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And yep, it exits cleanly. After all of this, I think it&rsquo;s pretty clear at this
point that there&rsquo;s no weird kernel corruption bug going on, just a poorly
documented edge case. But it sure was fun chasing this condition through the
system.</p>

<p>To prevent anyone else from tripping over this edge case, I filed a Apple Radar
ticket (number #19012087 for any Apple employees reading this). Hopefully if
anyone runs into this mysterious <code>EPROTOTYPE</code> it&rsquo;ll be documented for them, or
at least there&rsquo;s a chance they&rsquo;ll stumble over this blog post and save
themselves a weekend diving through the OS.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rewriting Rust Serialization, Part 2.2: More Benchmarks]]></title>
    <link href="http://erickt.github.io/blog/2014/11/13/benchmarks-2/"/>
    <updated>2014-11-13T09:07:36-08:00</updated>
    <id>http://erickt.github.io/blog/2014/11/13/benchmarks-2</id>
    <content type="html"><![CDATA[<p>Back to the benchmarks! I got some great comments on
<a href="https://www.reddit.com/r/rust/comments/2lzc9n/rust_serialization_part_21_now_with_more/">reddit</a>,
So I wanted to do another post to update my numbers. Here&rsquo;s what I changed:</p>

<ul>
<li>I wasn&rsquo;t consistent on whether or not the serialization benchmarks included
Some tests are including the allocation of a buffer to write into. I&rsquo;ve
  changed it so most are reusing one, which speeds everything up (especially
capnproto-rust!). This does depend on
<a href="https://github.com/rust-lang/rust/pull/18885">#18885</a> landing though.</li>
<li>I&rsquo;ve added <a href="https://github.com/TyOverby/bincode">bincode</a>, which serializes
values as raw bytes. Quite speedy too! Not nearly as fast as Cap&#8217;n Proto though.</li>
<li>I&rsquo;ve changed <code>C++</code> and <code>Rust</code> JSON tests to serialize enums as uints.</li>
<li>I added the time it takes to create the populate the structures. I&rsquo;m betting
  the reason the Rust numbers are so high is that we&rsquo;re allocating strings. Not
sure if the other languages are able to avoid that allocation.</li>
</ul>


<hr />

<p>JSON:</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library         </th>
<th> population (ns) </th>
<th> serialization (MB/s) </th>
<th> deserialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> Rust     </td>
<td> serialize::json </td>
<td> 1127            </td>
<td> 117                  </td>
<td> 26                     </td>
</tr>
<tr>
<td> C++      </td>
<td> rapidjson (dom) </td>
<td> 546             </td>
<td> 281                  </td>
<td> 144                    </td>
</tr>
<tr>
<td> C++      </td>
<td> rapidjson (dom) </td>
<td> 546             </td>
<td> 281                  </td>
<td> 181                    </td>
</tr>
<tr>
<td> Go       </td>
<td> encoding/json   </td>
<td> 343             </td>
<td> 63.99                </td>
<td> 22.46                  </td>
</tr>
<tr>
<td> Go       </td>
<td> ffjson          </td>
<td> 343             </td>
<td> 144.60               </td>
<td> (not supported)        </td>
</tr>
</tbody>
</table>


<hr />

<p>Cap&#8217;n Proto:</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library                   </th>
<th> population (ns) </th>
<th> serialization (MB/s) </th>
<th> deserialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> Rust     </td>
<td> capnproto-rust (unpacked) </td>
<td> 325             </td>
<td> 4977                 </td>
<td> 2251                   </td>
</tr>
<tr>
<td> Rust     </td>
<td> capnproto-rust (packed)   </td>
<td> 325             </td>
<td> 398                  </td>
<td> 246                    </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto              </td>
<td> 2368            </td>
<td> 2226.71              </td>
<td> 450                    </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto (zero copy)  </td>
<td> 2368            </td>
<td> 2226.71              </td>
<td> 1393.3                 </td>
</tr>
</tbody>
</table>


<hr />

<p>Protocol Buffers:</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library       </th>
<th> population (ns) </th>
<th> serialization (MB/s) </th>
<th> deserialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> Rust     </td>
<td> rust-protobuf </td>
<td> 1041            </td>
<td> 370                  </td>
<td> 118                    </td>
</tr>
<tr>
<td> Go       </td>
<td> goprotobuf    </td>
<td> 1133            </td>
<td> 138.27               </td>
<td> 91.18                  </td>
</tr>
<tr>
<td> Go       </td>
<td> gogoprotobuf  </td>
<td> 343             </td>
<td> 472.69               </td>
<td> 295.33                 </td>
</tr>
</tbody>
</table>


<hr />

<p>Misc:</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library      </th>
<th> population (ns) </th>
<th> serialization (MB/s) </th>
<th> deserialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> Rust     </td>
<td> rust-msgpack </td>
<td> 1143            </td>
<td> 454                  </td>
<td> 144                    </td>
</tr>
<tr>
<td> Rust     </td>
<td> bincode      </td>
<td> 1143            </td>
<td> 1149                 </td>
<td> 82                     </td>
</tr>
</tbody>
</table>


<p>Anyone want to add more C/Go/Rust/Java/etc benchmarks?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rewriting Rust Serialization, Part 2.1: Benchmarks]]></title>
    <link href="http://erickt.github.io/blog/2014/11/11/benchmarks/"/>
    <updated>2014-11-11T08:11:34-08:00</updated>
    <id>http://erickt.github.io/blog/2014/11/11/benchmarks</id>
    <content type="html"><![CDATA[<p>After <a href="http://erickt.github.io/blog/2014/11/03/performance/">part 2</a> I received
a couple requests to add in a couple other rust serialization libraries. So one
thing led to another, and now I&rsquo;ve got a benchmark suite I&rsquo;m calling
<a href="https://github.com/erickt/rust-serialization-benchmarks">rust-serialization-benchmarks</a>.
Really creative name, eh? This includes all the other benchmarks I referred to
previously, as well as <a href="https://github.com/dwrensha/capnproto-rust">capnproto</a>,
<a href="https://github.com/mneumann/rust-msgpack">msgpack</a>, and
<a href="https://github.com/stepancheg/rust-protobuf">protobuf</a>.</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library             </th>
<th> format                  </th>
<th> serialization (MB/s) </th>
<th> deserialization (MB/s)   </th>
</tr>
</thead>
<tbody>
<tr>
<td> C++      </td>
<td> rapidjson           </td>
<td> JSON (dom)              </td>
<td> 233                  </td>
<td> 102                      </td>
</tr>
<tr>
<td> C++      </td>
<td> rapidjson           </td>
<td> JSON (sax)              </td>
<td> 233                  </td>
<td> 124                      </td>
</tr>
<tr>
<td> Go       </td>
<td> encoding/json       </td>
<td> JSON                    </td>
<td> 54.93                </td>
<td> 16.72                    </td>
</tr>
<tr>
<td> Go       </td>
<td> ffjson              </td>
<td> JSON                    </td>
<td> 126.40               </td>
<td> (not supported)          </td>
</tr>
<tr>
<td> Go       </td>
<td> goprotobuf          </td>
<td> Protocol Buffers        </td>
<td> 138.27               </td>
<td> 91.18                    </td>
</tr>
<tr>
<td> Go       </td>
<td> gogoprotobuf        </td>
<td> Protocol Buffers        </td>
<td> 472.69               </td>
<td> 295.33                   </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto        </td>
<td> Cap&#8217;n Proto             </td>
<td> 2226.71              </td>
<td> 450                      </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto        </td>
<td> Cap&#8217;n Proto (zero copy) </td>
<td> 2226.71              </td>
<td> 1393.3                   </td>
</tr>
<tr>
<td> Rust     </td>
<td> serialize::json     </td>
<td> JSON                    </td>
<td> 89                   </td>
<td> 18                       </td>
</tr>
<tr>
<td> Rust     </td>
<td> rust-msgpack        </td>
<td> MessagePack             </td>
<td> 160                  </td>
<td> 52                       </td>
</tr>
<tr>
<td> Rust     </td>
<td> rust-protobuf       </td>
<td> Protocol Buffers        </td>
<td> 177                  </td>
<td> 70                       </td>
</tr>
<tr>
<td> Rust     </td>
<td> capnproto-rust      </td>
<td> Cap&#8217;n Proto (unpacked)  </td>
<td> 1729                 </td>
<td> 1276                     </td>
</tr>
<tr>
<td> Rust     </td>
<td> capnproto-rust      </td>
<td> Cap&#8217;n Proto (packed)    </td>
<td> 398                  </td>
<td> 246                      </td>
</tr>
</tbody>
</table>


<p>I upgraded to OS X Yosemite, so I think that brought these numbers down overall
from the last post.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rewriting Rust Serialization, Part 2: Performance]]></title>
    <link href="http://erickt.github.io/blog/2014/11/03/performance/"/>
    <updated>2014-11-03T06:38:38-08:00</updated>
    <id>http://erickt.github.io/blog/2014/11/03/performance</id>
    <content type="html"><![CDATA[<p>As I said in the <a href="http://erickt.github.io/blog/2014/10/28/serialization/">last post</a>,
Rust&rsquo;s <code>serialize</code> library, specifically <code>serialize::json</code> is pretty slow.
Back when I started this project a number of months ago, I wanted to benchmark
to see how we compared to some other languages. There are a bunch of JSON
benchmarks, but the one I chose was Cloudflare&rsquo;s Go language.
<a href="https://github.com/cloudflare/goser">Goser</a>, mainly because it was using a
complex real world log structure, and they did the hard work of implementing
benchmarks for <a href="http://golang.org/pkg/encoding/json">encoding/json</a>,
<a href="http://code.google.com/p/goprotobuf/">goprotobuf</a>,
<a href="http://code.google.com/p/gogoprotobuf/">gogoprotobuf</a>, and
<a href="https://github.com/glycerine/go-capnproto">go-capnproto</a>. I also included the
Go <a href="https://github.com/pquerna/ffjson">ffjson</a> and C++
<a href="https://github.com/erickt/rapidjson/blob/master/log.cc">rapidjson</a>, which
both claim to be the fastest JSON libraries for those languages. Here are the
results I got:</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library             </th>
<th> format           </th>
<th> serialization (MB/s) </th>
<th> deserialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> C++      </td>
<td> rapidjson           </td>
<td> JSON             </td>
<td> 294                  </td>
<td> 164 (DOM) / 192 (SAX)  </td>
</tr>
<tr>
<td> Go       </td>
<td> encoding/json       </td>
<td> JSON             </td>
<td> 71.47                </td>
<td> 25.09                  </td>
</tr>
<tr>
<td> Go       </td>
<td> ffjson              </td>
<td> JSON             </td>
<td> 156.67               </td>
<td> (not supported)        </td>
</tr>
<tr>
<td> Go       </td>
<td> goprotobuf          </td>
<td> Protocol Buffers </td>
<td> 148.78               </td>
<td> 99.57                  </td>
</tr>
<tr>
<td> Go       </td>
<td> gogoprotobuf        </td>
<td> Protocol Buffers </td>
<td> 519.48               </td>
<td> 319.40                 </td>
</tr>
<tr>
<td> Go       </td>
<td> go-capnproto        </td>
<td> Cap&#8217;n Proto      </td>
<td> 3419.54              </td>
<td> 665.35                 </td>
</tr>
<tr>
<td> Rust     </td>
<td> serialize::json     </td>
<td> JSON             </td>
<td> 40-ish               </td>
<td> 10-ish                 </td>
</tr>
</tbody>
</table>


<p>Notes:</p>

<ul>
<li><code>rapidjson</code> supports both DOM-style and SAX-style deserializing. DOM-style
means deserializing into a generic object, then from there into the final
object, SAX-style means a callback approach where a callback handler is
called for each JSON token.</li>
<li>Go&rsquo;s <code>encoding/json</code> uses reflection to serialize arbitrary values. <code>ffjson</code>
uses code generation to get it&rsquo;s serialization sped, but it doesn&rsquo;t implement
deserialization.</li>
<li>both <code>goprotobuf</code> and <code>gogoprotobuf</code> use code generation, but gogoprotobuf
uses Protocol Buffer&rsquo;s extension support to do cheaper serialization.</li>
<li>Cap&#8217;n Proto doesn&rsquo;t really do serialization, but lays the serialized data out
just like it is in memory so it has nearly zero serialization speed.</li>
<li>The Rust numbers are from a couple months ago and I couldn&rsquo;t track down
the exact numbers.</li>
</ul>


<p>So. Yikes. Not only are we no where near <code>rapidjson</code>, we were being soundly
beaten by Go&rsquo;s reflection-based framework <code>encoding/json</code>.  Even worse, our
compile time was at least 10 times theirs. So, not pretty at all.</p>

<p>But that was a couple months ago. Between then and now, Patrick Walton, Luqman
Aden, myself, and probably lots others found and fixed a number of bugs across
<code>serialize::json</code>, <code>std::io</code>, generic function calls, and more. All this work
got us to more than double our performance:</p>

<table>
<thead>
<tr>
<th> language </th>
<th> library           </th>
<th> format               </th>
<th> serialization (MB/s)   </th>
<th> deserialization (MB/s) </th>
</tr>
</thead>
<tbody>
<tr>
<td> Rust     </td>
<td> serialize::json   </td>
<td> JSON                 </td>
<td> 117                    </td>
<td> 25                     </td>
</tr>
</tbody>
</table>


<p>We&rsquo;re (kind of) beating Go! At least the builtin reflection-based solution.
Better, but not great. I think our challenge is those dang closures. While LLVM
can optimize simple closures, it seems to have a lot of trouble with all these
recursive closure calls. While having finished unboxed closures might finally
let us break through this performance bottleneck, it&rsquo;s not guaranteed.</p>

<p>All in all, this, and the representational problems from
<a href="http://erickt.github.io/blog/2014/10/28/serialization/">post 1</a> make it pretty
obvious we got some fundamental issues here and we need to use an alternative
solution. Next post I&rsquo;ll start getting into the details of the design of
<a href="https://github.com/erickt/rust-serde">serde</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rewriting Rust Serialization, Part 1]]></title>
    <link href="http://erickt.github.io/blog/2014/10/28/serialization/"/>
    <updated>2014-10-28T08:52:18-07:00</updated>
    <id>http://erickt.github.io/blog/2014/10/28/serialization</id>
    <content type="html"><![CDATA[<p>Hello everybody! It&rsquo;s been, what, <em>two</em> years since I last blogged? Not my best
performance, I&rsquo;m sorry to say. So for all of my 3 pageviews that are probably
bots, I appologize for such a long delay on updating my blog. I got to say I&rsquo;ve
been pretty inspired by the great <a href="http://jvns.ca/">Julia Evans</a> (who I hope we
can someday get back to working on rust stuff). She&rsquo;s an epic blogger, and I
hope I can get somewhere near that speed.</p>

<p>Anyway, on to the post. My main on-again-off-again project this past year has
been working Rust&rsquo;s generic <a href="http://doc.rust-lang.org/serialize/">serialize</a>
library. If you haven&rsquo;t played with it yet, it&rsquo;s really nifty. It&rsquo;s a generic
framework that allows a generic <code>Encoder</code> serialize a generic <code>Encodable</code>, and
the inverse with <code>Decoder</code> and <code>Decodable</code>. This allows you to write just one
<code>Encodable</code> impl that can transparently work with our
<a href="http://doc.rust-lang.org/serialize/">json</a> library,
<a href="https://github.com/mneumann/rust-msgpack">msgpack</a>,
<a href="https://github.com/alexcrichton/toml-rs">toml</a>, and etc. It&rsquo;s simple to use
too in most cases as you can use <code>#[deriving(Encodable, Decodable)]</code> to
automatically create a implementation for your type. Here&rsquo;s an example:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">serialize</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kn">use</span> <span class="n">serialize</span><span class="o">::</span><span class="n">json</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[deriving(Encodable, Decodable, Show)]</span>
</span><span class='line'><span class="k">struct</span> <span class="n">Employee</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">name</span><span class="o">:</span> <span class="n">String</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[deriving(Encodable, Decodable, Show)]</span>
</span><span class='line'><span class="k">struct</span> <span class="n">Company</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">employees</span><span class="o">:</span> <span class="n">Vec</span><span class="o">&lt;</span><span class="n">Employee</span><span class="o">&gt;</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">company</span> <span class="o">=</span> <span class="n">Company</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">employees</span><span class="o">:</span> <span class="n">vec</span><span class="o">!</span><span class="p">[</span>
</span><span class='line'>            <span class="n">Employee</span> <span class="p">{</span> <span class="n">name</span><span class="o">:</span> <span class="s">&quot;Dan&quot;</span><span class="p">.</span><span class="n">to_string</span><span class="p">()</span> <span class="p">},</span>
</span><span class='line'>            <span class="n">Employee</span> <span class="p">{</span> <span class="n">name</span><span class="o">:</span> <span class="s">&quot;Erin&quot;</span><span class="p">.</span><span class="n">to_string</span><span class="p">()</span> <span class="p">},</span>
</span><span class='line'>            <span class="n">Employee</span> <span class="p">{</span> <span class="n">name</span><span class="o">:</span> <span class="s">&quot;Jeff&quot;</span><span class="p">.</span><span class="n">to_string</span><span class="p">()</span> <span class="p">},</span>
</span><span class='line'>            <span class="n">Employee</span> <span class="p">{</span> <span class="n">name</span><span class="o">:</span> <span class="s">&quot;Spencer&quot;</span><span class="p">.</span><span class="n">to_string</span><span class="p">()</span> <span class="p">},</span>
</span><span class='line'>        <span class="p">],</span>
</span><span class='line'>    <span class="p">};</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="n">s</span> <span class="o">=</span> <span class="n">json</span><span class="o">::</span><span class="n">encode</span><span class="p">(</span><span class="o">&amp;</span><span class="n">company</span><span class="p">);</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">company</span><span class="o">:</span> <span class="n">Company</span> <span class="o">=</span> <span class="n">json</span><span class="o">::</span><span class="n">decode</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">as_slice</span><span class="p">()).</span><span class="n">unwrap</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>There are some downsides to serialize though. Manually implementing can be a
bit of a pain. Here&rsquo;s the example from before:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="n">S</span><span class="o">:</span> <span class="n">Encoder</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="n">Encodable</span><span class="o">&lt;</span><span class="n">S</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="k">for</span> <span class="n">Employee</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">encode</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">S</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">match</span> <span class="o">*</span><span class="bp">self</span> <span class="p">{</span>
</span><span class='line'>            <span class="n">Employee</span> <span class="p">{</span> <span class="n">name</span><span class="o">:</span> <span class="k">ref</span> <span class="n">name</span> <span class="p">}</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">s</span><span class="p">.</span><span class="n">emit_struct</span><span class="p">(</span><span class="s">&quot;Employee&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="k">u</span><span class="p">,</span> <span class="o">|</span><span class="n">s</span><span class="o">|</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">s</span><span class="p">.</span><span class="n">emit_struct_field</span><span class="p">(</span><span class="s">&quot;name&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="k">u</span><span class="p">,</span> <span class="o">|</span><span class="n">s</span><span class="o">|</span> <span class="n">name</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="n">s</span><span class="p">))</span>
</span><span class='line'>                <span class="p">})</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">impl</span><span class="o">&lt;</span><span class="n">D</span><span class="o">:</span> <span class="n">Decoder</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="n">Decodable</span><span class="o">&lt;</span><span class="n">D</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="k">for</span> <span class="n">Employee</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">fn</span> <span class="n">decode</span><span class="p">(</span><span class="n">d</span><span class="o">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">D</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">Employee</span><span class="p">,</span> <span class="n">E</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">d</span><span class="p">.</span><span class="n">read_struct</span><span class="p">(</span><span class="s">&quot;Employee&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="k">u</span><span class="p">,</span> <span class="o">|</span><span class="n">d</span><span class="o">|</span> <span class="p">{</span>
</span><span class='line'>            <span class="nb">Ok</span><span class="p">(</span><span class="n">Employee</span> <span class="p">{</span>
</span><span class='line'>                <span class="n">name</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>                    <span class="n">try</span><span class="o">!</span><span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">read_struct_field</span><span class="p">(</span><span class="s">&quot;name&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="k">u</span><span class="p">,</span> <span class="o">|</span><span class="n">d</span><span class="o">|</span> <span class="p">{</span>
</span><span class='line'>                        <span class="n">Decodable</span><span class="o">::</span><span class="n">decode</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
</span><span class='line'>                    <span class="p">}))</span>
</span><span class='line'>                <span class="p">}</span>
</span><span class='line'>            <span class="p">})</span>
</span><span class='line'>        <span class="p">})</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>As you can see, parsing compound structures requires these recursive closure
calls in order to perform the handshake between the <code>Encoder</code> and the
<code>Encodable</code>. A couple people have run into bugs in the past where they didn&rsquo;t
implement this pattern, which results in some confusing bugs. Furthermore, LLVM
isn&rsquo;t great at inlining these recursive calls, so <code>serialize</code> impls tend to not
perform well.</p>

<p>That&rsquo;s not the worst of it though. The real problem is that there are types
that can implement <code>Encodable</code>, there&rsquo;s no way to write a <code>Decodable</code>
implementation. They&rsquo;re pretty common too. For example, the
<code>serialize::json::Json</code> type:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span> <span class="k">enum</span> <span class="n">Json</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">I64</span><span class="p">(</span><span class="kt">i64</span><span class="p">),</span>
</span><span class='line'>    <span class="n">U64</span><span class="p">(</span><span class="kt">u64</span><span class="p">),</span>
</span><span class='line'>    <span class="n">F64</span><span class="p">(</span><span class="kt">f64</span><span class="p">),</span>
</span><span class='line'>    <span class="n">String</span><span class="p">(</span><span class="n">string</span><span class="o">::</span><span class="n">String</span><span class="p">),</span>
</span><span class='line'>    <span class="n">Boolean</span><span class="p">(</span><span class="kt">bool</span><span class="p">),</span>
</span><span class='line'>    <span class="n">List</span><span class="p">(</span><span class="n">JsonList</span><span class="p">),</span>
</span><span class='line'>    <span class="n">Object</span><span class="p">(</span><span class="n">JsonObject</span><span class="p">),</span>
</span><span class='line'>    <span class="n">Null</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">pub</span> <span class="k">type</span> <span class="n">JsonList</span> <span class="o">=</span> <span class="n">Vec</span><span class="o">&lt;</span><span class="n">Json</span><span class="o">&gt;</span><span class="p">;</span>
</span><span class='line'><span class="k">pub</span> <span class="k">type</span> <span class="n">JsonObject</span> <span class="o">=</span> <span class="n">TreeMap</span><span class="o">&lt;</span><span class="n">string</span><span class="o">::</span><span class="n">String</span><span class="p">,</span> <span class="n">Json</span><span class="o">&gt;</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>The <code>Json</code> value can represent any value that&rsquo;s in a JSON string. Implied in
this is the notion that the <code>Decodable</code> has to look ahead to see what the next
value is so it can decide which <code>Json</code> variant to construct. Unfortunately our
current <code>Decoder</code> infrastructure doesn&rsquo;t support lookahead. The way the
<code>Decoder</code>/<code>Decodable</code> handshake works is essentially:</p>

<ul>
<li><code>Decodable</code> asks for a struct named <code>"Employee"</code>.</li>
<li><code>Decodable</code> asks for a field named <code>"name"</code>.</li>
<li><code>Decodable</code> asks for a value of type <code>String</code>.</li>
<li><code>Decodable</code> asks for a field named <code>"age"</code>.</li>
<li><code>Decodable</code> asks for a value of type <code>uint</code>.</li>
<li>&hellip;</li>
</ul>


<p>Any deviation from this pattern results in an error. There isn&rsquo;t a way for the
<code>Decodable</code> to ask what is the type of the next value, so this is why we
serialize generic enums by explicitly tagging the variant, as in:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span> <span class="n">crate</span> <span class="n">serialize</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kn">use</span> <span class="n">serialize</span><span class="o">::</span><span class="n">json</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#[deriving(Encodable, Decodable, Show)]</span>
</span><span class='line'><span class="k">enum</span> <span class="n">Animal</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">Dog</span><span class="p">(</span><span class="kt">uint</span><span class="p">),</span>
</span><span class='line'>    <span class="n">Frog</span><span class="p">(</span><span class="n">String</span><span class="p">,</span> <span class="kt">uint</span><span class="p">),</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="n">animal</span> <span class="o">=</span> <span class="n">Frog</span><span class="p">(</span><span class="s">&quot;Frank&quot;</span><span class="p">.</span><span class="n">to_string</span><span class="p">(),</span> <span class="mi">349</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">let</span> <span class="n">s</span> <span class="o">=</span> <span class="n">json</span><span class="o">::</span><span class="n">encode</span><span class="p">(</span><span class="o">&amp;</span><span class="n">animal</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="nb">println</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;{}&quot;</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span>
</span><span class='line'>    <span class="c1">// prints {&quot;variant&quot;:&quot;Frog&quot;,&quot;fields&quot;:[&quot;Frank&quot;,349]}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>That&rsquo;s probably good enough for now. In my next post I&rsquo;ll go into in my
approach to fix this in <a href="https://github.com/erickt/rust-serde">serde</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rust for Ragel]]></title>
    <link href="http://erickt.github.io/blog/2012/07/29/rust-for-ragel/"/>
    <updated>2012-07-29T10:20:00-07:00</updated>
    <id>http://erickt.github.io/blog/2012/07/29/rust-for-ragel</id>
    <content type="html"><![CDATA[<p>I&rsquo;ve written a bunch of simple parsers for Rust, and it&rsquo;s starting to get a
little obnoxious. So I added a Rust backend to the
<a href="http://www.complang.org/ragel/">Ragel State Machine Compiler</a>.
You can find my fork <a href="https://github.com/erickt/ragel">here</a>. I&rsquo;m waiting for
Rust to stablize before I try to push it upstream.</p>

<p>Ragel is a rather neat way of writing simple parsers. In some ways it&rsquo;s pretty
similar to Lex, but Ragel also allows you execute arbitrary code at any point
in the state machine. Furthermore, this arbitrary code can manipulate the state
machine itself, so it can be used in many places you&rsquo;d traditionally need a
full parser, such as properly handling parentheses.</p>

<p>Here&rsquo;s an example of a <code>atoi</code> function:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>%%{
</span><span class='line'>machine atoi;
</span><span class='line'>
</span><span class='line'>action see_neg   { neg = true; }
</span><span class='line'>action add_digit { res = res * 10 + (fc as int - '0' as int); }
</span><span class='line'>
</span><span class='line'>main :=
</span><span class='line'>    ( '-' @see_neg | '+' )? ( digit @add_digit )+
</span><span class='line'>    '\n'?
</span><span class='line'>;
</span><span class='line'>
</span><span class='line'>write data;
</span><span class='line'>}%%
</span><span class='line'>
</span><span class='line'>fn atoi(data: ~str) -&gt; option&lt;int&gt; {
</span><span class='line'>    let mut neg = false;
</span><span class='line'>    let mut res = 0;
</span><span class='line'>
</span><span class='line'>    // Ragel assumes that it will be iterating over a value called data, but we
</span><span class='line'>    // need to tell ragel where to start (p) and end (pe) parsing.
</span><span class='line'>    let mut p = 0;
</span><span class='line'>    let mut pe = data.len();
</span><span class='line'>
</span><span class='line'>    // This is the current state in the state machine.
</span><span class='line'>    let mut cs: int;
</span><span class='line'>
</span><span class='line'>    write init;
</span><span class='line'>    write exec;
</span><span class='line'>
</span><span class='line'>    if neg { res = -1 * res; }
</span><span class='line'>
</span><span class='line'>    // If we stopped before we hit one of the exit states, then there must have
</span><span class='line'>    // been an error of some sort.
</span><span class='line'>    if cs &lt; atoi_first_final {
</span><span class='line'>        none
</span><span class='line'>    } else {
</span><span class='line'>        some(res)
</span><span class='line'>    }
</span><span class='line'>}</span></code></pre></td></tr></table></div></figure>


<p>While this is probably a bit more verbose than writing <code>atoi</code> by hand, it does
make the grammar pretty explicit, which can help keep it accurate.</p>

<p>Unfortunately there are some pretty severe performance issues at the moment.
Ragel supports two state machine styles, table-driven and goto-driven. My
backend uses tables, but since Rust doesn&rsquo;t yet support global constant
vectors, I need to malloc the state machine table on every function call. This
results in the <a href="https://github.com/erickt/ragel/blob/rust/examples/rust/url.rl">ragel-based url
parser</a> being about
10 times slower than the equivalent table-based parser in OCaml. You can see
the generated code <a href="https://gist.github.com/3200980">here</a>.</p>

<p>The <code>goto</code> route could be promising to explore. We could simulate it using
mutually recursive function calls. OCaml does this. But again, since Rust
doesn&rsquo;t support tailcalls (and may
<a href="https://github.com/mozilla/rust/issues/217">ever</a>), we could run into a stack
explosion. It may work well for small grammars though, and maybe LLVM could
optimize calls into tailcalls.</p>

<p>Unless I&rsquo;m doing something glaringly wrong, it seems likely that we are going
to need some compiler help before these performance issues get solved.</p>
]]></content>
  </entry>
  
</feed>
