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

  <title>sasheldon.com</title>
  <link href="http://sasheldon.com/blog/atom.xml" rel="self"/>
  <link href="http://sasheldon.com/"/>
  <updated>2025-12-29T13:13:13-06:00</updated>
  <id>http://sasheldon.com/</id>
  <author>
    <name>Steven Sheldon</name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html">Designing my own keyboard alpha layout for comfy inrolls</title>
    <link href="http://sasheldon.com/blog/2025/12/28/designing-keyboard-alpha-layout/"/>
    <updated>2025-12-29T00:00:00-06:00</updated>
    <id>http://sasheldon.com/blog/2025/12/28/designing-keyboard-alpha-layout</id>
    <content type="html">&lt;p&gt;Last year, the discomfort in my arms after using the computer got too bad to
continue ignoring, and I ordered my first ergonomic keyboard, the
&lt;a href=&quot;https://www.moergo.com/pages/glove80&quot;&gt;MoErgo Glove80&lt;/a&gt;. This was my first time
using a columnar keyboard, and my first programmable keyboard.
I expected to make some layout customizations; obviously the layout on this
new keyboard couldn&amp;rsquo;t match the keyboards I was used to.
But I didn&amp;rsquo;t expect how, when you&amp;rsquo;re using a totally new form factor and
can customize every part of the layout,
there&amp;rsquo;s really no reason not to customize deeply!&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;Ultimately this led me to designing my own alpha layout with inspiration from
other alternative layouts.
I switched to it at the start of the year and have been enjoying typing with it!
I prioritized finger utilization I found comfortable and inward rolling:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;x c l d k  z y o u q
r s t h f  p n e i a
w v g m j  ↵ b &amp;#39; . ,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#background&quot;&gt;Background&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#learning&quot;&gt;Learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#basics-of-layout-design&quot;&gt;Basics of layout design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#my-design-goals&quot;&gt;My design goals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#design-process&quot;&gt;Design process&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#vowels&quot;&gt;Vowels&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#consonants&quot;&gt;Consonants&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#punctuation&quot;&gt;Punctuation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#enter&quot;&gt;Enter?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#metrics&quot;&gt;Metrics&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#finger-utilization&quot;&gt;Finger utilization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#in-rolls&quot;&gt;In-rolls&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#redirects&quot;&gt;Redirects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#same-finger-usage&quot;&gt;Same finger usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#scissors-and-lateral-stretches&quot;&gt;Scissors and lateral stretches&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#thoughts-from-a-year-of-usage&quot;&gt;Thoughts from a year of usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#why-i-wrote-this&quot;&gt;Why I wrote this&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#resources-and-additional-reading&quot;&gt;Resources and additional reading&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;

&lt;p&gt;I originally intended to keep using QWERTY on my new keyboard.
Surely my existing muscle memory would be far more valuable than any minor
improvements to be gained from a new alpha layout.
Until I started using a columnar keyboard for the first time,
with fingers strictly assigned to keys, and realized:
my typing previously on QWERTY was nothing like this,
and using QWERTY this way kind of sucked.&lt;/p&gt;

&lt;p&gt;Using QWERTY with strictly assigned fingers raised a lot of questions.
Why did I so often have to type multiple letters in a row with the same finger?
Why did I so frequently have to reach with my index fingers for &lt;code&gt;t&lt;/code&gt;, &lt;code&gt;n&lt;/code&gt;, and &lt;code&gt;h&lt;/code&gt;?
Why was I resting my right hand on these home keys if they are so rarely used?
Why did I have to reach my right pinky to the top row for &lt;code&gt;p&lt;/code&gt; when its home
position was the rarely used &lt;code&gt;;&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;I realized that I had been avoiding a lot of these issues by not strictly using
fingers for certain keys. I learned that it&amp;rsquo;s common among QWERTY typists to
work around using the same finger repeatedly by using different fingers to hit
a key, a technique called &amp;ldquo;alt fingering&amp;rdquo;.
Even beyond this, my QWERTY typing had idiosyncrasies:
I type &lt;code&gt;the&lt;/code&gt; entirely with my left hand (middle-index-ring),
I barely use my right ring finger and never use my right pinky, and
I even hit the space bar with my right index finger.&lt;/p&gt;

&lt;p&gt;This meant that, for me, typing QWERTY on columnar was basically learning an
entirely new layout. I was typing really slowly and would need a lot of practice,
and I would be putting in all this effort to re-learn to type
with a layout that didn&amp;rsquo;t even perform well with strictly assigned fingers.&lt;/p&gt;

&lt;h2 id=&quot;learning&quot;&gt;Learning&lt;/h2&gt;

&lt;p&gt;Before we get into this process of designing a keyboard layout,
if you haven&amp;rsquo;t learned to use an alternative layout before,
you may be thinking that switching is prohibitively difficult.
The process of learning a new layout wasn&amp;rsquo;t as bad as I expected!&lt;/p&gt;

&lt;p&gt;When I got my first split columnar keyboard, I re-learned how to type three times
over the following months. I started out using columnar QWERTY for ~1 month,
then switched to an alternative layout designed to be similar to QWERTY for ~3 months,
then finally switched to the custom layout described in this post.
Learning for the third time seemed easier than the previous times.
I started practicing during a lazy holiday week off work and then
went back to work using it (clumsily). After a little over a month I started
hitting 70 wpm in typing tests, and now after a year I&amp;rsquo;ve hit 90 wpm in tests.&lt;/p&gt;

&lt;p&gt;To learn, I started out using &lt;a href=&quot;https://www.keybr.com/&quot;&gt;keybr&lt;/a&gt;,
which gradually adds additional letters for you to learn.
Once I had unlocked all letters there, I switched to &lt;a href=&quot;https://monkeytype.com/&quot;&gt;Monkeytype&lt;/a&gt;,
which offers more options and has a fun collection of quotes to practice with.&lt;/p&gt;

&lt;p&gt;The process of learning a new layout is frustrating at times, like when
I wanted to quickly type out an idea but was still too clumsy to do so.
But I also found it fun, and, strangely, I kind of miss it.
Typing practice was meditative for me, a good way to clear my head,
and it reminded me of practicing a musical instrument.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve only use alternative keyboard layouts on my split columnar keyboards;
I continue to use QWERTY on my laptop and any other unibody row-staggered keyboards.
I experienced a bit of confusion during the learning process,
but that cleared up as my muscle memory solidified,
so now I can easily switch between using the different kinds of keyboards.
Having such different form factors between the two seems to help maintain
separate muscle memory.&lt;/p&gt;

&lt;p&gt;I believe I still type faster on QWERTY than on my custom layout (~100 wpm),
but I don&amp;rsquo;t regularly take QWERTY typing tests to know for sure.
This is a little demoralizing after so much practice,
but it makes sense given the many years I&amp;rsquo;ve been typing QWERTY.
And I remind myself that the switch wasn&amp;rsquo;t about speed;
I may type faster on my laptop keyboard, but after using it for a while
I can feel the familiar forearm and wrist aches returning.&lt;/p&gt;

&lt;h2 id=&quot;basics-of-layout-design&quot;&gt;Basics of layout design&lt;/h2&gt;

&lt;p&gt;When I started researching alternative keyboard layouts, I thought I&amp;rsquo;d just
find the best, most optimal one and pick that.
Well, it turns out that&amp;rsquo;s not so easy to define.
There&amp;rsquo;s a passionate community using metrics to rigorously analyze layouts, but
there&amp;rsquo;s no obvious way to define a metric for how &amp;ldquo;good&amp;rdquo; a keyboard layout is.
Instead, we usually look for patterns that feel comfortable or uncomfortable,
and then try to formally define them and measure how frequently they occur.
Each layout optimizes for a different balance of these metrics.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o&quot;&gt;Ec0&amp;rsquo;s Keyboard layouts doc&lt;/a&gt; is the the best source for understanding how
modern layouts are designed and the metrics used. One of the basic metrics is
the frequency of &lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.84dl8gsr8by7#heading=h.11zdpmpqdkga&quot;&gt;&amp;ldquo;same finger bigrams&amp;rdquo; (SFBs)&lt;/a&gt;
which measures how often the same finger has to type two keys in a row.
There are metrics to measure how often fingers have to stretch apart
&lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.3j7hpqkn3etl#heading=h.52yn1he03w10&quot;&gt;vertically (scissors)&lt;/a&gt; or
&lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.i8oe0bwffr95#heading=h.gmkonyyr2tww&quot;&gt;horizontally (lateral stretch bigrams, LSBs)&lt;/a&gt;.
More advanced metrics look at &lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.6r1v629nms0d#heading=h.mabm585mao3e&quot;&gt;trigrams&lt;/a&gt;, 3-key sequences,
to evaluate how often typing switches between hands (alternation), or
uses the same hand flowing in a consistent direction (rolling), or
uses the same hand but with awkward changes in direction (redirects).
Some analyzers assign effort values to key positions to quantify how difficult
typing common words feels.&lt;/p&gt;

&lt;p&gt;All of these metrics make layout design a fascinating puzzle, where it&amp;rsquo;s
impossible to maximize every metric at once, and the layout designer must
decide what trade-offs to make to maximize metrics for their preferred patterns.&lt;/p&gt;

&lt;h2 id=&quot;my-design-goals&quot;&gt;My design goals&lt;/h2&gt;

&lt;p&gt;When I first started using my new keyboard, I quickly found that I was not
accustomed to typing with all 10 fingers, and some felt strained from the adjustment.
I found that I had used my middle fingers for many keys previously,
but now they were down to only 3 letters. Maybe I have short pinkies or
suboptimal hand positioning, but I found the top row pinky keys required
a stretch that was not comfortable for me to perform frequently.&lt;/p&gt;

&lt;p&gt;These observations led to comfortable finger utilization being my primary goal.
I wanted my middle fingers to have the most utilization, followed by index, ring,
and pinky, and I wanted to only have low frequency keys for the top row pinky keys.&lt;/p&gt;

&lt;p&gt;In hindsight, I&amp;rsquo;m not sure utilization was exactly the right metric. I now think
that finger movement (moving between keys) is more impactful than utilization;
I feel less strain on a finger that mostly presses a single key than a finger
that regularly switches between multiple, even if the single key is frequently used.
Fortunately, utilization does correlate somewhat with movement, so I ended up
in roughly the right place. Over time I have found that my weaker fingers have
grown more comfortable typing, so I think I could have adapted to a layout
that used them more, but perhaps it was good to not push my luck.&lt;/p&gt;

&lt;p&gt;After finger utilization, I decided I wanted to prioritize inward rolling.
When I first read about inward rolling (from pinky to index) vs
outward rolling (from index to pinky), I was surprised to compare
how much clumsier it felt to roll my fingers outwards.
I&amp;rsquo;m not sure how much this actually matters in typing,
so I didn&amp;rsquo;t zealously avoid all outward rolling,
but it was at least a fun little challenge to optimize around.&lt;/p&gt;

&lt;p&gt;Although I wanted to prioritize inward rolling, I didn&amp;rsquo;t want redirects to
become too frequent. If some rolls came with too many redirects,
I would prefer having alternation instead.&lt;/p&gt;

&lt;p&gt;Like all modern layouts, I wanted to minimize same finger bigrams, but
I found I wasn&amp;rsquo;t so sensitive to them that I&amp;rsquo;d prioritize this over my other goals.
I was hoping for SFBs a bit better than Colemak, but I knew I wouldn&amp;rsquo;t beat the
SFB rates of the newest layouts (especially ones with thumb alphas or magic keys).
I didn&amp;rsquo;t even consider same finger skipgrams;
just avoiding SFBs already felt luxurious enough coming from QWERTY.&lt;/p&gt;

&lt;p&gt;In the end, my priority ranking came to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Finger utilization&lt;/li&gt;
&lt;li&gt;High in-rolls&lt;/li&gt;
&lt;li&gt;Low redirects&lt;/li&gt;
&lt;li&gt;Low same finger bigrams&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;design-process&quot;&gt;Design process&lt;/h2&gt;

&lt;p&gt;With these goals established, how do we design a layout optimized for them?&lt;/p&gt;

&lt;p&gt;First, we should quantify the finger utilization targets. I chose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Index: 12-14%&lt;/li&gt;
&lt;li&gt;Middle: 16-18%&lt;/li&gt;
&lt;li&gt;Ring: 10-12%&lt;/li&gt;
&lt;li&gt;Pinky: 8-9%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The foundation of a layout is &lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.oldl5e1xa7v3#heading=h.fkc9oxga9jo9&quot;&gt;its placement of the 9 most common letters&lt;/a&gt;.
Modern layouts place all vowels on the same hand (in order to reduce redirects),
with &lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.gm0ejchjpek#heading=h.fy0chzg26unh&quot;&gt;the 4 most common vowels on three fingers&lt;/a&gt;
(in order to leave more room for placing the many consonants).
Let&amp;rsquo;s start &lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.uv9x1j70u2nc#heading=h.8grvg0w34swn&quot;&gt;designing the layout as recommended&lt;/a&gt; with the vowel hand!&lt;/p&gt;

&lt;h3 id=&quot;vowels&quot;&gt;Vowels&lt;/h3&gt;

&lt;p&gt;Laying out the vowel hand starts with choosing the vowel block.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.2yb5bwiy1wa8#heading=h.qyel7qja61lm&quot;&gt;The vowel block with highest inrolls&lt;/a&gt; is &lt;code&gt;yi oe ua&lt;/code&gt;.
The &lt;code&gt;oe&lt;/code&gt; stack would have utilization far past the target for ring,
so this would require &lt;code&gt;ua&lt;/code&gt; on index.
This means we&amp;rsquo;d have to push more consonants off the index finger to keep SFBs low,
and ultimately this leads to violating the finger utilization goal,
like adding more letters onto pinky;
therefore, let&amp;rsquo;s only consider vowel blocks that do not include index.&lt;/p&gt;

&lt;p&gt;The next best vowel block for inrolls is &lt;code&gt;yi oa ue&lt;/code&gt;, and
while &lt;code&gt;oa&lt;/code&gt; has less utilization than &lt;code&gt;oe&lt;/code&gt;, that&amp;rsquo;s still a lot for ring,
especially with a very common letter off the home row.
&lt;code&gt;i ue oa&lt;/code&gt; is next; this has the ring finger moving off home row far less often,
so it could be viable, but it still already means over 14% utilization for ring,
which is higher than the target.&lt;/p&gt;

&lt;p&gt;This leads us to &lt;code&gt;a ui oe&lt;/code&gt;. Although it doesn&amp;rsquo;t have the highest inrolls,
its utilization is closer to what we&amp;rsquo;re looking for. &lt;code&gt;oe&lt;/code&gt; alone is over 19%
utilization, but as long as we don&amp;rsquo;t add anything else common to the column,
it&amp;rsquo;s not too far past the middle finger utilization target&amp;rsquo;s 18% upper bound.&lt;/p&gt;

&lt;p&gt;With the vowel block chosen, we can begin laying out consonants on the vowel hand.
High-inroll layouts (usually) have
&lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.2yb5bwiy1wa8#heading=h.b3afrbm4ggth&quot;&gt;either &lt;code&gt;n&lt;/code&gt; on the vowel hand index or &lt;code&gt;h&lt;/code&gt; on the vowel hand pinky&lt;/a&gt;,
so &lt;code&gt;n&lt;/code&gt; index it is!
Let&amp;rsquo;s not stack another common consonant &lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.uv9x1j70u2nc#heading=h.cjrto5uint97&quot;&gt;like &lt;code&gt;r&lt;/code&gt;&lt;/a&gt; on the index,
because that would exceed the utilization target and limit our options
for the remaining 4 keys.&lt;/p&gt;

&lt;p&gt;I paired &lt;code&gt;y&lt;/code&gt; with &lt;code&gt;n&lt;/code&gt;, even though that leads to some moderate SFBs,
because then we have a &lt;code&gt;you&lt;/code&gt; three-roll,
and that just feels so dang nice (even as an outroll).
We&amp;rsquo;ll fill out the rest of this index later when laying out the consonants.&lt;/p&gt;

&lt;p&gt;For a low-utilization key for top vowel pinky, I chose &lt;code&gt;q&lt;/code&gt;.
This does mean a redirect for &lt;code&gt;equ&lt;/code&gt;, an SFB for &lt;code&gt;aqu&lt;/code&gt;, and an SFS for &lt;code&gt;qua&lt;/code&gt;, but
the guaranteed &lt;code&gt;qu&lt;/code&gt; inroll is nice, and &lt;code&gt;quo&lt;/code&gt; feels great and &lt;code&gt;que&lt;/code&gt; feels pretty good.&lt;/p&gt;

&lt;p&gt;At this point, we&amp;rsquo;ve laid out most of the vowel hand:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;☐ ☐ ☐ ☐ ☐  ☐ y o u q
☐ ☐ ☐ ☐ ☐  ☐ n e i a
☐ ☐ ☐ ☐ ☐  ☐ ☐ ☐ ☐ ☐
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;consonants&quot;&gt;Consonants&lt;/h3&gt;

&lt;p&gt;With the vowel hand mostly established, and only 4 consonants remaining from
the 9 most common letters, it&amp;rsquo;s time to start on the consonant hand.
By this point we can see that this layout will be a member of
&lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.2yb5bwiy1wa8#heading=h.e1vfsiwzv6vw&quot;&gt;the &amp;ldquo;N + vowels&amp;rdquo; family of inward rotation layouts in Ec0&amp;rsquo;s Keyboard layouts doc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s use the remaining 4 most common consonants for the home row of the
consonant hand; the arrangement with the highest inrolls is &lt;code&gt;rsth&lt;/code&gt;.
This is perfect, because it puts the most frequent consonant, &lt;code&gt;t&lt;/code&gt;, on middle finger,
which we&amp;rsquo;ll need in order to have higher utilization on the middle finger,
in just 3 keys, than the index finger, with its 6 keys.&lt;/p&gt;

&lt;p&gt;With this home row, &lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.uv9x1j70u2nc#heading=h.26oc0mqwptjr&quot;&gt;&lt;code&gt;c&lt;/code&gt; must stack with &lt;code&gt;s&lt;/code&gt; on ring finger&lt;/a&gt; to
minimize SFBs. Let&amp;rsquo;s place &lt;code&gt;l&lt;/code&gt;, the highest frequency consonant that we haven&amp;rsquo;t
already given a home row spot, on middle finger. &lt;code&gt;tl&lt;/code&gt; does mean some SFBs, but
this gives us more flexibility with what letters can be placed on the index.
&lt;code&gt;d&lt;/code&gt; then goes on the index, and by placing these in the top row we now have
nice adjacent same-row inrolls for &lt;code&gt;ld&lt;/code&gt; and &lt;code&gt;cl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the consonant pinky&amp;rsquo;s rare top key, I placed &lt;code&gt;x&lt;/code&gt; to have &lt;code&gt;xc&lt;/code&gt; and &lt;code&gt;xt&lt;/code&gt; inrolls,
plus a fun three-roll for &lt;code&gt;xcl&lt;/code&gt; in exclude.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;x c l d ☐  ☐ y o u q
r s t h ☐  ☐ n e i a
☐ ☐ ☐ ☐ ☐  ☐ ☐ ☐ ☐ ☐
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From here we should decide how to finish the consonant pinky.
&lt;code&gt;xr&lt;/code&gt; is still well below the 8-9% utilization target.
&lt;code&gt;w&lt;/code&gt; or &lt;code&gt;v&lt;/code&gt; are the natural choices to reduce SFBs.
I chose &lt;code&gt;w&lt;/code&gt; to get closer to the 8% utilization goal.
Fortunately a &lt;code&gt;wc&lt;/code&gt; pair almost never appears, so we avoid an uncomfortable scissor,
and the &lt;code&gt;wl&lt;/code&gt; and &lt;code&gt;wd&lt;/code&gt; pairs are infrequent, so we don&amp;rsquo;t have many row skips.
I find the &lt;code&gt;sw&lt;/code&gt;, &lt;code&gt;tw&lt;/code&gt;, and &lt;code&gt;wh&lt;/code&gt; pairs to be comfortable.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s another nice aspect of the &lt;code&gt;rw&lt;/code&gt; pinky: I especially dislike redirects
where the pinky is the finger upon which direction changes, and thankfully &lt;code&gt;r&lt;/code&gt;
and &lt;code&gt;w&lt;/code&gt; don&amp;rsquo;t often appear in the middle of consonant clusters.
They appear at the beginning (&lt;code&gt;rst&lt;/code&gt;, &lt;code&gt;rts&lt;/code&gt;, &lt;code&gt;wds&lt;/code&gt;) or at
the end (&lt;code&gt;str&lt;/code&gt;, &lt;code&gt;thr&lt;/code&gt;, &lt;code&gt;sw&lt;/code&gt;), but not in the middle (&lt;code&gt;srt&lt;/code&gt;, &lt;code&gt;trs&lt;/code&gt;, &lt;code&gt;dws&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;g&lt;/code&gt; shouldn&amp;rsquo;t go with &lt;code&gt;n&lt;/code&gt; or &lt;code&gt;h&lt;/code&gt;, so it should go on ring or middle.
Putting &lt;code&gt;g&lt;/code&gt; on middle doesn&amp;rsquo;t maximize middle finger utilization (&lt;code&gt;m&lt;/code&gt; would),
but it results in fewer SFBs than ring (&lt;code&gt;gl&lt;/code&gt; vs &lt;code&gt;gs&lt;/code&gt;),
so let&amp;rsquo;s settle for middle. The &lt;code&gt;ltg&lt;/code&gt; column is a little below the middle finger
utilization target, but it&amp;rsquo;s close enough. We can then finish off ring as &lt;code&gt;csv&lt;/code&gt;
to keep its SFBs low, since it already has the &lt;code&gt;sc&lt;/code&gt; pair to deal with.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;m&lt;/code&gt; and &lt;code&gt;pb&lt;/code&gt; remaining, we should put them on separate indexes.
&lt;code&gt;by&lt;/code&gt; has lower SFBs than &lt;code&gt;my&lt;/code&gt; (plus &lt;code&gt;ph&lt;/code&gt;), so &lt;code&gt;pb&lt;/code&gt; goes to the vowel hand index
and &lt;code&gt;m&lt;/code&gt; to the consonant hand index. Of &lt;code&gt;p&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;,
&lt;code&gt;p&lt;/code&gt; pairs more frequently with &lt;code&gt;o&lt;/code&gt;, while &lt;code&gt;b&lt;/code&gt; mostly pairs with &lt;code&gt;e&lt;/code&gt;, so let&amp;rsquo;s
place &lt;code&gt;p&lt;/code&gt; in the inner column and &lt;code&gt;b&lt;/code&gt; in the bottom row for fewer scissors
(despite slightly more lateral stretches from &lt;code&gt;po&lt;/code&gt;).&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;x c l d ☐  ☐ y o u q
r s t h ☐  p n e i a
w v g m ☐  ☐ b ☐ ☐ ☐
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this point, we have 5 spots left on the index fingers, 4 of which are the
inner column top/bottom row corner positions that are more than 1u from the
index finger&amp;rsquo;s home position.
Let&amp;rsquo;s assign &lt;code&gt;f&lt;/code&gt;, the last letter with &amp;gt; 1% utilization, to the
consonant hand index so that it need not be in one of these corner positions.
&lt;code&gt;f&lt;/code&gt; does not cause SFBs here, and although it could lead to higher inrolls on
the vowel hand index, at least on the consonant hand it mostly contributes to
alternation rather than outrolls.
I placed &lt;code&gt;f&lt;/code&gt; in the inner column and &lt;code&gt;m&lt;/code&gt; in the bottom row since
&lt;code&gt;f&lt;/code&gt; has less utilization and this avoids &lt;code&gt;fl&lt;/code&gt; scissors.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;k&lt;/code&gt;, the last letter besides the rare ones, can be assigned to
the consonant index to avoid &lt;code&gt;nk&lt;/code&gt; SFBs.
Putting it in the top row means less of a stretch for &lt;code&gt;ck&lt;/code&gt; and &lt;code&gt;lk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At this point we just have &lt;code&gt;j&lt;/code&gt; and &lt;code&gt;z&lt;/code&gt; to fill in the gaps.
I put &lt;code&gt;j&lt;/code&gt; on the consonant hand so that &lt;code&gt;j&lt;/code&gt; down and &lt;code&gt;k&lt;/code&gt; up vim commands
in the terminal are in a convenient place.
&lt;code&gt;z&lt;/code&gt; gets a vowel hand index spot, and now we&amp;rsquo;ve placed all the letters!&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;x c l d k  z y o u q
r s t h f  p n e i a
w v g m j  ☐ b ☐ ☐ ☐
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;punctuation&quot;&gt;Punctuation&lt;/h3&gt;

&lt;p&gt;We still have some open spots on the vowel hand to place punctuation.
The most frequent &lt;code&gt;.&lt;/code&gt; and &lt;code&gt;,&lt;/code&gt; deserve a spot on the base layer,
but on middle finger &lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.gm0ejchjpek#heading=h.fat0i9wavpm4&quot;&gt;they would cause higher SFBs with &lt;code&gt;e&lt;/code&gt;&lt;/a&gt;
and raise utilization even higher, so let&amp;rsquo;s place them on ring and pinky instead.&lt;/p&gt;

&lt;p&gt;I chose ring for &lt;code&gt;.&lt;/code&gt; because, in contrast to &lt;code&gt;,&lt;/code&gt;, it is tapped repeatedly for &lt;code&gt;...&lt;/code&gt;,
and is often interleaved with letters for programming, acronyms, and domains.
Putting it on ring also gives us the freedom to put &lt;code&gt;/&lt;/code&gt; on the pinky
outer column without creating an SFB for &lt;code&gt;./&lt;/code&gt; paths.
This does swap the order of &lt;code&gt;,.&lt;/code&gt; and the shifted &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt; from QWERTY,
but I&amp;rsquo;m not sure that matters when we&amp;rsquo;re deviating so much from QWERTY
and when angle brackets are often better positioned on a symbol layer.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;#39;&lt;/code&gt; could go on the pinky outer column without causing many SFBs, but I instead
chose middle finger. This does raise middle finger utilization somewhat higher,
but I prefer that to increased pinky lateral movement. This also means that
&lt;code&gt;&amp;#39;&lt;/code&gt; is still available on the base layer of 3x5 keyboards.&lt;/p&gt;

&lt;p&gt;Placing &lt;code&gt;&amp;#39;&lt;/code&gt; on middle causes an &lt;code&gt;e&amp;#39;&lt;/code&gt; 1u SFB on contractions like &lt;code&gt;he&amp;#39;s&lt;/code&gt; or &lt;code&gt;we&amp;#39;re&lt;/code&gt;,
and an &lt;code&gt;o_&amp;#39;&lt;/code&gt; 2u SFS on contractions like &lt;code&gt;don&amp;#39;t&lt;/code&gt; or &lt;code&gt;you&amp;#39;re&lt;/code&gt;,
but I don&amp;rsquo;t find these so unpleasant. Surprisingly, the layout analyzers say
the overall SFBs are the same as &lt;code&gt;/&lt;/code&gt; or &lt;code&gt;;&lt;/code&gt; on middle and &lt;code&gt;&amp;#39;&lt;/code&gt; on pinky,
and I&amp;rsquo;d rather handle SFBs with the more dexterous middle finger.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;x c l d k  z y o u q
r s t h f  p n e i a
w v g m j  ☐ b &amp;#39; . ,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;enter&quot;&gt;Enter?&lt;/h3&gt;

&lt;p&gt;You may notice this leaves one spot unaccounted for on the vowel hand index.
Normally a layout would include one more punctuation key, usually either &lt;code&gt;;&lt;/code&gt; or &lt;code&gt;/&lt;/code&gt;,
but I use these infrequently enough that they seem like a waste of a
base layer key for the strong index finger. Yet this position isn&amp;rsquo;t ideal for
keys that would regularly be used in the middle of typing prose:
it&amp;rsquo;s more than 1u from the index home position, requires a lateral stretch,
and can cause scissors given this layout&amp;rsquo;s top row bias on right hand.
Can we find a key that&amp;rsquo;s used regularly, but not in the middle of typing prose?&lt;/p&gt;

&lt;p&gt;The whitespace/control keys seemed like they might be a nice fit.
Placing one of them here could allow for lower pinky and thumb movement.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Space would obviously be a bad choice, since it&amp;rsquo;s used constantly when typing prose.&lt;/li&gt;
&lt;li&gt;Backspace is an option I thought might be good, but after trying it,
I found that I use it too frequently in the middle of typing prose to
quickly correct mistakes. (I put backspace on a thumb home key instead.)&lt;/li&gt;
&lt;li&gt;Delete and Escape could be fine options, but I don&amp;rsquo;t use them that regularly.&lt;/li&gt;
&lt;li&gt;Enter and Tab seem like good options.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use Enter more regularly than Tab, so I chose it.&lt;/p&gt;

&lt;p&gt;With that, we&amp;rsquo;ve reached the completed layout as shown at the start of this post!&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;x c l d k  z y o u q
r s t h f  p n e i a
w v g m j  ↵ b &amp;#39; . ,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;metrics&quot;&gt;Metrics&lt;/h2&gt;

&lt;p&gt;But enough of me justifying these choices; the best way to see if this layout
succeeded at its goals is to turn to an analyzer and look at the metrics!&lt;/p&gt;

&lt;p&gt;My favorite analyzer for evaluating and experimenting with layouts is
&lt;a href=&quot;https://cyanophage.github.io/&quot;&gt;Cyanophage&amp;rsquo;s&lt;/a&gt;, and you can see
&lt;a href=&quot;https://cyanophage.github.io/playground.html?layout=xcldkzyouq-rsthfpneia%2Fwvgmj%3Bb%27.%2C%5C%5E&amp;amp;mode=ergo&amp;amp;lan=english&quot;&gt;its analysis of this layout here&lt;/a&gt;.
Some other great interactive playground analyzers are &lt;a href=&quot;https://oxey.dev/playground/index.html&quot;&gt;Oxey&amp;rsquo;s&lt;/a&gt; and
&lt;a href=&quot;https://layouts.wiki/playground/&quot;&gt;Layouts Wiki&amp;rsquo;s&lt;/a&gt;, though these don&amp;rsquo;t support direct linking to
custom layouts.&lt;/p&gt;

&lt;p&gt;A caveat: these analyzers do not have data on usage of the Enter key, so
for this analysis I have replaced it with &lt;code&gt;;&lt;/code&gt;.
This means the usage of the right index will be undercounted, but
hopefully it does not have a large impact on bigram/trigram analysis.&lt;/p&gt;

&lt;p&gt;We can benchmark by comparing metrics against other layouts. I&amp;rsquo;ll compare with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://colemakmods.github.io/mod-dh/&quot;&gt;Colemak-DH&lt;/a&gt;: a version of &lt;a href=&quot;https://colemak.com/&quot;&gt;Colemak&lt;/a&gt;, slightly modified
and generally considered better for columnar keyboards. Colemak is one of
the most popular alternative layouts and is designed to be similar to QWERTY.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Apsu/APT&quot;&gt;APTv3&lt;/a&gt;: a well known inroll-focused layout from which I took inspiration.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/GalileoBlues/Gallium&quot;&gt;Gallium&lt;/a&gt;: a well-rounded layout often recommended as an upgrade from Colemak.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/QWERTY&quot;&gt;QWERTY&lt;/a&gt;: mostly just for laughs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;finger-utilization&quot;&gt;Finger utilization&lt;/h3&gt;

&lt;p&gt;The reported finger utilization is roughly in line with the targets:&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;Target&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;Left&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;Right&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pinky&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;8-9%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;8.01%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;9.23%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ring&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;10-12%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;10.58%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;11.00%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Middle&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;16-18%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;15.12%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;19.88%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Index&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;12-14%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;13.66%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;12.52%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Left middle is a little under, right middle is over, and right index may
actually be over when the true utilization of Enter is considered.&lt;/p&gt;

&lt;p&gt;Like mentioned earlier, finger movement is another useful measure of the work
performed by each finger:&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;Left&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;Right&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pinky&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;9.95&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;6.05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ring&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;21.07&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;18.87&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Middle&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;28.56&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;39.99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Index&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;41.43&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;28.33&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;For the most part, the movement of the fingers look good, but it shows some
interesting differences from finger utilization.
Although left pinky has lower utilization than right pinky, it has more movement.
And similarly, although left index has lower utilization than left middle,
it has significantly higher movement.
There may be more work required of these fingers than I hoped.&lt;/p&gt;

&lt;h3 id=&quot;in-rolls&quot;&gt;In-rolls&lt;/h3&gt;

&lt;table&gt;&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;2roll in&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;2roll out&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;3roll in&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;3roll out&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;Alt&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;This layout&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;30.07%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;14.62%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;1.33%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;1.07%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;33.45%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gallium&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;21.35%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;23.06%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.45%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;1.21%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;37.55%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;APTv3&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;32.63%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;14.12%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;2.26%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.54%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;30.73%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Colemak-DH&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;25.18%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;21.54%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;1.50%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.98%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;25.43%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QWERTY&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;20.38%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;21.38%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;1.32%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;1.48%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;21.38%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;The trigram metrics show we did a pretty good job of prioritizing inrolls!
Bigram inrolls are nearly twice as common as bigram outrolls and are noticeably
higher than Gallium and Colemak-DH. We get close to APTv3,
but cannot match it because of our focus on finger utilization,
falling behind especially on inward 3-rolls. We can see that alternation also
falls between Gallium and APTv3, which makes sense due to
&lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.6r1v629nms0d#heading=h.r8uk3gldl10w&quot;&gt;the inverse relationship between alternation and rolling&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;redirects&quot;&gt;Redirects&lt;/h3&gt;

&lt;table&gt;&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;Redirect&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;Weak Redirect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;This layout&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;2.53%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.30%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gallium&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;1.93%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.26%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;APTv3&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;3.60%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.42%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Colemak-DH&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;5.33%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;1.09%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QWERTY&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;6.22%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.44%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Similarly, redirects are situated between Gallium and APTv3, but significantly
better than Colemak-DH. We won&amp;rsquo;t be able to beat Gallium on redirects because
we&amp;rsquo;re prioritizing inrolls, and &lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o/edit?tab=t.6r1v629nms0d#heading=h.r8uk3gldl10w&quot;&gt;rolling correlates with redirects&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Additionally, I&amp;rsquo;m happy to see only +0.04% weak redirects over Gallium.
Cyanophage classifies redirects that occur on the middle, ring, and pinky
(i.e. without the index) as weak redirects, the redirects that feel clumsiest.&lt;/p&gt;

&lt;h3 id=&quot;same-finger-usage&quot;&gt;Same finger usage&lt;/h3&gt;

&lt;table&gt;&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;SFBs&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;SFSs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;This layout&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.84%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;3.50%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gallium&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.64%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;2.74%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;APTv3&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.81%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;3.09%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Colemak-DH&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.91%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;4.24%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QWERTY&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;4.38%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;5.45%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Same finger bigrams look acceptable. As expected, we do not beat Gallium,
though we get close to APTv3 and do beat Colemak-DH.
Index/middle SFBs are 0.58%, so most are on capable fingers.&lt;/p&gt;

&lt;p&gt;Since same finger skipgrams were not a design priority,
it&amp;rsquo;s understandable that they lag behind Gallium and APTv3,
though it&amp;rsquo;s good to see that they do still beat Colemak-DH.
A considerable portion of SFSs come from the &lt;code&gt;oe&lt;/code&gt; stack.&lt;/p&gt;

&lt;h3 id=&quot;scissors-and-lateral-stretches&quot;&gt;Scissors and lateral stretches&lt;/h3&gt;

&lt;table&gt;&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;Scissors&lt;/th&gt;
&lt;th style=&quot;text-align: center&quot;&gt;LSBs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;This layout&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.31%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.98%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gallium&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.95%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.96%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;APTv3&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.11%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.33%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Colemak-DH&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0.15%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;1.27%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QWERTY&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;1.46%&lt;/td&gt;
&lt;td style=&quot;text-align: center&quot;&gt;4.55%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Although scissors and lateral stretches weren&amp;rsquo;t a focus, we did consider them
during design, so it&amp;rsquo;s worth checking on them.&lt;/p&gt;

&lt;p&gt;Fortunately, the numbers seem reasonable! Scissors are lower than Gallium,
with most of the scissors coming from &lt;code&gt;bo&lt;/code&gt; (like Gallium&amp;rsquo;s &lt;code&gt;of&lt;/code&gt;).
Lateral stretch bigrams are comparable to Gallium and lower than Colemak-DH.&lt;/p&gt;

&lt;h2 id=&quot;thoughts-from-a-year-of-usage&quot;&gt;Thoughts from a year of usage&lt;/h2&gt;

&lt;p&gt;A layout can&amp;rsquo;t be completely evaluated from its design justification or
analyzer metrics; the real test is how it feels in real usage.
I&amp;rsquo;ve been using this layout for a year now, and I&amp;rsquo;ve been happy with it!&lt;/p&gt;

&lt;p&gt;It has largely succeeded at my goal of comfort. I no longer feel the strain on
my index fingers that I started to feel from using columnar QWERTY,
though perhaps that would have faded in time regardless.
The high middle finger utilization has not caused me any discomfort.&lt;/p&gt;

&lt;p&gt;Unfortunately, the layout did have one noticeable point of discomfort:
the &lt;code&gt;wr&lt;/code&gt; pinky. It seems that my left pinky has been messed up by a lifetime of
using only left shift on QWERTY, including weird contortions like Shift+1 and
long stretches like Shift+Y with my left index.
I started experiencing discomfort in my left pinky on the new layout, though
fortunately I was able to mitigate it by adjusting my navigation and
symbol layers for less pinky usage. It has lessened over time and now I
notice it only rarely if I&amp;rsquo;ve been typing quickly for long periods of time.&lt;/p&gt;

&lt;p&gt;In hindsight, I wonder if finger movement would have been a better design goal
than utilization. For a while I considered swapping to a &lt;code&gt;vr&lt;/code&gt; pinky,
which would reduce usage, but it comes with an increase in pinky SFBs and SFSs.
I considered something like an &lt;code&gt;xrz&lt;/code&gt; pinky, but
I was worried it&amp;rsquo;d lead to index discomfort, and
I never found a solution I liked before the pinky discomfort started improving.
I&amp;rsquo;m not sure if the more common &lt;code&gt;bn&lt;/code&gt; pinky would have fared better for me;
I can only imagine how bad I would have felt with Dvorak&amp;rsquo;s &lt;code&gt;ls&lt;/code&gt; pinky.&lt;/p&gt;

&lt;p&gt;The relatively high SFBs of the left middle and right index haven&amp;rsquo;t bothered me.
I don&amp;rsquo;t notice the &lt;code&gt;by&lt;/code&gt; 2u SFB, which I had expected to be annoying.
&lt;code&gt;ltg&lt;/code&gt; is a bit busy, but nothing compared to QWERTY&amp;rsquo;s &lt;code&gt;edc&lt;/code&gt;;
typing &lt;code&gt;digital&lt;/code&gt; for the first time was a funny experience, though.
The &lt;code&gt;ght&lt;/code&gt; SFS occasionally trips me up during fast typing, so
maybe &lt;code&gt;g&lt;/code&gt; on ring could have helped with that.&lt;/p&gt;

&lt;p&gt;One pleasant realization I had: of the 5 most repeated letters, this layout puts
4 (all but &lt;code&gt;s&lt;/code&gt;) on the middle fingers, which I find to be the most comfortable
finger to tap in quick succession. Nice!&lt;/p&gt;

&lt;p&gt;The inroll focus doesn&amp;rsquo;t feel as notable as I first imagined.
I&amp;rsquo;m excited whenever I get to type &lt;code&gt;rst&lt;/code&gt; or &lt;code&gt;ien&lt;/code&gt;, but
for the most part the inrolls fade into the background.
I can see why most layouts these days aren&amp;rsquo;t designed for directionality,
especially with the wide variance of the English language fighting against you.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve liked having Enter on an index finger. It feels nice for sending
quick messages and has helped me balance the load on my thumbs.
It doesn&amp;rsquo;t feel great if you have do repeated patterns of single letter + Enter,
like with yes/no CLI prompts&amp;hellip; which are especially annoying because
&lt;code&gt;y&lt;/code&gt; and &lt;code&gt;n&lt;/code&gt; are on the same finger, so I usually alt-finger this case.&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t think I&amp;rsquo;ll be hopping to a new layout any time soon;
any improvement it provides would have to be dramatic.
I&amp;rsquo;ve considered layouts with a thumb letter, but I&amp;rsquo;m concerned about
thumb strain if I have backspace and a letter on the same thumb.
Maybe someday a magic key will lure me into learning a new layout, but not yet.&lt;/p&gt;

&lt;h2 id=&quot;why-i-wrote-this&quot;&gt;Why I wrote this&lt;/h2&gt;

&lt;p&gt;Designing this layout was a fun project and I wanted to share about the process!
I don&amp;rsquo;t think I&amp;rsquo;ve designed the world&amp;rsquo;s best layout, and I don&amp;rsquo;t think that
everyone should use it; rather, I hope more people explore alternate layouts,
tweak existing ones to their preferences, and design their own.&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;re switching to an ergonomic keyboard, it&amp;rsquo;s a great time to try an alternative.
Every layout is made with certain preferences, and if you can&amp;rsquo;t find one that
matches yours, it&amp;rsquo;s not so hard to tweak an existing layout or design your own.&lt;/p&gt;

&lt;h2 id=&quot;resources-and-additional-reading&quot;&gt;Resources and additional reading&lt;/h2&gt;

&lt;p&gt;If you want to learn more about alternative layouts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://getreuer.info/posts/keyboards/alt-layouts/index.html&quot;&gt;Pascal Getreuer&amp;rsquo;s guide to alt keyboard layouts&lt;/a&gt; - a great
introduction that overviews many alternative layouts&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://layouts.wiki/guides/start/intro/&quot;&gt;Layouts Wiki&amp;rsquo;s guides&lt;/a&gt; - includes recommendations for
the latest layouts with reasons you may (or may not) prefer them&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.google.com/document/d/1W0jhfqJI2ueJ2FNseR4YAFpNfsUM-_FlREHbpNGmC2o&quot;&gt;Ec0&amp;rsquo;s Keyboard layouts doc&lt;/a&gt; - already linked many times in this post,
but worth repeating; an in-depth resource for understanding and creating layouts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, in addition to the layouts linked earlier for benchmarking, here are some
layouts with neat ideas and writeups that I&amp;rsquo;ve enjoyed reading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.google.com/document/d/1HjylX4exH3wyBbxbwranSP4htHXn2qMqOKutpPDxN9c&quot;&gt;Thraeg&amp;rsquo;s Mumak&lt;/a&gt; - prioritizes middle finger utilization and
adjacent finger rolls&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/MightyAcas/vylet/blob/main/README.md&quot;&gt;Acas&amp;rsquo;s Vylet&lt;/a&gt; - prioritizes inrolls with an added magic key&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://valorance.net/night/design&quot;&gt;Valorance&amp;rsquo;s Night&lt;/a&gt; - achieves very low SFBs and SFSs with a thumb letter,
plus its writeup includes a nice overview of other layouts with thumb letters&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.simn.me/posts/2025/afterburner/&quot;&gt;Simon Zeng&amp;rsquo;s Afterburner&lt;/a&gt; - a really neat idea for multiple
magic keys to dramatically reduce same finger usage&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
  <entry>
    <title type="html">How I Broke Rust's Package Manager for All Windows Users</title>
    <link href="http://sasheldon.com/blog/2017/05/07/how-i-broke-cargo-for-windows/"/>
    <updated>2017-05-07T12:07:40-05:00</updated>
    <id>http://sasheldon.com/blog/2017/05/07/how-i-broke-cargo-for-windows</id>
    <content type="html">&lt;p&gt;Last weekend I was playing around with a way to represent null-terminated UTF8
strings in Rust. Rather than just toying with it forever,
I decided to clean up a minimal version and publish it to crates.io. Creating
the crate went smoothly, exactly the same as the 11 prior crates I&amp;rsquo;ve published.
I closed up my laptop and called it a day.&lt;/p&gt;

&lt;p&gt;Well, everything only seemed the same until an hour later when I got this tweet:&lt;/p&gt;

&lt;!-- more --&gt;

&lt;blockquote&gt;
&lt;p&gt;Hi Steven, Rust team here :) We’re having some technical difficulties with the name of one of your crates… feel free to DM&lt;/p&gt;

&lt;p&gt;— @bstrie &lt;a href=&quot;https://twitter.com/bstrie/status/858784809413472257&quot;&gt;April 30, 2017&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;the-impact&quot;&gt;The impact&lt;/h2&gt;

&lt;p&gt;The crate I had just published was named &lt;code&gt;nul&lt;/code&gt;, after
&lt;a href=&quot;https://en.wikipedia.org/wiki/Null_character&quot;&gt;the null terminator character&lt;/a&gt;
which is abbreviated as &lt;code&gt;NUL&lt;/code&gt;.
I hopped onto Rust&amp;rsquo;s IRC channel to figure out what I had done, and
&lt;a href=&quot;https://botbot.me/mozilla/rust-internals/msg/84953638/&quot;&gt;the friendly Rust devs informed me&lt;/a&gt;
that they were going to delete &lt;code&gt;nul&lt;/code&gt; from crates.io.&lt;/p&gt;

&lt;p&gt;While trying to catch up at this point, I saw that there was an
&lt;a href=&quot;https://github.com/SSheldon/nul/issues/1&quot;&gt;issue filed on my repo&lt;/a&gt;.
And an &lt;a href=&quot;https://github.com/rust-lang/cargo/issues/3982&quot;&gt;issue filed on cargo&lt;/a&gt;.
And a &lt;a href=&quot;https://www.reddit.com/r/rust/comments/68hemz/i_think_a_crate_called_nul_is_causing_errors_for/&quot;&gt;reddit thread&lt;/a&gt;.
Whoops.&lt;/p&gt;

&lt;p&gt;Whenever any users on Windows attempted to download new crates or update
their dependencies, they were greeted with this error:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;Updating registry https://github.com/rust-lang/crates.io-index
error: [20/-1] Cannot checkout to invalid path &amp;#39;3/n/nul&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As &lt;a href=&quot;https://botbot.me/mozilla/rust/msg/84953614/&quot;&gt;kmc described&lt;/a&gt;
the status of cargo on Windows:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/how-i-broke-cargo-for-windows/on-fire.jpeg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;h2 id=&quot;but-why&quot;&gt;But why?&lt;/h2&gt;

&lt;p&gt;Turns out that &amp;ldquo;NUL&amp;rdquo; (including &amp;ldquo;nul&amp;rdquo;) is a reserved filename on Windows.
&lt;code&gt;NUL&lt;/code&gt; is the Windows equivalent of Unix&amp;rsquo;s &lt;code&gt;/dev/null&lt;/code&gt;, but instead of existing
at a specific directory you can write to &lt;code&gt;NUL&lt;/code&gt; in any directory,
and even with any extension!&lt;/p&gt;

&lt;p&gt;That might sound surprising, but
&lt;a href=&quot;https://blogs.msdn.microsoft.com/oldnewthing/20031022-00/?p=42073&quot;&gt;Raymond Chen has an illuminating explanation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Because DOS 1.0 didn&amp;rsquo;t have subdirectories.
There was only one directory, which today we would call the root directory&amp;hellip;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And so, since these DOS 1.0 days, tons of batch files exist on Windows
redirecting with &lt;code&gt;&amp;gt;NUL&lt;/code&gt;, and the reserved filenames remain.&lt;/p&gt;

&lt;h2 id=&quot;the-aftermath&quot;&gt;The aftermath&lt;/h2&gt;

&lt;p&gt;Once my &lt;code&gt;nul&lt;/code&gt; crate was deleted, Windows users were back in business.
The Rust team quickly moved to prevent this issue from happening again by
&lt;a href=&quot;https://github.com/rust-lang/crates.io/pull/695&quot;&gt;adding &amp;ldquo;NUL&amp;rdquo; and Windows&amp;rsquo; 21 other reserved filenames to the list of reserved crate names&lt;/a&gt;.
Guess I won&amp;rsquo;t get to publish that &lt;code&gt;aux&lt;/code&gt; crate now 😉&lt;/p&gt;

&lt;p&gt;Apologies to Carol Nichols and any other Rust devs whose weekends I interrupted,
thanks for your quick action!&lt;/p&gt;

&lt;p&gt;Although, I mean, like withoutboats said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I thought Rust was supposed to prevent nul errors! ;-)&lt;/p&gt;

&lt;p&gt;— @withoutboats &lt;a href=&quot;https://twitter.com/withoutboats/status/858791127750557696&quot;&gt;April 30, 2017&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content>
  </entry>
  
  <entry>
    <title type="html">Objective-C from Rust: Statically Verified Type Encodings without Allocation</title>
    <link href="http://sasheldon.com/blog/2017/02/20/objective-c-from-rust-type-encodings/"/>
    <updated>2017-02-21T01:39:39-06:00</updated>
    <id>http://sasheldon.com/blog/2017/02/20/objective-c-from-rust-type-encodings</id>
    <content type="html">&lt;p&gt;Lately I&amp;rsquo;ve been thinking about a new way to generate
&lt;a href=&quot;https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html&quot;&gt;Objective-C type encodings&lt;/a&gt;
from Rust. The Objective-C runtime needs these encodings when declaring methods
and instance variables, and in Objective-C they&amp;rsquo;re simply generated via the
&lt;code&gt;@encode()&lt;/code&gt; compiler directive, but that&amp;rsquo;s not available in Rust!&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;The current approach used in the &lt;code&gt;objc&lt;/code&gt; crate basically just treats them as
strings, like they are in Objective-C. The intention was: when you want the
encoding of a type, just go run the Objective-C compiler and copy the result of
&lt;code&gt;@encode()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, the encoding for a type is not the same on all platforms;
certain types have different encodings on different architectures.
&lt;code&gt;@encode(NSInteger)&lt;/code&gt; is &lt;code&gt;&amp;quot;i&amp;quot;&lt;/code&gt; on 32-bit systems and &lt;code&gt;&amp;quot;q&amp;quot;&lt;/code&gt; on 64-bit systems,
while &lt;code&gt;@encode(BOOL)&lt;/code&gt; is &lt;code&gt;&amp;quot;c&amp;quot;&lt;/code&gt; on most platforms but &lt;code&gt;&amp;quot;b&amp;quot;&lt;/code&gt; on ARM64.&lt;/p&gt;

&lt;p&gt;With these discrepancies, it&amp;rsquo;s really convenient to have ways of building up
a type encoding from its parts. A first approach could look something like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;encode_struct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fields&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;fm&quot;&gt;format!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{{}=&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cloned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;&amp;#39;}&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;encode_struct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;CGPoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GCFloat&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CGFloat&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This makes it easier for us to generate the struct&amp;rsquo;s encoding and
use the appropriate encoding for &lt;code&gt;CGFloat&lt;/code&gt; on our platform.
However, it&amp;rsquo;s a &lt;a href=&quot;http://wiki.c2.com/?StringlyTyped&quot;&gt;stringly-typed API&lt;/a&gt;;
encodings have a well-defined format, but this code accepts inputs that can
make it produce invalid encodings, like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode_struct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;CGPoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Hello, World!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Can we do better? Is there a design that will allow us to say
&amp;ldquo;I accept valid encodings and will produce a valid encoding from them&amp;rdquo;?&lt;/p&gt;

&lt;h2 id=&quot;abstract-syntax&quot;&gt;Abstract syntax&lt;/h2&gt;

&lt;p&gt;Looking at the documentation for encodings, we can see that their grammar is
pretty simple. It&amp;rsquo;s not hard to represent the abstract syntax with Rust&amp;rsquo;s enums:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Struct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With this, it&amp;rsquo;s even easier to build the encoding of a struct from its parts,
because the type system won&amp;rsquo;t let you build a struct encoding with an
invalid format!&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s something I&amp;rsquo;m curious if we can improve on, though: see &lt;code&gt;Box&lt;/code&gt; and &lt;code&gt;Vec&lt;/code&gt;
in that definition? Each of those will involve a memory allocation.
Representing as simple an encoding as &lt;code&gt;&amp;quot;^i&amp;quot;&lt;/code&gt; will allocate additional memory,
and complex encodings like &lt;code&gt;&amp;quot;{CGRect={CGPoint=dd}{CGSize=dd}}&amp;quot;&lt;/code&gt; require more.&lt;/p&gt;

&lt;h2 id=&quot;zero-allocation&quot;&gt;Zero allocation&lt;/h2&gt;

&lt;p&gt;Our new challenge is composing these encodings together without allocation or
virtualization. That problem reminds me of the design of
&lt;a href=&quot;https://doc.rust-lang.org/std/iter/index.html&quot;&gt;iterators&lt;/a&gt; and
&lt;a href=&quot;https://aturon.github.io/blog/2016/08/11/futures/&quot;&gt;futures&lt;/a&gt; in Rust;
rather than representing these as a single concrete type, there is a trait
defining the core functionality and then iterators/futures can be combined
through generic structs which also conform to the trait.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s take some inspiration from this design and say that there is an &lt;code&gt;Encoding&lt;/code&gt;
trait which every type representing a valid encoding implements
(we&amp;rsquo;ll come back later to exactly what functionality it should expose).
Modelling a pointer encoding can be as simple as:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// T is the type of the target&amp;#39;s encoding&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Pointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Simple, and it avoids allocating!&lt;/p&gt;

&lt;p&gt;Things get trickier when we want to model a struct, because we need to hold the
encoding of its multiple fields which may be of differing types.
My go-to solution for representing heterogenous collections is using tuples
with a trait they implement exposing the functionality we need, like the
&lt;a href=&quot;/blog/2015/08/02/objective-c-from-rust-objc_msgsend/&quot;&gt;&lt;code&gt;MessageArguments&lt;/code&gt; trait in the &lt;code&gt;objc&lt;/code&gt; crate&lt;/a&gt;.
With such a trait, we could be able to create struct encodings like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Struct&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;&amp;quot;MyStruct&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fields&lt;/span&gt;: &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Again, no allocations needed. But what functionality will be needed in our
encoding-tuple trait?&lt;/p&gt;

&lt;h2 id=&quot;encodings-trait&quot;&gt;Encodings trait&lt;/h2&gt;

&lt;p&gt;In the end, the functionality we&amp;rsquo;ll need from encodings will include
writing out their string representation and comparing them for equality.
For a struct encoding to do this, it will need access to its fields.
If we could iterate over the fields of the struct, that should be sufficient!&lt;/p&gt;

&lt;p&gt;Unfortunately, we can&amp;rsquo;t create an &lt;code&gt;Iterator&lt;/code&gt; in this case; what would be the
type of the items it yields? As mentioned earlier, we&amp;rsquo;re working with tuples
that contain encodings of differing types, so there is no single type we could
choose for the type of the iterator&amp;rsquo;s items.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s a different iteration technique we can fall back to:
&lt;a href=&quot;http://journal.stuffwithstuff.com/2013/01/13/iteration-inside-and-out/&quot;&gt;internal iteration&lt;/a&gt;.
Internal (or push-based) iteration differs from external (or pull-based)
iteration in that, instead of asking for each next element and then doing
something with it, you provide an action to perform and that action is called
for each item in the collection.&lt;/p&gt;

&lt;p&gt;Internal iteration works for us because, instead of needing to say explicitly
which type of item will be returned, we can just ask for an action that can be
performed on any type that implements &lt;code&gt;Encoding&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s one obstacle here: we can&amp;rsquo;t use Rust&amp;rsquo;s usual &lt;code&gt;Fn&lt;/code&gt; types because when
the closure is passed, we don&amp;rsquo;t know exactly which type of encoding it will be
called with. In fact, we expect it to be called with different types of encoding!
In effect, we want a closure that hasn&amp;rsquo;t yet been monomorphized,
which doesn&amp;rsquo;t appear to be possible.
If it were, the declaration would look something like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encodings&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;callback&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Encode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;FnMut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But instead we settle for defining the callback as a custom trait:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EncodingsIterateCallback&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encodings&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;EncodingsIterateCallback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;callback&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And voilà! Now we have a way to iterate over a heterogenous collection of
encodings. We can implement this trait for encodings of tuples and be on our way.&lt;/p&gt;

&lt;h2 id=&quot;encoding-trait&quot;&gt;Encoding trait&lt;/h2&gt;

&lt;p&gt;You may have noticed that we&amp;rsquo;ve so far dodged an important question:
what does the &lt;code&gt;Encoding&lt;/code&gt; trait look like? Let&amp;rsquo;s figure that out!&lt;/p&gt;

&lt;p&gt;As mentioned earlier, one of the things we&amp;rsquo;ll want to do with encodings is
compare them for equality. But how can we compare with an encoding that could
be any type? The &lt;code&gt;Encoding&lt;/code&gt; trait will need to provide some sort of
&amp;ldquo;common language&amp;rdquo; through which encodings of different types can interoperate.&lt;/p&gt;

&lt;p&gt;Fortunately, the kinds of encodings that exist are constrained and well-known.
We would be able to compare if we could ask encodings something like:
are you a pointer? what&amp;rsquo;s the encoding of your target? are you an array?
what&amp;rsquo;s your length?&lt;/p&gt;

&lt;p&gt;To solve this, I used a &lt;code&gt;Descriptor&lt;/code&gt; enum that describes which kind an encoding
is and provides its properties. In pseudo-Rust, it looks like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Descriptor&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Primitive is an enum of all encodings not composed from others&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Primitive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Primitive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Struct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encodings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Union&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encodings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/SSheldon/rust-objc-encode/blob/0.0.2/src/descriptor.rs&quot;&gt;real implementation&lt;/a&gt;
looks gnarlier and is generic rather than using &lt;code&gt;impl Trait&lt;/code&gt;, but it&amp;rsquo;s the same
idea.&lt;/p&gt;

&lt;p&gt;With this descriptor we are effectively able to &amp;ldquo;downcast&amp;rdquo; encodings and figure
out more about them, allowing us to compare encodings or convert them to strings.
The &lt;code&gt;Encoding&lt;/code&gt; trait ultimately ends up looking like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PointerTarget&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Sized&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayItem&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Sized&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StructFields&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Sized&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encodings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UnionMembers&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Sized&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encodings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;descriptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Descriptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;Self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;PointerTarget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                                       &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;Self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;ArrayItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                                       &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;Self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;StructFields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                                       &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;Self&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;UnionMembers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;eq_encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Sized&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* implementation provided based on the descriptor */&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;fmt&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;fmt&lt;/span&gt;::&lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* implementation provided based on the descriptor */&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;parsing-encodings&quot;&gt;Parsing encodings&lt;/h2&gt;

&lt;p&gt;As cool as the encoding structs we&amp;rsquo;ve made so far are, we can&amp;rsquo;t build encodings
like them from parsing a string. This is because at compile time we have know
idea how big the result would be, and with monomorphization the compiler would
have to generate code for creating every possible kind of encoding struct,
and there are infinitely many possible encodings. Believe me, I tried:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/objective-c-from-rust-type-encodings/recursion-limit.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;What we can do, though, is make a new kind of encoding that is initialized from
a string and parses itself lazily; I ended up calling
&lt;a href=&quot;https://github.com/SSheldon/rust-objc-encode/blob/0.0.2/src/parse/encoding.rs&quot;&gt;this type &lt;code&gt;StrEncoding&lt;/code&gt;&lt;/a&gt;.
When &lt;code&gt;StrEncoding&lt;/code&gt;&amp;rsquo;s &lt;code&gt;descriptor&lt;/code&gt; method is called, it determines which kind of
encoding it is and creates more &lt;code&gt;StrEncoding&lt;/code&gt;s for any sub-encodings it contains.
These sub-encodings reference safely into the original buffer,
no copying required, thanks to Rust&amp;rsquo;s lifetimes and ownership system.&lt;/p&gt;

&lt;p&gt;There is one gotcha: our &lt;code&gt;Encoding&lt;/code&gt; trait was designed for structs with
encodings inside them, and so was designed where references to the contained
encodings are returned. This doesn&amp;rsquo;t seem to work with &lt;code&gt;StrEncoding&lt;/code&gt;;
it doesn&amp;rsquo;t own its sub-encodings (remember, it creates them on demand),
and how could we return a reference to something that was created inside the
method and is about to drop out of scope?&lt;/p&gt;

&lt;p&gt;The key to solving this was realizing that the &lt;code&gt;StrEncoding&lt;/code&gt; doesn&amp;rsquo;t actually
need any data other than its input string. What if we were able to convert
a reference to a &lt;code&gt;str&lt;/code&gt; into a reference to a &lt;code&gt;StrEncoding&lt;/code&gt;?
Turns out this is possible if &lt;code&gt;StrEncoding&lt;/code&gt; is defined as a
&lt;a href=&quot;https://doc.rust-lang.org/nomicon/exotic-sizes.html#dynamically-sized-types-dsts&quot;&gt;dynamically-sized type&lt;/a&gt;
wrapping &lt;code&gt;str&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StrEncoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And with that, when a &lt;code&gt;StrEncoding&lt;/code&gt; is parsed, it is able to return references
to sub-encodings with the same lifetime!&lt;/p&gt;

&lt;h2 id=&quot;owned-strencoding&quot;&gt;Owned StrEncoding&lt;/h2&gt;

&lt;p&gt;As nice as our dynamically sized &lt;code&gt;StrEncoding&lt;/code&gt; is, sometimes it&amp;rsquo;d be beneficial
to have a parsed encoding which owns its buffer and can be passed around
without worrying about lifetimes.&lt;/p&gt;

&lt;p&gt;Complicating this is the fact that I was aiming to have this encodings crate be
&lt;a href=&quot;https://doc.rust-lang.org/book/using-rust-without-the-standard-library.html&quot;&gt;&lt;code&gt;no_std&lt;/code&gt;, relying only on libcore&lt;/a&gt;.
&lt;code&gt;String&lt;/code&gt; doesn&amp;rsquo;t even exist in libcore! How can we make a parsed encoding
which owns a &lt;code&gt;String&lt;/code&gt; when it&amp;rsquo;s not available?&lt;/p&gt;

&lt;p&gt;Since we can&amp;rsquo;t access &lt;code&gt;String&lt;/code&gt; ourselves, I figured we&amp;rsquo;d have to use a generic
type parameter through which users could specify that &lt;code&gt;String&lt;/code&gt; is used.
I scoured the docs for a trait that is implemented by &lt;code&gt;String&lt;/code&gt; and accessible
in libcore and found just what we need in &lt;code&gt;AsRef&amp;lt;str&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A further bonus is that &lt;code&gt;str&lt;/code&gt; itself implements &lt;code&gt;AsRef&amp;lt;str&amp;gt;&lt;/code&gt;,
so we don&amp;rsquo;t actually even need a new type for this;
we can modify &lt;code&gt;StrEncoding&lt;/code&gt; to support its original use case and this new one:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StrEncoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;S&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Sized&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;AsRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can have multiple flavors of string encodings:
the original, dynamically sized version as &lt;code&gt;&amp;amp;StrEncoding&amp;lt;str&amp;gt;&lt;/code&gt;,
or one with an owned buffer as &lt;code&gt;StrEncoding&amp;lt;String&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-end-result&quot;&gt;The end result&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve published the end result as
&lt;a href=&quot;https://crates.io/crates/objc-encode&quot;&gt;the &lt;code&gt;objc-encode&lt;/code&gt; crate&lt;/a&gt;,
which allows creating encodings that are statically known to be valid
and can be compared against encodings parsed from a string representation,
all without memory allocation.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/SSheldon/rust-objc-encode/blob/0.0.2/examples/core_graphics.rs#L41-L53&quot;&gt;The encodings compose well&lt;/a&gt;,
albeit with a bit of boilerplate for more complex structs.
The good news is that this boilerplate is very formulaic, and I think generating
it would be a great candidate for a
&lt;a href=&quot;https://doc.rust-lang.org/book/procedural-macros.html&quot;&gt;custom derive macro&lt;/a&gt;,
something I&amp;rsquo;m eager to try in the future!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title type="html">Testing Rust on iOS with Travis</title>
    <link href="http://sasheldon.com/blog/2016/02/22/testing-rust-on-ios-with-travis/"/>
    <updated>2016-02-23T00:10:43-06:00</updated>
    <id>http://sasheldon.com/blog/2016/02/22/testing-rust-on-ios-with-travis</id>
    <content type="html">&lt;p&gt;Since I started automatically testing my Rust crate with Travis,
I had always wanted to test on iOS as well.
Unfortunately, the default Rust compiler on Travis doesn&amp;rsquo;t support iOS,
and compiling one from scratch takes a prohibitively long time.
With Rust&amp;rsquo;s improved cross-compilation support, it&amp;rsquo;s now possible!&lt;/p&gt;

&lt;!-- more --&gt;

&lt;h2 id=&quot;travis-configurations&quot;&gt;Travis configurations&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;ll be running our tests on Xcode&amp;rsquo;s iOS simulator,
which means that these tests have to run on Travis&amp;rsquo;s OSX image.
We&amp;rsquo;ll start with these Travis configurations for iOS builds:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;language&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;l l-Scalar l-Scalar-Plain&quot;&gt;rust&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;rust&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;l l-Scalar l-Scalar-Plain&quot;&gt;nightly&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;l l-Scalar l-Scalar-Plain&quot;&gt;osx&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;osx_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;l l-Scalar l-Scalar-Plain&quot;&gt;xcode7.2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you&amp;rsquo;ll be testing your library on OSX and iOS, I&amp;rsquo;ve found it convenient
to use an &lt;code&gt;IOS_ARCHS&lt;/code&gt; environment variable; this variable lists all the
iOS architectures we should build, and will be empty for our OSX builds.
To build for all currently supported iOS architectures,
&lt;code&gt;IOS_ARCHS&lt;/code&gt; can be defined as &lt;code&gt;IOS_ARCHS=&amp;quot;i386 x86_64 armv7 armv7s aarch64&amp;quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By using an &lt;code&gt;IOS_ARCHS&lt;/code&gt; environment variable, we can take advantage of
&lt;a href=&quot;https://docs.travis-ci.com/user/environment-variables/#Defining-Variables-in-.travis.yml&quot;&gt;Travis&amp;rsquo;s build matrix functionality&lt;/a&gt;
to have separate iOS and OSX builds:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p p-Indicator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;l l-Scalar l-Scalar-Plain&quot;&gt;IOS_ARCHS=&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p p-Indicator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;l l-Scalar l-Scalar-Plain&quot;&gt;IOS_ARCHS=&amp;quot;i386 x86_64 armv7 armv7s aarch64&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will trigger two separate builds in Travis&amp;rsquo;s matrix: one for no iOS
architectures (i.e. an OSX build) and one for all iOS architectures.&lt;/p&gt;

&lt;h2 id=&quot;setting-up-the-cross-compiler&quot;&gt;Setting up the cross compiler&lt;/h2&gt;

&lt;p&gt;The Rust compiler included on Travis is not able to compile for iOS.
With Rust&amp;rsquo;s cross compiler support, though, compiling for iOS is just
a matter of downloading the iOS versions of the standard library.&lt;/p&gt;

&lt;p&gt;Following the &lt;a href=&quot;https://github.com/japaric/rust-cross/blob/master/README.md&quot;&gt;rust-cross guide&lt;/a&gt;,
we can add a &lt;a href=&quot;https://docs.travis-ci.com/user/customizing-the-build/#Customizing-the-Installation-Step&quot;&gt;Travis &lt;code&gt;install&lt;/code&gt; step&lt;/a&gt;
to install all the architectures we&amp;rsquo;ll be building for:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;arch&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IOS_ARCHS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ios_stdlib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;rust-std-nightly-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;arch&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-apple-ios&amp;quot;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;curl&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-O&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;http://static.rust-lang.org/dist/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ios_stdlib&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.tar.gz&amp;quot;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;tar&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;xzf&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ios_stdlib&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.tar.gz&amp;quot;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;./&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ios_stdlib&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/install.sh&amp;quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;--prefix&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;rustc&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;--print&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;sysroot&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;building-an-ios-library&quot;&gt;Building an iOS library&lt;/h2&gt;

&lt;p&gt;The trickiest part about testing Rust on iOS currently is that
you cannot directly run the &lt;code&gt;#[test]&lt;/code&gt;s you&amp;rsquo;ve written in Rust.
Rust&amp;rsquo;s testing infrastructure compiles tests into an executable to be run,
but executables on iOS have to be packaged as apps and signed properly,
a process best handled by Xcode.&lt;/p&gt;

&lt;p&gt;I chose to extract some of my testing code into a library that could be
called from iOS, and then wrote a simple iOS test project that would link
and call these tests. The objc crate actually has
&lt;a href=&quot;https://github.com/SSheldon/rust-objc/blob/e034af2/xtests/build.py&quot;&gt;a Python script to parse out the tests from the project&lt;/a&gt;
to be included in a crate for external tests;
ideally this will someday be replaced with a
&lt;a href=&quot;https://github.com/rust-lang/rfcs/issues/816&quot;&gt;custom test harness&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The code we&amp;rsquo;d like to test on iOS has to be compiled to a static library,
as support for dynamic libraries on iOS was only added recently and
&lt;a href=&quot;https://github.com/rust-lang/rust/issues/21727&quot;&gt;Rust does not yet support them&lt;/a&gt;.
To compile to a static library, simply add the
&lt;a href=&quot;http://doc.crates.io/manifest.html#building-dynamic-or-static-libraries&quot;&gt;&lt;code&gt;crate-type&lt;/code&gt; key&lt;/a&gt;
to the &lt;code&gt;lib&lt;/code&gt; section of the &lt;code&gt;Cargo.toml&lt;/code&gt; for your test library:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;[lib]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;crate-type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;staticlib&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The test code that will be called from our iOS app must be properly exposed like
&lt;a href=&quot;https://doc.rust-lang.org/book/ffi.html#calling-rust-code-from-c&quot;&gt;any Rust code called from C&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;#[no_mangle]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rust_lib_test_functionality&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;c_int&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Returns a non-zero code for test failure&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Great! Now we have a static lib exposing some test functionality that
we&amp;rsquo;ll call on iOS.&lt;/p&gt;

&lt;p&gt;One last thing: iOS libraries support multiple architectures, so to test
on multiple architectures we&amp;rsquo;ll want to combine the different builds of
our library using the &lt;code&gt;lipo&lt;/code&gt; tool:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;arch&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IOS_ARCHS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;cargo&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;build&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;--target&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;arch&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-apple-ios&amp;quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
lipo&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-create&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-output&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LIB&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;target/*-apple-ios/debug/&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LIB&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;ios-test-project&quot;&gt;iOS test project&lt;/h2&gt;

&lt;p&gt;Now that we have our library of test code to call from iOS, we can create
an iOS test project. Starting out from an empty project in Xcode,
we&amp;rsquo;ll add a new iOS unit testing target:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/testing-rust-on-ios-with-travis/new-test-target.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Next, drag your compiled library of Rust tests into the &amp;ldquo;Link Binary With
Libraries&amp;rdquo; section of the &amp;ldquo;Build Phases&amp;rdquo; for your test target.&lt;/p&gt;

&lt;p&gt;Now we&amp;rsquo;re ready to write an &lt;code&gt;XCTestCase&lt;/code&gt; verifying the functionality of
the Rust library:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objc&quot; data-lang=&quot;objc&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rust_lib_test_functionality&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RustLibTests&lt;/span&gt; : &lt;span class=&quot;nc&quot;&gt;XCTestCase&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@implementation&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RustLibTests&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rust_lib_test_functionality&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;XCTAssertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Test failed with a non-zero code&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this point, we can run our tests from within Xcode and should see a
nice green checkmark if it&amp;rsquo;s passing on the iOS simulator!&lt;/p&gt;

&lt;h2 id=&quot;running-on-travis&quot;&gt;Running on Travis&lt;/h2&gt;

&lt;p&gt;The last step is simply adding a
&lt;a href=&quot;https://docs.travis-ci.com/user/customizing-the-build/#Customizing-the-Build-Step&quot;&gt;Travis &lt;code&gt;script&lt;/code&gt; step&lt;/a&gt;
to run our iOS tests.&lt;/p&gt;

&lt;p&gt;One caveat, first: running tests from a script requires a shared scheme, so
make sure the test target scheme is shared and the &lt;code&gt;.xcscheme&lt;/code&gt; file committed.
This can be done in Xcode from the
&amp;ldquo;Product&amp;rdquo; &amp;gt; &amp;ldquo;Scheme&amp;rdquo; &amp;gt; &amp;ldquo;Manage Schemes&amp;hellip;&amp;rdquo; menu:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/testing-rust-on-ios-with-travis/shared-scheme.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Now, we can add a script step using &lt;code&gt;xcodebuild&lt;/code&gt;. &lt;code&gt;xcodebuild&lt;/code&gt; takes
&lt;a href=&quot;https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html&quot;&gt;a multitude of options&lt;/a&gt;,
but if your project and scheme were named &lt;code&gt;RustLibTests&lt;/code&gt;,
running your tests on an iPhone 5 and 5s simulator (32 and 64-bit,
respectively) could be done with the following command:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;&lt;/span&gt;xcodebuild&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;-project&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;RustLibTests.xcodeproj&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;-scheme&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;RustLibTests&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;-destination&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;platform=iOS Simulator,name=iPhone 5&amp;#39;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;-destination&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;platform=iOS Simulator,name=iPhone 5s&amp;#39;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And there we have it! Now, Travis will run our tests on an iOS simulator
to verify that our crate is working.&lt;/p&gt;

&lt;p&gt;For an example of this in action, check out the
&lt;a href=&quot;https://github.com/SSheldon/rust-objc&quot;&gt;objc crate&lt;/a&gt;.
It may seem like a lot of hoops to jump though, but I am impressed with
the ease of setting up Rust itself for cross-compilation.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title type="html">Objective-C from Rust: objc_msgSend</title>
    <link href="http://sasheldon.com/blog/2015/08/02/objective-c-from-rust-objc_msgsend/"/>
    <updated>2015-08-03T01:53:50-05:00</updated>
    <id>http://sasheldon.com/blog/2015/08/02/objective-c-from-rust-objc_msgsend</id>
    <content type="html">&lt;p&gt;I previously wrote about how to &lt;a href=&quot;/blog/2014/11/28/interoperating-between-objective-c-and-rust/&quot;&gt;interoperate between Objective-C and Rust&lt;/a&gt;
and use a Rust macro to pass a variable number of arguments to &lt;code&gt;objc_msgSend&lt;/code&gt;.
Well, there&amp;rsquo;s a problem with this: &lt;code&gt;objc_msgSend&lt;/code&gt; isn&amp;rsquo;t a variadic function!&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;&lt;code&gt;objc_msgSend&lt;/code&gt; is actually a &amp;ldquo;trampoline&amp;rdquo; that works by jumping directly to
the implementation of the method, not calling it and passing parameters.
Safely calling it requires first casting it to the type of the underlying
method implementation, like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objc&quot; data-lang=&quot;objc&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// id result = [obj description];&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;SEL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objc_msgSend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you try to call &lt;code&gt;objc_msgSend&lt;/code&gt; as if it were a variadic function,
&lt;a href=&quot;https://github.com/servo/cocoa-rs/pull/74#issuecomment-75492331&quot;&gt;weird things can happen&lt;/a&gt;!&lt;/p&gt;

&lt;h2 id=&quot;handling-arguments&quot;&gt;Handling arguments&lt;/h2&gt;

&lt;p&gt;How can we handle &lt;code&gt;objc_msgSend&lt;/code&gt; in Rust? Let&amp;rsquo;s try to write a
wrapper function that calls it correctly.
It&amp;rsquo;s easy to see how we could do this for, say, two arguments:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;msg_send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Sel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg1&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg2&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Transmute objc_msgSend to the type of the method implementation&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send_fn&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mem&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;transmute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objc_msgSend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send_fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But our function needs to be able to accept one argument, or no arguments,
or more than 2. This sounds a lot like function overloading, which Rust
doesn&amp;rsquo;t support. However, there&amp;rsquo;s a pattern that can emulate function
overloading in Rust: functions with a generic parameter. In our case,
our function could take a generic parameter that is the arguments,
represented as a tuple:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;msg_send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Sel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;How do we implement this now?
Well, it was easy to implement for a fixed number of arguments,
so we can let the arguments themselves handle calling &lt;code&gt;objc_msgSend&lt;/code&gt;.
Let&amp;rsquo;s add a &lt;code&gt;MessageArguments&lt;/code&gt; trait and implement it for tuples:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MessageArguments&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Sel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Transmute objc_msgSend to the type of the method implementation&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send_fn&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mem&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;transmute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objc_msgSend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send_fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/SSheldon/rust-objc/blob/2bc409b/src/message.rs#L134-L175&quot;&gt;Using a macro&lt;/a&gt;,
we can easily implement this trait for tuples from size 0 to some upper bound.
Our function simply becomes:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;msg_send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Sel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;R&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;MessageArguments&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now we&amp;rsquo;re no longer pretending that &lt;code&gt;objc_msgSend&lt;/code&gt; is variadic!&lt;/p&gt;

&lt;h2 id=&quot;return-types&quot;&gt;Return types&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s one other caveat with &lt;code&gt;objc_msgSend&lt;/code&gt;, though:
different versions of it are used for different return types.
Which version is used depends on the calling conventions of the architecture.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s encapsulate this with a simple function that returns the correct
version of &lt;code&gt;objc_msgSend&lt;/code&gt; for the return type:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;msg_send_fn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can implement this for different architectures with a
&lt;a href=&quot;https://doc.rust-lang.org/stable/reference.html#conditional-compilation&quot;&gt;&lt;code&gt;cfg&lt;/code&gt; attribute&lt;/a&gt;.
x86&amp;rsquo;s calling conventions are &lt;a href=&quot;https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html&quot;&gt;arguably the most complicated&lt;/a&gt;,
so for it this function would look like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;#[cfg(target_arch = &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;x86&amp;quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;msg_send_fn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;R&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;any&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;TypeId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type_id&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TypeId&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;of&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mem&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;size_of&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type_id&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TypeId&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;of&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;f32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type_id&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TypeId&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;of&lt;/span&gt;::&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;f64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mem&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;transmute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objc_msgSend_fpret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mem&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;transmute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objc_msgSend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mem&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;transmute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objc_msgSend_stret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With this &lt;code&gt;msg_send_fn&lt;/code&gt; function &lt;a href=&quot;https://github.com/SSheldon/rust-objc/blob/2bc409b/src/message.rs#L14-L112&quot;&gt;defined for each architecture&lt;/a&gt;,
we can use it to get the correct version of &lt;code&gt;objc_msgSend&lt;/code&gt; for
our return type.&lt;/p&gt;

&lt;p&gt;At this point we&amp;rsquo;re invisibly handling &lt;code&gt;objc_msgSend&lt;/code&gt; correctly for any
combination of argument types and any return type. We can further
&lt;a href=&quot;https://github.com/SSheldon/rust-objc/blob/2bc409b/src/macros.rs#L58-L83&quot;&gt;wrap it with a macro&lt;/a&gt;
to make it more ergonomic; in the end, calling Objective-C methods is nearly
as easy from Rust as it is in Objective-C!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title type="html">Interoperating Between Objective-C and Rust</title>
    <link href="http://sasheldon.com/blog/2014/11/28/interoperating-between-objective-c-and-rust/"/>
    <updated>2014-11-28T03:52:17-06:00</updated>
    <id>http://sasheldon.com/blog/2014/11/28/interoperating-between-objective-c-and-rust</id>
    <content type="html">&lt;p&gt;Since the Objective-C runtime exposes a C interface, it&amp;rsquo;s actually pretty easy
to interact with from Rust.
Over the past months I&amp;rsquo;ve worked on a Rust wrapper around the
&lt;a href=&quot;https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/index.html&quot;&gt;Objective-C runtime&lt;/a&gt;
and some classes of the
&lt;a href=&quot;https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/ObjC_classic/index.html&quot;&gt;Foundation framework&lt;/a&gt;,
creatively called &lt;a href=&quot;https://github.com/SSheldon/rust-objc/&quot;&gt;rust-objc&lt;/a&gt;.
I had hoped to learn more about Rust&amp;rsquo;s foreign function interface and the
Objective-C runtime, but along the way I also encountered some interesting
challenges in API design.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;h2 id=&quot;calling-objective-c-methods&quot;&gt;Calling Objective-C methods&lt;/h2&gt;

&lt;p&gt;If we want to interact with Objective-C from Rust, one of the first things
we&amp;rsquo;ll need to be able to do is call methods on Objective-C objects.
Let&amp;rsquo;s consider this example where we have an &lt;code&gt;NSString&lt;/code&gt; pointer, &lt;code&gt;string&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objc&quot; data-lang=&quot;objc&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UTF8String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since the Objective-C runtime actually has a C interface, we can invoke methods
in C using the &lt;a href=&quot;https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/index.html#//apple_ref/c/func/objc_msgSend&quot;&gt;&lt;code&gt;objc_msgSend&lt;/code&gt;&lt;/a&gt;
function. Our previous Objective-C code is equivalent to this C:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SEL&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sel_registerName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;UTF8String&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objc_msgSend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now that we see the C code, the translation into Rust is pretty straightforward
using &lt;a href=&quot;http://doc.rust-lang.org/guide-ffi.html&quot;&gt;Rust&amp;rsquo;s foreign function interface&lt;/a&gt;.
Once we&amp;rsquo;ve set up an interface for the functions of the Objective-C runtime,
we can write:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;UTF8String&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;with_c_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sel_registerName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objc_msgSend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_char&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nice! But this is Rust, we can make this better with
&lt;a href=&quot;http://doc.rust-lang.org/guide-macros.html&quot;&gt;Rust&amp;rsquo;s powerful macros&lt;/a&gt;.
We can even support methods with arguments using a macro like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;fm&quot;&gt;macro_rules!&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;$obj&lt;/span&gt;:&lt;span class=&quot;nc&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;$($name&lt;/span&gt;:&lt;span class=&quot;nc&quot;&gt;ident&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;: &lt;span class=&quot;cp&quot;&gt;$arg&lt;/span&gt;:&lt;span class=&quot;nc&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sel_name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;fm&quot;&gt;concat!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;fm&quot;&gt;stringify!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;&amp;#39;:&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sel&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sel_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;with_c_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sel_registerName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objc_msgSend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;$obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sel&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;$(,$arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By adding a special case to our macro for the no-argument case, we can rewrite
our example as:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UTF8String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_char&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And so we have a convenient way to call Objective-C methods with a syntax that
feels comfortable for Objective-C developers.&lt;/p&gt;

&lt;h2 id=&quot;representing-objective-c-objects&quot;&gt;Representing Objective-C objects&lt;/h2&gt;

&lt;p&gt;In our previous examples, we&amp;rsquo;ve been working with a variable named &lt;code&gt;string&lt;/code&gt;,
but what is the type of this variable? Well, in Objective-C it&amp;rsquo;d be declared
like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objc&quot; data-lang=&quot;objc&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The identical declaration in Rust would look like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Okay, so we&amp;rsquo;ll need some sort of &lt;code&gt;NSString&lt;/code&gt; type in Rust.
Since we don&amp;rsquo;t actually know or care about the memory layout of the &lt;code&gt;NSString&lt;/code&gt;,
we could declare it simply as a unit struct:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There&amp;rsquo;s a problem with this, though: it allows user to construct an &lt;code&gt;NSString&lt;/code&gt;
on the stack, and Objective-C objects only live on the heap!&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string_on_stack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string_on_stack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UTF8String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_char&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Oops!&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We don&amp;rsquo;t actually want users to be able to construct our &lt;code&gt;NSString&lt;/code&gt;, we&amp;rsquo;ll just
be giving them pointers and references to one. To avoid this, we could use a
phantom type:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By using an enum with no variants, &lt;code&gt;NSString&lt;/code&gt; will be a valid type but there is
no way for users to instantiate an instance of one.&lt;/p&gt;

&lt;p&gt;Unfortunately, this still has a problem; if a user has a reference to this
&lt;code&gt;NSString&lt;/code&gt;, they can still dereference it in safe code:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string_on_stack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This happens because the Rust compiler sees that our enum has no fields that
can&amp;rsquo;t be copied, and therefore infers that our enum is copyable as well.
To solve this, we must use the
&lt;a href=&quot;http://doc.rust-lang.org/std/kinds/marker/struct.NoCopy.html&quot;&gt;&lt;code&gt;NoCopy&lt;/code&gt;&lt;/a&gt; marker:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nocopy&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;NoCopy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This also lets us use a struct again; now that it has a private field, users
cannot construct an &lt;code&gt;NSString&lt;/code&gt; themselves. As long as we don&amp;rsquo;t construct an
&lt;code&gt;NSString&lt;/code&gt; on the stack in our module, there will be no way in safe code for
users to end up with a stack-allocated &lt;code&gt;NSString&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;drawbacks-of-this-representation&quot;&gt;Drawbacks of this representation&lt;/h3&gt;

&lt;p&gt;This isn&amp;rsquo;t a perfect solution, because even if there&amp;rsquo;s no way to get a
stack-allocated &lt;code&gt;NSString&lt;/code&gt;, the compiler will still accept definitions like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vector&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Additionally, the following code will compile and run without doing anything:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;mem&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;swap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Doesn&amp;#39;t actually do anything&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ideally, we would opt out of the
&lt;a href=&quot;http://doc.rust-lang.org/std/kinds/trait.Sized.html&quot;&gt;&lt;code&gt;Sized&lt;/code&gt;&lt;/a&gt; trait so that
the compiler would disallow these types as local variables, but unfortunately
it doesn&amp;rsquo;t seem possible to have an unsized type without all references to it
becoming &amp;ldquo;fat&amp;rdquo; two-word references.&lt;/p&gt;

&lt;h3 id=&quot;why-not-just-wrap-the-pointer&quot;&gt;Why not just wrap the pointer?&lt;/h3&gt;

&lt;p&gt;If an &lt;code&gt;NSString&lt;/code&gt; can never exist on the stack, why don&amp;rsquo;t we just prevent that
by making a struct that wraps a pointer?&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let&amp;rsquo;s consider the case of an &lt;code&gt;NSArray&lt;/code&gt; of &lt;code&gt;NSString&lt;/code&gt;s.
If we want to get a string from the array, our array can&amp;rsquo;t return references
to this &lt;code&gt;NSString&lt;/code&gt; struct:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;object_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;: &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;NSArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;uint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string_ptr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objectAtIndex&lt;/span&gt;:&lt;span class=&quot;nc&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;string_ptr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Oops! string doesn&amp;#39;t live past this method&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Instead, we&amp;rsquo;d have to return this &lt;code&gt;NSString&lt;/code&gt; struct by value, and then it&amp;rsquo;s
not tied to the lifetime of our array at all.
This would allow us to get multiple copies of an &lt;code&gt;NSString&lt;/code&gt; from our array and
try to mutate them simultaneously, which would cause a race condition.
To fix this we&amp;rsquo;d need to add a lifetime parameter to indicate that the string
is only valid as long as the array is mutably borrowed.
Not all strings should have this lifetime parameter, though, so we&amp;rsquo;d actually
end up needing 3 different &lt;code&gt;NSString&lt;/code&gt; representations:
an owned string (&lt;code&gt;NSString&lt;/code&gt;),
one representing an immutable borrow (&lt;code&gt;NSStringRef&amp;lt;&amp;#39;a&amp;gt;&lt;/code&gt;),
and one representing a mutable borrow (&lt;code&gt;NSStringRefMut&amp;lt;&amp;#39;a&amp;gt;&lt;/code&gt;).
This results in an interface that looks odd to both Rust and Objective-C
developers.&lt;/p&gt;

&lt;p&gt;I felt that, despite the imperfections of representing Objective-C objects as
structs in Rust, it makes for a much more usable API.&lt;/p&gt;

&lt;h2 id=&quot;a-safe-rust-interface&quot;&gt;A safe Rust interface&lt;/h2&gt;

&lt;p&gt;Now that we&amp;rsquo;ve got a struct for representing our &lt;code&gt;NSString&lt;/code&gt;, we can implement
some methods on it. For example, we can wrap the
&lt;a href=&quot;https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/#//apple_ref/occ/instp/NSString/UTF8String&quot;&gt;&lt;code&gt;UTF8String&lt;/code&gt;&lt;/a&gt;
method using idiomatic Rust types:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;as_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UTF8String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_str_to_static_slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we can also see one of the challenges of wrapping Objective-C with a safe
interface. Of the C string returned by &lt;code&gt;UTF8String&lt;/code&gt;, the docs say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This C string is a pointer to a structure inside the string object, which may
have a lifetime shorter than the string object and will certainly not have a
longer lifetime.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We&amp;rsquo;ve assumed that as long as the string isn&amp;rsquo;t mutated, the internal pointer is
still valid, but since Foundation is closed source there isn&amp;rsquo;t really a way for
us to verify this.&lt;/p&gt;

&lt;h3 id=&quot;inheritance&quot;&gt;Inheritance&lt;/h3&gt;

&lt;p&gt;What happens when we decide to implement a safe interface for &lt;code&gt;NSMutableString&lt;/code&gt;?
Since &lt;code&gt;NSMutableString&lt;/code&gt; inherits from &lt;code&gt;NSString&lt;/code&gt;, it should also have this
method, but Rust structs don&amp;rsquo;t allow inheritance.
Instead of just duplicating the method, we can implement it in a trait:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;INSString&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;as_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UTF8String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_str_to_static_slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;INSString&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now if we just implement &lt;code&gt;INSString&lt;/code&gt; for &lt;code&gt;NSMutableString&lt;/code&gt;, it&amp;rsquo;ll get this
functionality, too.
This trait is also useful for generic programming; with it, we can write
functions that take any type that implements the &lt;code&gt;INSString&lt;/code&gt; trait and will
accept either an &lt;code&gt;NSString&lt;/code&gt; or an &lt;code&gt;NSMutableString&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There is a drawback to this approach, though: users could implement this trait
for any type inappropriately.
Since it doesn&amp;rsquo;t require any other methods implemented, I could, in safe code,
just implement the &lt;code&gt;INSString&lt;/code&gt; trait for &lt;code&gt;int&lt;/code&gt; and then have undefined
behavior by sending Objective-C messages on an &lt;code&gt;int&lt;/code&gt;.
I don&amp;rsquo;t know of a way to prevent this without losing the convenience of
only declaring these methods once.&lt;/p&gt;

&lt;h2 id=&quot;objective-c-memory-management&quot;&gt;Objective-C memory management&lt;/h2&gt;

&lt;p&gt;Great, at this point we can call methods from an &lt;code&gt;NSString&lt;/code&gt; reference,
but where does this reference come from? What&amp;rsquo;s its lifetime?&lt;/p&gt;

&lt;p&gt;Our Objective-C objects must be retained while we&amp;rsquo;re using them and released
when we&amp;rsquo;re done with them, so this is a great fit for a custom smart pointer in
Rust:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Drop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Deref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;deref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;*&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can use this to create safe wrappers over an object&amp;rsquo;s initializers:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;NSString&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;with_c_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objc_getClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This finally allows us to work with an &lt;code&gt;NSString&lt;/code&gt; without any unsafe blocks!&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt;::&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;fm&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;as_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When the &lt;code&gt;Id&lt;/code&gt; goes out of scope, the object will automatically be released.
With just a few lines of Rust code, we&amp;rsquo;ve implemented our own simplified
version of &lt;a href=&quot;http://clang.llvm.org/docs/AutomaticReferenceCounting.html&quot;&gt;Objective-C&amp;rsquo;s automatic reference counting&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;mutability&quot;&gt;Mutability&lt;/h3&gt;

&lt;p&gt;Sometimes we may want to retain a shared object, but it wouldn&amp;rsquo;t be safe to do
this if we implement
&lt;a href=&quot;http://doc.rust-lang.org/std/ops/trait.DerefMut.html&quot;&gt;&lt;code&gt;DerefMut&lt;/code&gt;&lt;/a&gt; for any
&lt;code&gt;Id&lt;/code&gt;, because if it is mutably dereferenced in multiple places we&amp;rsquo;d have
aliasing mut references. Similarly, it&amp;rsquo;d be safe to implement
&lt;a href=&quot;http://doc.rust-lang.org/std/clone/trait.Clone.html&quot;&gt;&lt;code&gt;Clone&lt;/code&gt;&lt;/a&gt;
when the object is shared, but an &lt;code&gt;Id&lt;/code&gt; that implements &lt;code&gt;DerefMut&lt;/code&gt; shouldn&amp;rsquo;t
implement &lt;code&gt;Clone&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I chose to resolve this was by adding a phantom type parameter to &lt;code&gt;Id&lt;/code&gt; which is
either &lt;code&gt;Owned&lt;/code&gt; or &lt;code&gt;Shared&lt;/code&gt;. Then, we can implement &lt;code&gt;Clone&lt;/code&gt; only for a shared
&lt;code&gt;Id&lt;/code&gt;, and we can implement &lt;code&gt;DerefMut&lt;/code&gt; only for an owned &lt;code&gt;Id&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;retain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DerefMut&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;deref_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;kp&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can also allow an owned &lt;code&gt;Id&lt;/code&gt; to be &amp;ldquo;downgraded&amp;rdquo; to a shared &lt;code&gt;Id&lt;/code&gt;
and then cloned.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Owned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;share&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&quot;nc&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;: &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Thinking about Objective-C in terms of Rust&amp;rsquo;s memory semantics leads to some
interesting questions, and these phantom types will be used again.
For example, unlike a &lt;code&gt;Vec&lt;/code&gt; in Rust, an &lt;code&gt;NSArray&lt;/code&gt; can be copied without
copying all of its elements.
If we consider the array to own its objects, this isn&amp;rsquo;t safe because it could create aliasing mut references.
However, it&amp;rsquo;s totally fine if the array&amp;rsquo;s objects are shared.
We can resolve this by using an approach similar to &lt;code&gt;Id&lt;/code&gt;:
if our &lt;code&gt;NSArray&lt;/code&gt; has a type parameter for &lt;code&gt;Owned&lt;/code&gt; or &lt;code&gt;Shared&lt;/code&gt;,
we only implement copying for the shared array.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title type="html">Simplifying JSON Response Mocks With Jinja</title>
    <link href="http://sasheldon.com/blog/2013/12/14/simplifying-json-response-mocks-with-jinja/"/>
    <updated>2013-12-14T15:43:01-06:00</updated>
    <id>http://sasheldon.com/blog/2013/12/14/simplifying-json-response-mocks-with-jinja</id>
    <content type="html">&lt;p&gt;For documenting and testing large APIs, response mocks can be a very useful
tool. They not only provide examples for the users of your API, but they can be
used in automated tests as if you had received real data without actually
hitting the network.&lt;/p&gt;

&lt;p&gt;Creating and maintaining a large collection of response mocks can be greatly
simplified by preprocessing them with a template engine like Python&amp;rsquo;s
&lt;a href=&quot;http://jinja.pocoo.org/&quot;&gt;Jinja&lt;/a&gt;. Although this adds another step to your build
process, it allows some really useful functionality!&lt;/p&gt;

&lt;!-- more --&gt;

&lt;h3 id=&quot;variables&quot;&gt;Variables&lt;/h3&gt;

&lt;p&gt;One of the first advantages of processing response mocks with Jinja is that
we can use &lt;a href=&quot;http://jinja.pocoo.org/docs/templates/#variables&quot;&gt;variables&lt;/a&gt; when
generating them.
For example, let&amp;rsquo;s consider an API that can respond with information about a
person. One of our mock responses is a Person object, like so:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;first_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;John&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;last_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Smith&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;phone_number&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;415 555-1234&amp;quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However, developers in different locations require that the phone number have a
local area code. In this situation, we could simply change the mock to be:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js+jinja&quot; data-lang=&quot;js+jinja&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;first_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;John&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;last_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Smith&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;phone_number&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;area_code&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; 555-1234&amp;quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, we only need to process the mocks through Jinja with the area code in
the context to generate mocks using the new area code. We can render the mock
with &lt;code&gt;area_code=&amp;#39;312&amp;#39;&lt;/code&gt; in the context to get the phone number &lt;code&gt;&amp;quot;312 555-1234&amp;quot;&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;conditionals&quot;&gt;Conditionals&lt;/h3&gt;

&lt;p&gt;We can further take advantage of Jinja to template our mocks using more
complicated control flows. For example, suppose that we wanted to format our
mock from the previous example to include a Person&amp;rsquo;s last name sometimes, but
not in other cases. We can accomplish this simply in Jinja with an
&lt;a href=&quot;http://jinja.pocoo.org/docs/templates/#if&quot;&gt;if block&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js+jinja&quot; data-lang=&quot;js+jinja&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;first_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;John&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;last_names_included&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;last_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Smith&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;phone_number&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;415 555-1234&amp;quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If this mock is rendered with &lt;code&gt;last_names_included=True&lt;/code&gt; in the context,
it will include the &lt;code&gt;last_name&lt;/code&gt; field, and if not it will be absent!&lt;/p&gt;

&lt;h3 id=&quot;including-mocks&quot;&gt;Including mocks&lt;/h3&gt;

&lt;p&gt;The previous examples might feel a little contrived, but importing one mock
from another is one of the greatest benefits of Jinja.
A large API will likely have objects with a common scheme that are used in
multiple responses, and it can be very convenient and greatly simplify our
mocks if we can define an object once and reference it in many places.&lt;/p&gt;

&lt;p&gt;Perhaps multiple responses from our example API include addresses in a common
format. We can provide an example address in its own file:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;street_address&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;21 2nd Street&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;city&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;New York&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;state&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;NY&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;postal_code&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;10021&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, in any response that includes an address, instead of copy-pasting this
example address or creating an entirely new address, we can simply include our
address in the mock with
&lt;a href=&quot;http://jinja.pocoo.org/docs/templates/#include&quot;&gt;Jinja&amp;rsquo;s include tag&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js+jinja&quot; data-lang=&quot;js+jinja&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;first_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;John&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;last_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Smith&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;address&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;address.json&amp;#39;&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;phone_number&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;415 555-1234&amp;quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The include tag does not only let us avoid duplicating data; if each object is
stored in its own file, it can turn our response mocks into a simple
composition of objects where the structure is clear at a glance.&lt;/p&gt;

&lt;h3 id=&quot;extending-mocks&quot;&gt;Extending mocks&lt;/h3&gt;

&lt;p&gt;I commonly need to create a response mock that is modified slightly from an
existing one, like a version of the response that has a parameter with a
different value or that specifies some optional parameters.
I think of this like JSON &amp;ldquo;inheritance&amp;rdquo;, where an object gets all the values
from a base object but can then override them.&lt;/p&gt;

&lt;p&gt;With Jinja, we call allow this &amp;ldquo;inheritance&amp;rdquo; by creating a way to extend mocks.
We can simply model the changes we want and the base object as Python
&lt;a href=&quot;http://docs.python.org/2/library/stdtypes.html#mapping-types-dict&quot;&gt;&lt;code&gt;dict&lt;/code&gt;&lt;/a&gt;s and
use the &lt;a href=&quot;http://docs.python.org/2/library/stdtypes.html#dict.update&quot;&gt;&lt;code&gt;update&lt;/code&gt;&lt;/a&gt;
method to override the items in the base dictionary with our changes.
The dictionary of updates will be specified in JSON, so a function to return
the JSON that results from updating looks like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;json_update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;updates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;updates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sort_keys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can then include this function in Jinja&amp;rsquo;s context to access it within our
response mocks. This allows us to write an &lt;code&gt;extend_json&lt;/code&gt;
&lt;a href=&quot;http://jinja.pocoo.org/docs/templates/#macros&quot;&gt;macro&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-jinja&quot; data-lang=&quot;jinja&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;macro&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;include_json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;endmacro&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;macro&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;extend_json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;base_path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;json_update&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;include_json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;base_path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;caller&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;endmacro&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This macro will be called with the JSON updates as its body so that they are
accessible within the macro through the &lt;code&gt;caller()&lt;/code&gt; function.
The &lt;code&gt;include_json&lt;/code&gt; macro just allows us to use an included file as an argument
to the &lt;code&gt;json_update&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;To see this macro in action, let&amp;rsquo;s consider our Person object with an age
parameter:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;first_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;John&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;last_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Smith&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;age&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;phone_number&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;415 555-1234&amp;quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To create another Person object with a different age, we only have to do this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js+jinja&quot; data-lang=&quot;js+jinja&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;extend_json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;person.json&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;age&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;70&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;endcall&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It&amp;rsquo;s useful to note that the &lt;code&gt;extend_json&lt;/code&gt; macro must be available in this
file, so we&amp;rsquo;ll likely need to
&lt;a href=&quot;http://jinja.pocoo.org/docs/templates/#import&quot;&gt;import&lt;/a&gt; it from the file in
which it is declared.&lt;/p&gt;

&lt;p&gt;The functionality of Jinja doesn&amp;rsquo;t end with macros; after all, it&amp;rsquo;s a
full-fledged template engine with many
&lt;a href=&quot;http://jinja.pocoo.org/docs/templates/#list-of-builtin-filters&quot;&gt;built-in filters&lt;/a&gt;
and a powerful (if complicated)
&lt;a href=&quot;http://jinja.pocoo.org/docs/extensions/&quot;&gt;extension system&lt;/a&gt;.
This article just covered the functionality that I&amp;rsquo;ve found useful, but Jinja
can surely adapt to meet whatever your needs are.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title type="html">Waiting for Octopress 2.0's Successor</title>
    <link href="http://sasheldon.com/blog/2013/07/07/waiting-for-octopress-2-successor/"/>
    <updated>2013-07-07T02:24:00-05:00</updated>
    <id>http://sasheldon.com/blog/2013/07/07/waiting-for-octopress-2-successor</id>
    <content type="html">&lt;p&gt;The next version of &lt;a href=&quot;http://octopress.org/&quot;&gt;Octopress&lt;/a&gt; is packed full of
&lt;a href=&quot;https://gist.github.com/imathis/e9c2ee2406e93c4269e8&quot;&gt;awesome improvements&lt;/a&gt;.
Octopress will change massively to be more extensible and customizable while
still being as powerful and easy as ever; as such, this update has been in
development for a long time, still not having released officially.&lt;/p&gt;

&lt;p&gt;In anticipation of this update, I periodically check the
&lt;a href=&quot;https://twitter.com/octopress&quot;&gt;Octopress Twitter&lt;/a&gt; for news and have
encountered many release date estimates. Estimating time for development is
&lt;a href=&quot;http://blog.hut8labs.com/coding-fast-and-slow.html&quot;&gt;notoriously difficult&lt;/a&gt;,
so I&amp;rsquo;ve compiled a lighthearted Twitter history of Octopress 2.0&amp;rsquo;s
successor and its estimated release dates.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;The follow-up to Octopress 2.0 was originally envisioned as a much smaller set
of changes to be called Octopress 2.1. The release of this version was first
mentioned in March of 2012 as &amp;ldquo;soon&amp;rdquo;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;That will be shipping in 2.1 (soon).&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/184723922556686337&quot;&gt;March 27, 2012&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By May, the outlook for Octopress 2.1 was looking good enough that its release
seemed imminent, within a &amp;ldquo;day or two&amp;rdquo;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Have you tried 2.1 yet? I&amp;rsquo;m hoping to release it in the next day or two.&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/205288498591309824&quot;&gt;May 23, 2012&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But it was not to be! A week and a half later, in June, 2.1 was still looking
as though it would release &amp;ldquo;soon&amp;rdquo;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;2.1 should be releasing soon. It has lots of goodies and fixes.&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/209408163571707905&quot;&gt;June 3, 2012&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next month, July, enough progress had been made to offer a new estimate that
2.1 would release in a &amp;ldquo;week or two&amp;rdquo;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It&amp;rsquo;ll be released once I finish a couple of remaining features. I&amp;rsquo;m hoping that&amp;rsquo;ll be in the next week or two.&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/219804276447379456&quot;&gt;July 2, 2012&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It was not until 4 months later in November that the next estimation was made
that 2.1 would be released before the end of 2012.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I can’t give a solid date right now. But I expect to have a release before years end.&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/268762061197148161&quot;&gt;November 14, 2012&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With an acknowledgement of the difficulty in estimating, by January 2013
Octopress 2.1 was predicted to be completed &amp;ldquo;soon&amp;rdquo;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We&amp;rsquo;re working on an asset pipeline, fixing any critical bugs and setting up a migration for 2.0. It&amp;rsquo;s hard to estimate, but soon.&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/289446177575948289&quot;&gt;January 10, 2013&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In February, it seemed that the eagerly awaited update would be finalized
within a &amp;ldquo;month or two&amp;rdquo;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;right now [the 2.1 branch is] not entirely stable. We’re working on a few large features then we’ll release it in the next month or two.&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/300027017397665793&quot;&gt;February 8, 2013&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the tremendous amount of effort that had gone into the update, it seemed
more fitting that the major version change, so it would instead be released as
&lt;a href=&quot;https://twitter.com/octopress/status/306972342582657026&quot;&gt;Octopress 3.0&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By March, this 3.0 update&amp;rsquo;s release date was further clarified to &amp;ldquo;mid April&amp;rdquo;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Right now, 2.1 is under pretty active development. We’re shooting for a mid April release, so it might be a good idea to wait.&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/314553072535887872&quot;&gt;March 20, 2013&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My mid April, though, it seemed more likely that the release would occur
later in the month.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[The next release is] in flux right now. We’re hoping for late April.&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/323868125709864960&quot;&gt;April 15, 2013&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Although an April release had been missed, by late May it seemed that there
would be a 3.0 release candidate available within a &amp;ldquo;month or so&amp;rdquo;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We’re currently working through getting some core functionality working, but I’ll be announcing an RC in the next month or so.&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/339044122801360896&quot;&gt;May 27, 2013&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At the end of June, the ambitious Octopress 3.0 was still predicted to arrive
during the summer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[3.0 is] Going well. We’re targeting a summer release, still lots to do though. :)&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/351439257996505088&quot;&gt;June 30, 2013&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And so we still anticipate the official release of this update that will
redefine Octopress. This does showcase a neat benefit of open source;
despite not being officilly released, you can try out 3.0 and closely follow
its development &lt;a href=&quot;https://github.com/imathis/octopress/tree/2.1&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Regardless of Octopress&amp;rsquo; history of imprecise estimates, I have great faith in
its developers to deliver such an ambitious update. I&amp;rsquo;ll keep an eye out on
Twitter for an announcement that Octopress 3.0 has finally been perfected!&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;&lt;strong&gt;Update (Aug 18, 2013):&lt;/strong&gt;
By the end of July, there was still &amp;ldquo;a ways to go&amp;rdquo; on Octopress 3.0, but
version 2.1 of Octopress was resurrected as a smaller, incremental upgrade on
the way to Octopress 3.0.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;we still have a ways to go. Right now I’m working on 2.1 which adds support for Jekyll 1.0 and uses Guard for watching files.&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/361299670313615360&quot;&gt;July 27, 2013&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr&gt;

&lt;p&gt;&lt;strong&gt;Update (Feb 15, 2014):&lt;/strong&gt;
In September, Octopress 3.0 still wasn&amp;rsquo;t ready for release, but it seemed
mature enough that a blog post was promised detailing the roadmap leading up
to its release.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We’ve finally nailed it down. Blog post coming soon after @imathis gets back from BlendConf.&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/375377966727192576&quot;&gt;September 4, 2013&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Despite it originally being anticipated that this blog post would be published
&lt;a href=&quot;https://twitter.com/octopress/statuses/381781655385812992&quot;&gt;within a week&lt;/a&gt;,
by mid October there were still details to be ironed out.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There’s a draft. Still ironing out some details. :)&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/392425128442994688&quot;&gt;October 21, 2013&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By the new year, it appeared that version 3.0 was still &amp;ldquo;a couple of months&amp;rdquo;
away from being released.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The update is coming with Octopress 3.0 (which is probably a couple of months out) you should be able to migrate content easily.&lt;/p&gt;

&lt;p&gt;— @octopress &lt;a href=&quot;https://twitter.com/octopress/status/420592959672029184&quot;&gt;January 7, 2014&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It also appears that the previously proposed version 2.1 was abandoned,
so no new version is slated before Octopress 3.0.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title type="html">Octopress</title>
    <link href="http://sasheldon.com/blog/2012/11/15/octopress/"/>
    <updated>2012-11-15T22:14:00-06:00</updated>
    <id>http://sasheldon.com/blog/2012/11/15/octopress</id>
    <content type="html">&lt;p&gt;I really like git; if I could keep everything under version control, I would.
I&amp;rsquo;ve started writing all my papers in LaTeX instead of Word, not only because
it&amp;rsquo;s cleaner and can provide more control, but because then I can version
control them. Hell, I&amp;rsquo;ve even started keeping my Borderlands 2 game saves
backed up in a git repository.&lt;/p&gt;

&lt;p&gt;Imagine my delight, then, when I discovered &lt;a href=&quot;http://octopress.org/&quot;&gt;Octopress&lt;/a&gt;.
Octopress is a framework that makes it really easy to generate a blog just from
a set of markdown files that can be hosted on
&lt;a href=&quot;http://pages.github.com/&quot;&gt;GitHub pages&lt;/a&gt;. I&amp;rsquo;ve already been using GitHub to
host my personal website, and using it to host a blog would be pretty swell.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve worked through the documentation to get a blog up and running; after all,
I have homework to be working on right now, so I need to find something else to
do. Nevermind the fact that I never actually put in the effort to blog or can
come up with interesting topics; if nothing else, this was just an exercise to
test out Octopress and to become more familiar with the features of GitHub
pages.&lt;/p&gt;
</content>
  </entry>
  
</feed>
