people.gnome.org_federico.atom.xml - sfeed_tests - sfeed tests and RSS and Atom files
 (HTM) git clone git://git.codemadness.org/sfeed_tests
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       people.gnome.org_federico.atom.xml (1402111B)
       ---
            1 <?xml version="1.0" encoding="utf-8"?>
            2 <feed xmlns="http://www.w3.org/2005/Atom"><title>Federico's Blog</title><link href="https://people.gnome.org/~federico/blog/" rel="alternate"></link><link href="https://people.gnome.org/~federico/blog/feeds/atom.xml" rel="self"></link><id>https://people.gnome.org/~federico/blog/</id><updated>2021-09-01T13:57:47-05:00</updated><subtitle></subtitle><entry><title>GNOME themes, an incomplete status report, and how you can help</title><link href="https://people.gnome.org/~federico/blog/gnome-themes.html" rel="alternate"></link><published>2021-09-01T13:57:47-05:00</published><updated>2021-09-01T13:57:47-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2021-09-01:/~federico/blog/gnome-themes.html</id><summary type="html">&lt;p&gt;"Themes in GNOME" is a complicated topic in technical and social
            3 terms.  Technically there are a lot of incomplete moving parts;
            4 socially there is a lot of missing documentation to be written, a lot
            5 of miscommunication and mismatched expectations.&lt;/p&gt;
            6 &lt;p&gt;The following is a brief and incomplete, but hopefully encouraging,
            7 summary …&lt;/p&gt;</summary><content type="html">&lt;p&gt;"Themes in GNOME" is a complicated topic in technical and social
            8 terms.  Technically there are a lot of incomplete moving parts;
            9 socially there is a lot of missing documentation to be written, a lot
           10 of miscommunication and mismatched expectations.&lt;/p&gt;
           11 &lt;p&gt;The following is a brief and incomplete, but hopefully encouraging,
           12 summary of the status of themes in GNOME.  I want to give you an
           13 overall picture of the status of things, and more importantly, an idea
           14 of how you can help.  This is not a problem that can be solved by a
           15 small team of platform developers.&lt;/p&gt;
           16 &lt;p&gt;I wish to thank Alexander Mikhaylenko for providing most of the
           17 knowledge in this post.&lt;/p&gt;
           18 &lt;h1&gt;Frame of reference&lt;/h1&gt;
           19 &lt;p&gt;First, I urge you to read Cassidy James Blaede's comprehensive "&lt;a href="https://blog.elementary.io/the-need-for-a-freedesktop-dark-style-preference/"&gt;The
           20 Need for a FreeDesktop Dark Style
           21 Preference&lt;/a&gt;".
           22 That gives an excellent, well-researched introduction to the "dark
           23 style" problem, the status quo on other platforms, and exploratory
           24 plans for GNOME and Elementary from 2019.&lt;/p&gt;
           25 &lt;p&gt;Go ahead, read it.  It's very good.&lt;/p&gt;
           26 &lt;p&gt;There is also a &lt;a href="https://www.youtube.com/watch?v=gi_3b81eBUE&amp;amp;list=PLkmRdYgttscEuv9v2-H9P5FBj8-td_Nri&amp;amp;index=31"&gt;GUADEC talk about Cassidy's
           27 research&lt;/a&gt;
           28 if you prefer to watch a video.&lt;/p&gt;
           29 &lt;p&gt;Two key take-aways from this: First, about this being a
           30 &lt;strong&gt;preference&lt;/strong&gt;, not a system-enforced setting:&lt;/p&gt;
           31 &lt;blockquote&gt;
           32 &lt;p&gt;I’m explicitly using the language “Dark Style Preference” for a
           33 reason! As you’ll read further on, it’s important that this is
           34 treated as a user “preference,” not an explicit “mode” or
           35 strictly-enforced “setting.” It’s also not a “theme” in the sense
           36 that it just swaps out some assets, but is a way for the OS to
           37 support a user expressing a preference, and apps to respond to that
           38 preference.&lt;/p&gt;
           39 &lt;/blockquote&gt;
           40 &lt;p&gt;Second, about the &lt;strong&gt;accessibility&lt;/strong&gt; implications:&lt;/p&gt;
           41 &lt;blockquote&gt;
           42 &lt;p&gt;Clearly there’s an accessibility and usability angle here. And as
           43 with other accessibility efforts, it’s important to not relegate a
           44 dark style preference to a buried “Universal Access” or
           45 “Accessibility” feature, as that makes it less discoverable, less
           46 tested, and less likely to be used by folks who could greatly
           47 benefit, but don’t consider themselves “disabled.”&lt;/p&gt;
           48 &lt;/blockquote&gt;
           49 &lt;h1&gt;Libadwaita and the rest of the ecosystem&lt;/h1&gt;
           50 &lt;p&gt;Read the &lt;a href="https://discourse.gnome.org/t/libadwaita-1-0-roadmap/7415"&gt;libadwaita
           51 roadmap&lt;/a&gt;;
           52 it is very short, but links to very interesting issues on gitlab.&lt;/p&gt;
           53 &lt;p&gt;For example, this merge request is for an &lt;a href="https://gitlab.gnome.org/GNOME/libadwaita/-/merge_requests/224"&gt;API to query the dark style
           54 and high-contrast
           55 preferences&lt;/a&gt;.
           56 It has links to pending work in other parts of the platform: libhandy,
           57 gsettings schemas, portals so that containerized applications can
           58 query those preferences.&lt;/p&gt;
           59 &lt;p&gt;As far as I understand it, applications that just use GTK3 or libhandy
           60 can opt in to supporting the dark style preference — it is opt-in
           61 because doing that unconditionally in GTK/libhandy right now would
           62 break existing applications..  If your app uses libadwaita, it is
           63 assumed that you have opted into supporting that preference, since
           64 libadwaita's widgets already make that assumption, and it is not
           65 API-stable yet — so it can make that assumption from the beginning.&lt;/p&gt;
           66 &lt;p&gt;There is discussion of the accessibility implications in &lt;a href="https://gitlab.gnome.org/Teams/Design/settings-mockups/-/issues/27#note_1257700"&gt;the design
           67 mockups&lt;/a&gt;.&lt;/p&gt;
           68 &lt;h1&gt;CSS parity across implementations&lt;/h1&gt;
           69 &lt;p&gt;In GNOME we have three implementations of CSS:&lt;/p&gt;
           70 &lt;ul&gt;
           71 &lt;li&gt;
           72 &lt;p&gt;librsvg uses servo's engine for CSS selector matching, and micro-parsers for CSS values based on servo's cssparser.&lt;/p&gt;
           73 &lt;/li&gt;
           74 &lt;li&gt;
           75 &lt;p&gt;GTK has its own CSS parser and processor.&lt;/p&gt;
           76 &lt;/li&gt;
           77 &lt;li&gt;
           78 &lt;p&gt;Gnome-shell uses an embedded version of libcroco for parsing, but it
           79   does most of the selector matching and cascading with gnome-shell's
           80   own Shell Toolkit code.&lt;/p&gt;
           81 &lt;/li&gt;
           82 &lt;/ul&gt;
           83 &lt;p&gt;None of those implementations supports &lt;code&gt;@media&lt;/code&gt; queries nor custom
           84 properties with &lt;code&gt;var()&lt;/code&gt;.  That is, unlike in the web platform, GNOME
           85 applications cannot have this in their CSS:&lt;/p&gt;
           86 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;media&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;dark&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           87   &lt;span class="c"&gt;/* styles for dark style */&lt;/span&gt;
           88 &lt;span class="p"&gt;}&lt;/span&gt;
           89 
           90 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;media&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;light&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           91   &lt;span class="c"&gt;/* styles for light style */&lt;/span&gt;
           92 &lt;span class="p"&gt;}&lt;/span&gt;
           93 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
           94 
           95 &lt;p&gt;Or even declaring colors in a civilized fashion:&lt;/p&gt;
           96 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           97   &lt;span class="nv"&gt;--main-bg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;pink&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
           98 &lt;span class="p"&gt;}&lt;/span&gt;
           99 
          100 &lt;span class="nt"&gt;some_widget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          101   &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;--main-bg-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          102 &lt;span class="p"&gt;}&lt;/span&gt;
          103 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
          104 
          105 &lt;p&gt;Or combining the two:&lt;/p&gt;
          106 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;media&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;dark&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          107   &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          108     &lt;span class="nv"&gt;--main-bg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c"&gt;/* some nice dark background color */&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          109     &lt;span class="nv"&gt;--main-fg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c"&gt;/* a contrasty light foreground */&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          110   &lt;span class="p"&gt;}&lt;/span&gt;
          111 &lt;span class="p"&gt;}&lt;/span&gt;
          112 
          113 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;media&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;light&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          114   &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          115     &lt;span class="nv"&gt;--main-bg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c"&gt;/* some nice light background color */&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          116     &lt;span class="nv"&gt;--main-fg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c"&gt;/* a contrasty dark foreground */&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          117   &lt;span class="p"&gt;}&lt;/span&gt;
          118 &lt;span class="p"&gt;}&lt;/span&gt;
          119 
          120 &lt;span class="nt"&gt;some_widget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          121   &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;--main-bg-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          122 &lt;span class="p"&gt;}&lt;/span&gt;
          123 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
          124 
          125 &lt;p&gt;Boom.  I think this would remove some workarounds we have right now:&lt;/p&gt;
          126 &lt;ul&gt;
          127 &lt;li&gt;
          128 &lt;p&gt;Just like GTK, libadwaita generates four variants of the system's
          129   stylesheet using scss (regular, dark, high-contrast,
          130   high-contrast-dark).  This would be obviated with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media"&gt;&lt;code&gt;@media&lt;/code&gt;
          131   queries&lt;/a&gt;
          132   for &lt;code&gt;prefers-color-scheme&lt;/code&gt;, &lt;code&gt;prefers-contrast&lt;/code&gt;, &lt;code&gt;inverted-colors&lt;/code&gt; as
          133   in the web platform.&lt;/p&gt;
          134 &lt;/li&gt;
          135 &lt;li&gt;
          136 &lt;p&gt;GTK has a custom &lt;code&gt;@define-color&lt;/code&gt; keyword, but neither gnome-shell
          137   nor librsvg support that.  This would be obviated with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/--*"&gt;CSS custom
          138   properties&lt;/a&gt; -
          139   the &lt;code&gt;var()&lt;/code&gt; mechanism.  (I don't know if some "environmental" stuff
          140   would be better done as
          141   &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/env()"&gt;&lt;code&gt;env()&lt;/code&gt;&lt;/a&gt;,
          142   but none of the three implementations support that, either.)&lt;/p&gt;
          143 &lt;/li&gt;
          144 &lt;/ul&gt;
          145 &lt;h1&gt;Accent colors&lt;/h1&gt;
          146 &lt;p&gt;They are currently implemented with GTK's &lt;code&gt;@define-color&lt;/code&gt;, which is
          147 not ideal if the colors have to trickle down from GTK to SVG icons,
          148 since librsvg doesn't do &lt;code&gt;@define-color&lt;/code&gt; - it would rather have
          149 &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/459"&gt;&lt;code&gt;var()&lt;/code&gt;
          150 instead&lt;/a&gt;.&lt;/p&gt;
          151 &lt;p&gt;Of course, gnome-shell's libcroco doesn't do &lt;code&gt;@define-color&lt;/code&gt; either.&lt;/p&gt;
          152 &lt;p&gt;Look for &lt;code&gt;@accent_color&lt;/code&gt;, &lt;code&gt;@accent_bg_color&lt;/code&gt;, &lt;code&gt;@warning_color&lt;/code&gt;, etc. in the &lt;a href="https://gitlab.gnome.org/GNOME/libadwaita/-/blob/main/src/stylesheet/_defaults.scss"&gt;default
          153 stylesheet&lt;/a&gt;,
          154 or better yet, &lt;strong&gt;write documentation!&lt;/strong&gt;&lt;/p&gt;
          155 &lt;p&gt;The default style:&lt;/p&gt;
          156 &lt;p&gt;&lt;img alt="Default blue style" src="https://people.gnome.org/~federico/blog/images/adwaita-default.png"&gt;&lt;/p&gt;
          157 &lt;p&gt;Accent color set to orange (e.g. tweak it in GTK's CSS inspector):&lt;/p&gt;
          158 &lt;p&gt;&lt;img alt="Orange accents for widgets" src="https://people.gnome.org/~federico/blog/images/adwaita-accent-orange.png"&gt;&lt;/p&gt;
          159 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c"&gt;/* Standalone, e.g. the &amp;quot;Page 1&amp;quot; label */&lt;/span&gt;
          160 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;define-color&lt;/span&gt; &lt;span class="nt"&gt;accent_color&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;orange_5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          161 
          162 &lt;span class="c"&gt;/* background+text pair */&lt;/span&gt;
          163 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;define-color&lt;/span&gt; &lt;span class="nt"&gt;accent_bg_color&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;orange_4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          164 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;define-color&lt;/span&gt; &lt;span class="nt"&gt;accent_fg_color&lt;/span&gt; &lt;span class="nt"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          165 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
          166 
          167 &lt;h1&gt;Custom widgets&lt;/h1&gt;
          168 &lt;p&gt;Again, your app's custom stylesheet for its custom widgets can use the
          169 colors defined through &lt;code&gt;@define-color&lt;/code&gt; from the system's stylesheet.&lt;/p&gt;
          170 &lt;h1&gt;Recoloring styles&lt;/h1&gt;
          171 &lt;p&gt;You will be able to do this after it gets merged into the main branch,
          172 e.g. recolor everything to sepia:&lt;/p&gt;
          173 &lt;p&gt;&lt;img alt="Adwaita recolored to sepia" src="https://people.gnome.org/~federico/blog/images/adwaita-recolored.png"&gt;&lt;/p&gt;
          174 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;define-color&lt;/span&gt; &lt;span class="nt"&gt;headerbar_bg_color&lt;/span&gt; &lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="nn"&gt;eedcbf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          175 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;define-color&lt;/span&gt; &lt;span class="nt"&gt;headerbar_fg_color&lt;/span&gt; &lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="nn"&gt;483a22&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          176 
          177 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;define-color&lt;/span&gt; &lt;span class="nt"&gt;bg_color&lt;/span&gt; &lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="nn"&gt;f9f3e9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          178 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;define-color&lt;/span&gt; &lt;span class="nt"&gt;fg_color&lt;/span&gt; &lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="nn"&gt;483a22&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          179 
          180 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;define-color&lt;/span&gt; &lt;span class="nt"&gt;dark_fill_color&lt;/span&gt; &lt;span class="nt"&gt;shade&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="nn"&gt;f9f3e9&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;95&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          181 
          182 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;define-color&lt;/span&gt; &lt;span class="nt"&gt;accent_bg_color&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;orange_4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          183 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;define-color&lt;/span&gt; &lt;span class="nt"&gt;accent_color&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;orange_5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          184 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
          185 
          186 &lt;p&gt;Of course &lt;code&gt;shade()&lt;/code&gt; is not web-platform CSS, either.  We could keep
          187 it, or redo it by implementing &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/calc()"&gt;&lt;code&gt;calc()&lt;/code&gt;
          188 function&lt;/a&gt; for
          189 color values.&lt;/p&gt;
          190 &lt;h1&gt;Recoloring icons&lt;/h1&gt;
          191 &lt;p&gt;Currently GTK takes some defined colors and &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/539#note_669487"&gt;creates a chunk of CSS to
          192 inject into SVG for
          193 icons&lt;/a&gt;.
          194 This has &lt;a href="https://gitlab.gnome.org/GNOME/gtk/-/issues/2314"&gt;some
          195 problems&lt;/a&gt;.&lt;/p&gt;
          196 &lt;p&gt;There is also some discussion about &lt;a href="https://gitlab.gnome.org/GNOME/gtk/-/issues/1762"&gt;standardizing recolorable
          197 icons&lt;/a&gt; across
          198 desktop environments.&lt;/p&gt;
          199 &lt;h1&gt;How you can help&lt;/h1&gt;
          200 &lt;p&gt;Implement support for &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries"&gt;&lt;code&gt;@media&lt;/code&gt;
          201 queries&lt;/a&gt;
          202 in our three CSS implementations (librsvg, gnome-shell, GTK).  Decide
          203 how CSS media features like &lt;code&gt;prefers-color-scheme&lt;/code&gt;,
          204 &lt;code&gt;prefers-contrast&lt;/code&gt;, &lt;code&gt;inverted-colors&lt;/code&gt; should interact with the GNOME's
          205 themes and accessibility, and decide if we should use them for
          206 familiarity with the web platform, or if we need media features with
          207 different names.&lt;/p&gt;
          208 &lt;p&gt;Implement support for &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties"&gt;CSS custom properties -
          209 &lt;code&gt;var()&lt;/code&gt;&lt;/a&gt;
          210 in our three CSS implementations.  Decide if we should replace the
          211 current &lt;code&gt;@define-color&lt;/code&gt; with that (note that &lt;code&gt;@define-color&lt;/code&gt; is only
          212 in GTK, but not in librsvg or gnome-shell).&lt;/p&gt;
          213 &lt;p&gt;See the &lt;a href="https://discourse.gnome.org/t/libadwaita-1-0-roadmap/7415"&gt;libadwaita
          214 roadmap&lt;/a&gt;
          215 and help out!&lt;/p&gt;
          216 &lt;p&gt;Port applications to use the proposed APIs for querying the dark style
          217 preference.  There are a bunch of hacky ways of doing it right now;
          218 they need to be migrated to the new system.&lt;/p&gt;
          219 &lt;p&gt;Personally I would love help with finishing to &lt;a href="https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1355"&gt;port gnome-shell's
          220 styles to
          221 Rust&lt;/a&gt; -
          222 this is part of unifying librsvg's and gnome-shell's CSS machinery.&lt;/p&gt;</content><category term="misc"></category><category term="gnome"></category></entry><entry><title>Bzip2's experimental repository is changing maintainership</title><link href="https://people.gnome.org/~federico/blog/bzip2-changing-maintainership.html" rel="alternate"></link><published>2021-06-03T19:21:04-05:00</published><updated>2021-06-03T19:21:04-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2021-06-03:/~federico/blog/bzip2-changing-maintainership.html</id><summary type="html">&lt;p&gt;Bzip2's stable repository is maintained &lt;a href="https://sourceware.org/git/?p=bzip2.git;a=summary"&gt;at Sourceware&lt;/a&gt; by
          223 Mark Wielaard.  In 2019 I started maintaining an &lt;a href="https://gitlab.com/bzip2/bzip2/"&gt;experimental
          224 repository in GitLab&lt;/a&gt;, with the intention of updating
          225 the build system and starting a Rust port of bzip2.  Unfortunately I
          226 have left this project slip by.&lt;/p&gt;
          227 &lt;p&gt;The new maintainer of the &lt;a href="https://gitlab.com/bzip2/bzip2/"&gt;experimental repository …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;Bzip2's stable repository is maintained &lt;a href="https://sourceware.org/git/?p=bzip2.git;a=summary"&gt;at Sourceware&lt;/a&gt; by
          228 Mark Wielaard.  In 2019 I started maintaining an &lt;a href="https://gitlab.com/bzip2/bzip2/"&gt;experimental
          229 repository in GitLab&lt;/a&gt;, with the intention of updating
          230 the build system and starting a Rust port of bzip2.  Unfortunately I
          231 have left this project slip by.&lt;/p&gt;
          232 &lt;p&gt;The new maintainer of the &lt;a href="https://gitlab.com/bzip2/bzip2/"&gt;experimental repository&lt;/a&gt; for
          233 Bzip2 is Micah Snyder.  Thanks, Micah, for picking it up!&lt;/p&gt;</content><category term="misc"></category><category term="bzip2"></category><category term="rust"></category></entry><entry><title>Librsvg, Rust, and non-mainstream architectures</title><link href="https://people.gnome.org/~federico/blog/librsvg-rust-and-non-mainstream-architectures.html" rel="alternate"></link><published>2021-02-24T19:14:55-06:00</published><updated>2021-02-24T19:14:55-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2021-02-24:/~federico/blog/librsvg-rust-and-non-mainstream-architectures.html</id><summary type="html">&lt;p&gt;Almost five years ago &lt;a href="https://people.gnome.org/~federico/news-2016-10.html#25"&gt;librsvg introduced Rust into its source
          234 code&lt;/a&gt;.  Around the same time, Linux distributions
          235 started shipping the first versions of Firefox that also required
          236 Rust.  I unashamedly wanted to ride that wave: distros would &lt;em&gt;have&lt;/em&gt; to
          237 integrate a new language in their build infrastructure, or they would …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Almost five years ago &lt;a href="https://people.gnome.org/~federico/news-2016-10.html#25"&gt;librsvg introduced Rust into its source
          238 code&lt;/a&gt;.  Around the same time, Linux distributions
          239 started shipping the first versions of Firefox that also required
          240 Rust.  I unashamedly wanted to ride that wave: distros would &lt;em&gt;have&lt;/em&gt; to
          241 integrate a new language in their build infrastructure, or they would
          242 be left without Firefox.  I was hoping that having a working Rust
          243 toolchain would make it easier for the rustified librsvg to get into
          244 distros.&lt;/p&gt;
          245 &lt;p&gt;Two years after that, &lt;a href="https://lwn.net/Articles/771355/"&gt;someone from Debian complained&lt;/a&gt;
          246 that this made it hard or impossible to build librsvg (and all the
          247 software that depends on it, which is A Lot) on all the architectures
          248 that Debian builds on — specifically, on things like HP PA-RISC or
          249 Alpha, which &lt;a href="https://www.debian.org/ports/"&gt;even Debian marks as "discontinued" now&lt;/a&gt;.&lt;/p&gt;
          250 &lt;p&gt;Recently there was a similar kerfuffle, this time from &lt;a href="https://lwn.net/Articles/845535/"&gt;someone from
          251 Gentoo&lt;/a&gt;, specifically about how Python's cryptography
          252 package now requires Rust.  So, it doesn't build for platforms that
          253 Rust/LLVM don't support, like hppa, alpha, and Itanium.  It also
          254 doesn't build for platforms for which there are no Rust packages from
          255 Gentoo yet (mips, s390x, riscv among them).&lt;/p&gt;
          256 &lt;h2&gt;Memories of discontinued architectures&lt;/h2&gt;
          257 &lt;p&gt;Let me reminisce about a couple of discontinued architectures.  If I'm
          258 reading &lt;a href="https://en.wikipedia.org/wiki/DEC_Alpha"&gt;Wikipedia&lt;/a&gt; correctly, the DEC Alpha ceased to be
          259 developed in 2001, and HP, who purchased Compaq, who purchased DEC,
          260 stopped selling Alpha systems in 2007.  Notably, Compaq phased out the
          261 Alpha in favor of the Itanium, which stopped being developed in 2017.&lt;/p&gt;
          262 &lt;p&gt;I &lt;em&gt;used&lt;/em&gt; an Alpha machine in 1997-1998, back at the University.
          263 &lt;a href="https://twitter.com/migueldeicaza/"&gt;Miguel&lt;/a&gt; kindly let me program and learn from him at the Institute
          264 where he worked, and the computer lab there got an Alpha box to let
          265 the scientists run mathematical models on a machine with really fast
          266 floating-point.  This was a time when people actually regularly ssh'ed
          267 into machines to run X11 applications remotely — in their case, I
          268 think it was Matlab and Mathematica.  Good times.&lt;/p&gt;
          269 &lt;p&gt;The Alpha had fast floating point, much faster than Intel x86 CPUs,
          270 and I was delighted to do graphics work on it.  That was the first
          271 64-bit machine I used, and it let me learn how to fix code that only
          272 assumed 32 bits.  It had a really picky floating-point unit.  Whereas
          273 x86 would happily throw you a NaN if you used uninitialized memory as
          274 floats, the Alpha would properly fault and crash the program.  I fixed
          275 so many bugs thanks to that!&lt;/p&gt;
          276 &lt;p&gt;I also have fond memories of the 32-bit SPARC
          277 boxes at the University and their flat-screen fixed-frequency CRT
          278 displays, but you know, I haven't &lt;em&gt;seen&lt;/em&gt; one of those machines since
          279 1998.  Because I was doing graphics work, I used the single SPARC
          280 machine in the computer lab at the Institute that had 24-bit graphics,
          281 with a humongous 21" CRT display.  PCs at the time still had 8-bit video
          282 cards and shitty little monitors.&lt;/p&gt;
          283 &lt;p&gt;At about the same time that the Institute got its Alpha, it also got
          284 one of the first 64-bit UltraSPARCs from Sun — a very expensive
          285 machine definitely not targeted to hobbyists.  I think it had two CPUs!
          286 Multicore did not exist!&lt;/p&gt;
          287 &lt;p&gt;I think I saw a single Itanium machine in my life, probably around
          288 2002-2005.  The Ximian/Novell office in Mexico City got one, for QA
          289 purposes — an incredibly loud and unstable machine.  I don't think we
          290 ever did any actual development on that box; it was a "can you
          291 reproduce this bug there" kind of thing.  I think Ximian/Novell had a
          292 contract with HP to test the distro there, I don't remember.&lt;/p&gt;
          293 &lt;h2&gt;Unsupported architectures at the LLVM level&lt;/h2&gt;
          294 &lt;p&gt;Platforms like the Alpha and Itanium that Rust/LLVM don't support —
          295 those platforms are dead in the water.  The compiler cannot target
          296 them, as Rust generates machine code via LLVM, and LLVM doesn't
          297 support them.&lt;/p&gt;
          298 &lt;p&gt;I don't know why distributions maintained by volunteers give
          299 themselves the responsibility to keep their software running on
          300 platforms that have not been manufactured for years, and that were
          301 never even hobbyist machines.&lt;/p&gt;
          302 &lt;p&gt;I read the other day, and now I regret not keeping the link, something
          303 like this: don't assume that your hobby computing entitles you to free
          304 labor on the part of compiler writers, software maintainers, and
          305 distro volunteers.  (If someone helps me find the source, I'll happily
          306 link to it and quote it properly.)&lt;/p&gt;
          307 &lt;h2&gt;Non-tier-1 platforms and "$distro does not build Rust there yet"&lt;/h2&gt;
          308 &lt;p&gt;I think people are discovering these once again:&lt;/p&gt;
          309 &lt;ul&gt;
          310 &lt;li&gt;
          311 &lt;p&gt;Writing and supporting a compiler for a certain architecture takes Real Work.&lt;/p&gt;
          312 &lt;/li&gt;
          313 &lt;li&gt;
          314 &lt;p&gt;Supporting a distro for a certain architecture takes Real Work.&lt;/p&gt;
          315 &lt;/li&gt;
          316 &lt;li&gt;
          317 &lt;p&gt;Fixing software to work on a certain architecture takes Real Work.&lt;/p&gt;
          318 &lt;/li&gt;
          319 &lt;/ul&gt;
          320 &lt;p&gt;Rust divides its support for different platforms into &lt;a href="https://doc.rust-lang.org/nightly/rustc/platform-support.html"&gt;tiers&lt;/a&gt;, going
          321 from tier 1, the most supported, to tier 3, the least supported.  Or,
          322 I should say, &lt;em&gt;taken care of&lt;/em&gt;, which is a combination of people who
          323 actually have the hardware in question, and whether the general CI and
          324 build tooling is prepared to deal with them as effectively as it does
          325 for tier 1 platforms.&lt;/p&gt;
          326 &lt;p&gt;In other words: there are more people capable of paying attention to, and
          327 testing things on, x86_64 PCs than there are for
          328 &lt;code&gt;sparc-unknown-linux-gnu&lt;/code&gt;.&lt;/p&gt;
          329 &lt;h2&gt;Some anecdotes from Suse&lt;/h2&gt;
          330 &lt;p&gt;At Suse we actually support IBM's s390x big iron; those mainframes run
          331 Suse Linux Enterprise Server.  You have to pay a lot of money to get a
          332 machine like that and support for it.  It's a room-sized beast that
          333 requires professional babysitting.&lt;/p&gt;
          334 &lt;p&gt;When librsvg and Firefox started getting rustified, there was of
          335 course concern about getting Rust to work properly on the s390x.
          336 I worked sporadically with the people who made the distro work there,
          337 and who had to deal with building Rust and Firefox on it (librsvg
          338 was a non-issue after getting Rust and Firefox to work).&lt;/p&gt;
          339 &lt;p&gt;I think all the LLVM work for the s390x was done at IBM.  There were
          340 probably a couple of miscompilations that affected Firefox; they got fixed.&lt;/p&gt;
          341 &lt;p&gt;One would expect bugs in software for IBM mainframes to be fixed by
          342 IBM or its contractors, not by volunteers maintaining a distro in
          343 their spare time.&lt;/p&gt;
          344 &lt;p&gt;Giving computing time on mainframes to volunteers in distros could seem
          345 like a good samaritan move, or a trap to extract free labor from
          346 unsuspecting people.&lt;/p&gt;
          347 &lt;h3&gt;Endianness bugs&lt;/h3&gt;
          348 &lt;p&gt;Firefox's problems on the s390x were more around big-endian bugs than
          349 anything.  You see, all the common architectures these days (x86_64
          350 and arm64) are little-endian.  However, s390x is &lt;a href="https://en.wikipedia.org/wiki/Endianness"&gt;big-endian&lt;/a&gt;,
          351 which means that all multi-byte numbers in memory are stored backwards
          352 from what most software expects.&lt;/p&gt;
          353 &lt;p&gt;It is not a problem to write software that assumes little-endian or
          354 big-endian all the time, but it takes a little care to write software
          355 that works on either.&lt;/p&gt;
          356 &lt;p&gt;Most of the software that volunteers and paid people write assumes
          357 little-endian CPUs, because that is likely what they are targeting.
          358 It is a pain in the ass to encounter code that works incorrectly on
          359 big-endian — a pain because &lt;em&gt;knowing where to look&lt;/em&gt; for evidence of
          360 bugs is tricky, and &lt;em&gt;fixing existing code&lt;/em&gt; to work with either
          361 endianness can be either very simple, or a major adventure in
          362 refactoring and testing.&lt;/p&gt;
          363 &lt;p&gt;Two cases in point:&lt;/p&gt;
          364 &lt;p&gt;&lt;strong&gt;Firefox.&lt;/strong&gt;  When Suse started dealing with Rust and Firefox in the
          365 s390x, there were endianness bugs in the graphics code in Firefox that
          366 deals with pixel formats.  Whether pixels get stored in memory as
          367 ARGB/ABGR/RGBA/etc. is a platform-specific thing, and is generally a
          368 combination of the graphics hardware for that platform, plus the
          369 actual CPU architecture.  At that time, it looked like the C++ code in
          370 Firefox that deals with pixels had been rewritten/refactored, and had
          371 lost big-endian support along the way.  I don't know the current
          372 status (not a single big-endian CPU in my vincinity), but I haven't
          373 seen related bugs come in the Suse bug tracker?  Maybe it's fixed now?&lt;/p&gt;
          374 &lt;p&gt;&lt;strong&gt;Librsvg&lt;/strong&gt; had &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues?scope=all&amp;amp;utf8=%E2%9C%93&amp;amp;state=closed&amp;amp;search=s390"&gt;two root causes of bugs for
          375 big-endian&lt;/a&gt;.  One was in the old code for SVG
          376 filter effects that was written in C; &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/195"&gt;it never supported big-endian&lt;/a&gt;.  The
          377 initial port to Rust inherited the same bug (think of a line-by-line
          378 port, althought it wasn't exactly like that), but it got fixed when my
          379 Summer of Code intern Ivan Molodetskikh refactored the code to have a
          380 &lt;code&gt;Pixel&lt;/code&gt; abstraction that works for little-endian and big-endian, and
          381 wraps Cairo's funky requirements.&lt;/p&gt;
          382 &lt;p&gt;The other endian-related bug in librsvg was when &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/328"&gt;computing
          383 masks&lt;/a&gt;.  Again, a little refactoring with that &lt;code&gt;Pixel&lt;/code&gt;
          384 abstraction fixed it.&lt;/p&gt;
          385 &lt;p&gt;I knew that the original C code for SVG filter effects didn't work on
          386 big-endian.  But even back then, at Suse we never got
          387 reports of it producing incorrect results on the s390x... maybe people don't use
          388 their mainframes to run &lt;code&gt;rsvg-convert&lt;/code&gt;?  I was hoping that the port to
          389 Rust of that code would automatically fix that bug, and it kind of
          390 happened that way through Ivan's careful work.&lt;/p&gt;
          391 &lt;p&gt;And the code for masks?  There were two bugs reported with that same
          392 root cause: &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/328"&gt;one from
          393 Debian&lt;/a&gt; as a
          394 failure in librsvg's test suite (yay, it caught that bug!), and one
          395 from &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/322"&gt;someone running an Apple PowerBook
          396 G4&lt;/a&gt; with a MATE
          397 desktop and seeing incorrectly-rendered SVG icons.&lt;/p&gt;
          398 &lt;p&gt;And you know what?  I am &lt;strong&gt;delighted&lt;/strong&gt; to see people trying to keep
          399 those lovely machines alive.  A laptop that doesn't get warm enough to
          400 burn your thighs, what a concept.  A perfectly serviceable 32-bit
          401 laptop with a maximum of about 1 GB of RAM and a 40 GB hard drive (it
          402 didn't have HDMI!)...  But you know, it's the same kind of delight I
          403 feel when people talk about doing film photography on a
          404 &lt;a href="https://en.wikipedia.org/wiki/Rollei_35"&gt;Rollei 35&lt;/a&gt;.  A lot of
          405 nostalgia for hardware of days past, and a lot of mixed feelings about
          406 not throwing out working things and creating more trash.&lt;/p&gt;
          407 &lt;p&gt;As a graphics programmer I feel the responsibility to write code that
          408 works on little-endian and big-endian, but you know, it's not exactly
          409 an everyday concern anymore.  The last big-endian machine I used on an
          410 everyday basis was the SPARCs in the university, more than 20 years
          411 ago.&lt;/p&gt;
          412 &lt;h3&gt;Who gets paid to fix this?&lt;/h3&gt;
          413 &lt;p&gt;That's the question.  Suse got paid to support Firefox on the s390x; I
          414 suppose IBM has an interest in fixing LLVM there; both actually have
          415 people and hardware and money to that effect.&lt;/p&gt;
          416 &lt;p&gt;Within Suse, I am by default responsible for keeping librsvg
          417 working for the s390x as well — it gets built as part of the distro,
          418 after all.  I have never gotten an endianness bug report from the Suse
          419 side of things.&lt;/p&gt;
          420 &lt;p&gt;Which leads me to suspect that, probably similar to Debian and Gentoo,
          421 we &lt;em&gt;build&lt;/em&gt; a lot of software because it's in the build chain, but we
          422 don't &lt;em&gt;run&lt;/em&gt; it to its fullest extent.  Do people run GNOME desktops on
          423 s390x virtual machines?  Maybe?  Did they not notice endianness bugs
          424 &lt;strong&gt;because they were not in the code path that most GNOME icons
          425 actually use&lt;/strong&gt;?  Who knows!&lt;/p&gt;
          426 &lt;p&gt;I'm thankful to Simon from the Debian bug for pointing out
          427 the failure in librsvg's test case for masks, and to Mingcong for
          428 actually showing a screenshot of a MATE desktop running on a PPC
          429 PowerBook.  Those were useful things for them to do.&lt;/p&gt;
          430 &lt;p&gt;Also — they were kind about it.  It was a pleasure to interact with them.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category></entry><entry><title>Do not use librsvg 2.40.x</title><link href="https://people.gnome.org/~federico/blog/do-not-use-librsvg-2.40.x.html" rel="alternate"></link><published>2020-11-27T10:28:46-06:00</published><updated>2020-11-27T10:28:46-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-11-27:/~federico/blog/do-not-use-librsvg-2.40.x.html</id><summary type="html">&lt;p&gt;Please do not use librsvg 2.40.x; &lt;strong&gt;it cannot render recent Adwaita icon themes correctly&lt;/strong&gt;.&lt;/p&gt;
          431 &lt;p&gt;The librsvg 2.40.x series is the last "C only" version of the library;
          432 it was deprecated in 2017.&lt;/p&gt;
          433 &lt;p&gt;During the port to Rust, I rewrote the path parser to be
          434 spec-compliant, and …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Please do not use librsvg 2.40.x; &lt;strong&gt;it cannot render recent Adwaita icon themes correctly&lt;/strong&gt;.&lt;/p&gt;
          435 &lt;p&gt;The librsvg 2.40.x series is the last "C only" version of the library;
          436 it was deprecated in 2017.&lt;/p&gt;
          437 &lt;p&gt;During the port to Rust, I rewrote the path parser to be
          438 spec-compliant, and fixed a few cases that the C version did not
          439 handle.  One of this cases is for compact Arc data.&lt;/p&gt;
          440 &lt;p&gt;The &lt;a href="https://www.w3.org/TR/SVG11/paths.html#PathDataBNF"&gt;SVG path grammar&lt;/a&gt; allows
          441 one to remove whitespace between numbers if the next number starts
          442 with a sign.  For example, &lt;code&gt;23-45&lt;/code&gt; gets parsed as two numbers &lt;code&gt;23
          443 -45&lt;/code&gt;.&lt;/p&gt;
          444 &lt;p&gt;In addition, the arguments of the Arc commands have two flags in the
          445 middle of a bunch of numbers.  The flags can be &lt;code&gt;0&lt;/code&gt; or &lt;code&gt;1&lt;/code&gt;, and there
          446 may be no whitespace between the flags and the next number. For
          447 example, &lt;code&gt;A1.98 1.98 0 0015 13.96&lt;/code&gt; gets parsed as &lt;code&gt;A1.98 1.98 0 0 0 15
          448 13.96&lt;/code&gt; — note the two &lt;code&gt;0 0&lt;/code&gt; flags before the &lt;code&gt;15&lt;/code&gt;.&lt;/p&gt;
          449 &lt;p&gt;Librsvg 2.40.x does not parse this correctly.
          450 Adwaita-icon-theme-3.36, and possibly earlier versions, uses minimized
          451 SVG files with compressed whitespace, and will not render correctly
          452 with the C-only version of librsvg.&lt;/p&gt;
          453 &lt;p&gt;This is &lt;code&gt;help-contents-symbolic.svg&lt;/code&gt; rendered with librsvg 2.40.21:&lt;/p&gt;
          454 &lt;p&gt;&lt;img alt="icon rendered incorrectly" src="https://people.gnome.org/~federico/blog/images/help-contents-symbolic-2.40.21.png"&gt;&lt;/p&gt;
          455 &lt;p&gt;And this is &lt;code&gt;help-contents-symbolic.svg&lt;/code&gt; rendered with librsvg 2.50.2:&lt;/p&gt;
          456 &lt;p&gt;&lt;img alt="icon rendered correctly" src="https://people.gnome.org/~federico/blog/images/help-contents-symbolic-2.50.2.png"&gt;&lt;/p&gt;
          457 &lt;p&gt;This is not the only icon with compact Arc commands; there are many
          458 others that will also be mis-rendered in 2.40.x.&lt;/p&gt;
          459 &lt;p&gt;I don't know when Adwaita started using SVGs with compressed
          460 whitespace; probably it didn't when librsvg 2.40.x was the latest
          461 version, or everyone would have noticed mis-rendered icons.&lt;/p&gt;
          462 &lt;p&gt;&lt;strong&gt;Background:&lt;/strong&gt; Someone recently filed a
          463 &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/654"&gt;bug&lt;/a&gt; about
          464 memory unsafety in librsvg 2.40.x's path parser, which mysteriously
          465 enough only manifests itself in big-endian platforms.  I wouldn't be
          466 surprised if this had latent bugs on little-endian as well.&lt;/p&gt;
          467 &lt;p&gt;Please use at least librsvg 2.48.x; any earlier versions are not
          468 supported.  Generally I keep an eye on the last two stable release
          469 sets (2.48.x and 2.50.x as of this writing), but only commit fixes to
          470 the latest stable series (2.50.x currently).&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category></entry><entry><title>Librsvg's test suite is now in Rust</title><link href="https://people.gnome.org/~federico/blog/librsvg-test-suite-is-now-in-rust.html" rel="alternate"></link><published>2020-10-26T10:38:12-06:00</published><updated>2020-10-26T10:38:12-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-10-26:/~federico/blog/librsvg-test-suite-is-now-in-rust.html</id><summary type="html">&lt;p&gt;Some important changes are afoot in librsvg.&lt;/p&gt;
          471 &lt;h2&gt;Changes to continuous integration&lt;/h2&gt;
          472 &lt;p&gt;Some days ago, &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/398"&gt;Dunja Lalic rewrote the continuous integration
          473 scripts&lt;/a&gt; to be much faster.  A complete pipeline used to take
          474 about 90 minutes to run, now it takes about 15 minutes on average.&lt;/p&gt;
          475 &lt;p&gt;&lt;img alt="Graph with pipeline timings, which shrink drastically" src="https://people.gnome.org/~federico/blog/images/librsvg-fast-ci.png" title="Guess when the CI changed"&gt;&lt;/p&gt;
          476 &lt;p&gt;The &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/398"&gt;description of changes&lt;/a&gt; is interesting …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Some important changes are afoot in librsvg.&lt;/p&gt;
          477 &lt;h2&gt;Changes to continuous integration&lt;/h2&gt;
          478 &lt;p&gt;Some days ago, &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/398"&gt;Dunja Lalic rewrote the continuous integration
          479 scripts&lt;/a&gt; to be much faster.  A complete pipeline used to take
          480 about 90 minutes to run, now it takes about 15 minutes on average.&lt;/p&gt;
          481 &lt;p&gt;&lt;img alt="Graph with pipeline timings, which shrink drastically" src="https://people.gnome.org/~federico/blog/images/librsvg-fast-ci.png" title="Guess when the CI changed"&gt;&lt;/p&gt;
          482 &lt;p&gt;The &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/398"&gt;description of changes&lt;/a&gt; is interesting.  The idea is to make tests fail as fast as possible, close to the beginning of the pipeline.  To speed up the whole pipeline, Dunja did the following:&lt;/p&gt;
          483 &lt;ul&gt;
          484 &lt;li&gt;
          485 &lt;p&gt;Move the &lt;code&gt;cargo check&lt;/code&gt; stage to the beginning.  This test means,
          486   "does this even have a chance of compiling?".&lt;/p&gt;
          487 &lt;/li&gt;
          488 &lt;li&gt;
          489 &lt;p&gt;Have the code style and formatting tests, &lt;code&gt;cargo clippy&lt;/code&gt; and &lt;code&gt;cargo
          490   fmt&lt;/code&gt;, run in parallel with the unit tests.  These lints can fail,
          491   but they are easy to fix after one is finished modifying the main
          492   code.&lt;/p&gt;
          493 &lt;/li&gt;
          494 &lt;li&gt;
          495 &lt;p&gt;Run the unit tests and the smoke tests in debug mode, so they compile
          496   quickly.&lt;/p&gt;
          497 &lt;/li&gt;
          498 &lt;li&gt;
          499 &lt;p&gt;Run the complete integration test suite in release mode.  This takes
          500   longer to compile, but there are some slow tests that benefit a lot
          501   from faster execution.&lt;/p&gt;
          502 &lt;/li&gt;
          503 &lt;li&gt;
          504 &lt;p&gt;Move the release tests until the end, and only run them once a week
          505   — or whenever, by hand.  These take a good amount of time to run,
          506   because they do a full &lt;code&gt;make distcheck&lt;/code&gt; and autotools is slow.  Even
          507   then, now these tests take 30-40 minutes, instead of the 90 from
          508   before.&lt;/p&gt;
          509 &lt;/li&gt;
          510 &lt;li&gt;
          511 &lt;p&gt;Between each stage of the pipeline, don't cache what doesn't help
          512   reduce compilation time.  It seems that keeping around a big cache,
          513   with the whole build &lt;code&gt;target&lt;/code&gt;, between each pipeline stage can be
          514   worse than not having one at all.&lt;/p&gt;
          515 &lt;/li&gt;
          516 &lt;/ul&gt;
          517 &lt;p&gt;&lt;img alt="Complete pipeline with all the stages" src="https://people.gnome.org/~federico/blog/images/librsvg-complete-pipeline.png"&gt;&lt;/p&gt;
          518 &lt;h2&gt;Test suite in Rust&lt;/h2&gt;
          519 &lt;p&gt;Beteen Sven Neumann, Dunja Lalic, and myself we have finally &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/408"&gt;ported
          520 the test suite to Rust&lt;/a&gt;: all of librsvg's tests are
          521 now in Rust, except for the C API tests.  We had to do a few things:&lt;/p&gt;
          522 &lt;ul&gt;
          523 &lt;li&gt;
          524 &lt;p&gt;Review the old tests and remove some obsolete ones.&lt;/p&gt;
          525 &lt;/li&gt;
          526 &lt;li&gt;
          527 &lt;p&gt;Port each of the test modules to Rust.  They are small, but each one
          528   has special little things — test for crashes in the XML loading
          529   code, test for crashes during rendering, test the library's security
          530   limits.&lt;/p&gt;
          531 &lt;/li&gt;
          532 &lt;li&gt;
          533 &lt;p&gt;Fix the small tests that come as part of the documentation.&lt;/p&gt;
          534 &lt;/li&gt;
          535 &lt;li&gt;
          536 &lt;p&gt;Untangle the reference tests and port them to Rust.&lt;/p&gt;
          537 &lt;/li&gt;
          538 &lt;li&gt;
          539 &lt;p&gt;Move little chunks of code around so the unit tests and integration
          540   tests can share utilities to compare images, compute file paths for
          541   test fixtures, etc.&lt;/p&gt;
          542 &lt;/li&gt;
          543 &lt;/ul&gt;
          544 &lt;p&gt;The most complicated thing to port was the reference tests.  These are
          545 the most important ones; each test loads an SVG document, renders it,
          546 and compares the result to a reference PNG image.  There are some
          547 complications in the tests; they have to create a special
          548 configuration for Fontconfig and Pango, so as to have reproducible
          549 font rendering.  The pango-rs bindings do not cover this part of
          550 Pango, so we had to do some things by hand.&lt;/p&gt;
          551 &lt;p&gt;Anyway, &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/tree/master/tests/src"&gt;the tests are now in Rust&lt;/a&gt;.  One nice thing is that
          552 now the tests run automatically in parallel, across all CPU cores, so
          553 we save on total testing time.&lt;/p&gt;
          554 &lt;h2&gt;What's next: cargo-c and publish to crates.io&lt;/h2&gt;
          555 &lt;p&gt;We want to be able to &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/635"&gt;publish librsvg in crates.io&lt;/a&gt; as a
          556 normal crate; this implies being able to compile, test, and publish
          557 entirely from Cargo.  The compilation and testing part is done.&lt;/p&gt;
          558 &lt;p&gt;Now, we have to reorganize the code so it can be published to
          559 crates.io.  Librsvg comes in three parts, &lt;code&gt;rsvg_internals&lt;/code&gt; with the
          560 implementation of the library, &lt;code&gt;librsvg&lt;/code&gt; with the traditional C API,
          561 and &lt;code&gt;librsvg_crate&lt;/code&gt; with the Rust API.  However, to publish the Rust
          562 API to crates.io, it would be more convenient to have a single crate
          563 instead of one with the internals and one with the API.&lt;/p&gt;
          564 &lt;p&gt;The next step is thus to reorganize the code:&lt;/p&gt;
          565 &lt;ul&gt;
          566 &lt;li&gt;
          567 &lt;p&gt;Make it possible to implement the C API as a compile-time option on
          568   top of the normal Rust code.  We want to &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/552"&gt;use cargo-c&lt;/a&gt; to
          569   compile the traditional shared library &lt;code&gt;librsvg.so&lt;/code&gt;, instead of
          570   depending on C tools for compiling and linking.&lt;/p&gt;
          571 &lt;/li&gt;
          572 &lt;li&gt;
          573 &lt;p&gt;Combine &lt;code&gt;rsvg_internals&lt;/code&gt; and &lt;code&gt;librsvg_crate&lt;/code&gt; in a single crate, to
          574   publish them together.  Crates.io has a 10 MB limit per crate; now
          575   that the test suite lives in a separate &lt;code&gt;tests&lt;/code&gt; crate, this
          576   shouldn't be a problem.&lt;/p&gt;
          577 &lt;/li&gt;
          578 &lt;li&gt;
          579 &lt;p&gt;I would like to &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/597"&gt;polish the public error types&lt;/a&gt; before
          580   publishing the Rust API; right now they expose some implementation
          581   details that are of no interest to callers of the library.&lt;/p&gt;
          582 &lt;/li&gt;
          583 &lt;/ul&gt;
          584 &lt;h2&gt;What remains to be ported to Rust?&lt;/h2&gt;
          585 &lt;p&gt;Only two things, which amount to less than 900 lines of C code:&lt;/p&gt;
          586 &lt;ul&gt;
          587 &lt;li&gt;
          588 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/534"&gt;rsvg-convert&lt;/a&gt; - the command-line program that everyone uses to
          589   convert SVG to PNG and other formats.  Fortunately, Sven Neumann
          590   wrote some &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/blob/master/tests/src/cmdline/rsvg_convert.rs"&gt;fantastic tests&lt;/a&gt; for rsvg-convert,
          591   as it is like an API that we need to keep stable: if we change the
          592   command-line options or the program's behavior, we would break
          593   everyone's scripts.&lt;/p&gt;
          594 &lt;/li&gt;
          595 &lt;li&gt;
          596 &lt;p&gt;The gdk-pixbuf module for loading SVG.  Alberto Ruiz &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/tree/wip/aruiz/rust-pixbuf-loader"&gt;has started
          597   porting it to Rust&lt;/a&gt;.  The generic part of this code
          598   could later serve to wrap other Rust image codecs and plug them to
          599   gdk-pixbuf.&lt;/p&gt;
          600 &lt;/li&gt;
          601 &lt;/ul&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category><category term="rust"></category></entry><entry><title>Librsvg is accepting interns for Outreachy's December 2020 round</title><link href="https://people.gnome.org/~federico/blog/librsvg-accepting-outreachy-interns-2020.html" rel="alternate"></link><published>2020-10-05T09:52:27-05:00</published><updated>2020-10-05T09:52:27-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-10-05:/~federico/blog/librsvg-accepting-outreachy-interns-2020.html</id><summary type="html">&lt;p&gt;There are two projects in librsvg available for &lt;a href="https://www.outreachy.org"&gt;Outreachy&lt;/a&gt; applicants
          602 in the December 2020 / March 2021 round:&lt;/p&gt;
          603 &lt;ul&gt;
          604 &lt;li&gt;
          605 &lt;p&gt;&lt;strong&gt;Revamp the text engine&lt;/strong&gt; - Do you know about international text
          606   layout?  Can you read a right-to-left language, or do you write in a
          607   language that requires complex shaping?  Would you like to implement …&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;There are two projects in librsvg available for &lt;a href="https://www.outreachy.org"&gt;Outreachy&lt;/a&gt; applicants
          608 in the December 2020 / March 2021 round:&lt;/p&gt;
          609 &lt;ul&gt;
          610 &lt;li&gt;
          611 &lt;p&gt;&lt;strong&gt;Revamp the text engine&lt;/strong&gt; - Do you know about international text
          612   layout?  Can you read a right-to-left language, or do you write in a
          613   language that requires complex shaping?  Would you like to implement
          614   the &lt;a href="https://www.w3.org/TR/SVG2/text.html"&gt;SVG 2 text specification&lt;/a&gt; in a &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/blob/master/rsvg_internals/src/text.rs"&gt;pleasant Rust code
          615   base&lt;/a&gt;?  This project requires someone who can write Rust
          616   comfortably; it will require reading and refactoring some
          617   existing code.  You don't need to be an expert in exotic lifetimes
          618   and trait bounds and such; the code doesn't use them.&lt;/p&gt;
          619 &lt;/li&gt;
          620 &lt;li&gt;
          621 &lt;p&gt;&lt;strong&gt;Implement SVG2/CSS3 features&lt;/strong&gt; - Are you excited by all the &lt;a href="https://www.w3.org/TR/SVG2/changes.html"&gt;SVG2
          622   features&lt;/a&gt; in Inkscape, and would like to add support for them
          623   in librsvg?  Would you like to do small changes to many parts of the
          624   code to implement small features, one at a time?  Do you like
          625   test-driven development?  This project requires someone who can
          626   write Rust code at a medium level; you'll learn a lot by
          627   cutting&amp;amp;pasting from existing code and refactoring things to
          628   implement SVG2 features.&lt;/p&gt;
          629 &lt;/li&gt;
          630 &lt;/ul&gt;
          631 &lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Outreachy's December 2020 / March 2021 round is available &lt;a href="https://www.outreachy.org/docs/applicant/#eligibility"&gt;only
          632 for students in the Southern hemisphere&lt;/a&gt;.  People in the
          633 Northern hemisphere can wait until the 2021 mid-year round.&lt;/p&gt;
          634 &lt;p&gt;You can see &lt;a href="https://www.outreachy.org/apply/project-selection/#gnome"&gt;GNOME's projects in Outreachy&lt;/a&gt; for this round.
          635 &lt;strong&gt;The deadline for initial contributions and project applications is
          636 October 31, 2020 at 16:00 UTC.&lt;/strong&gt;&lt;/p&gt;</content><category term="misc"></category><category term="mentoring"></category><category term="librsvg"></category></entry><entry><title>"Rust does not have a stable ABI"</title><link href="https://people.gnome.org/~federico/blog/rust-stable-abi.html" rel="alternate"></link><published>2020-08-12T22:01:44-05:00</published><updated>2020-08-12T22:01:44-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-08-12:/~federico/blog/rust-stable-abi.html</id><summary type="html">&lt;p&gt;I've seen GNOME people (often, people who have been working for a long
          637 time on C libraries) express concerns along the following lines:&lt;/p&gt;
          638 &lt;ol&gt;
          639 &lt;li&gt;Compiled Rust code doesn't have a stable ABI (application binary interface).&lt;/li&gt;
          640 &lt;li&gt;So, we can't have shared libraries in the traditional fashion of
          641    Linux distributions.&lt;/li&gt;
          642 &lt;li&gt;Also Rust bundles …&lt;/li&gt;&lt;/ol&gt;</summary><content type="html">&lt;p&gt;I've seen GNOME people (often, people who have been working for a long
          643 time on C libraries) express concerns along the following lines:&lt;/p&gt;
          644 &lt;ol&gt;
          645 &lt;li&gt;Compiled Rust code doesn't have a stable ABI (application binary interface).&lt;/li&gt;
          646 &lt;li&gt;So, we can't have shared libraries in the traditional fashion of
          647    Linux distributions.&lt;/li&gt;
          648 &lt;li&gt;Also Rust bundles its entire standard library with every binary it compiles, which makes Rust-built libraries huge.&lt;/li&gt;
          649 &lt;/ol&gt;
          650 &lt;p&gt;These are extremely valid concerns to be addressed by people like
          651 myself who propose that chunks of infrastructural libraries
          652 should be done in Rust.&lt;/p&gt;
          653 &lt;p&gt;So, let's begin.&lt;/p&gt;
          654 &lt;p&gt;The first part of this article is a super-quick introduction to shared
          655 libraries and how Linux distributions use them.  If you already know
          656 those things, feel free to skip to the "&lt;a href="#rust_does_not_have_a_stable_abi"&gt;Rust does not have a stable
          657 ABI&lt;/a&gt;" section.&lt;/p&gt;
          658 &lt;h2&gt;How do distributions use shared libraries?&lt;/h2&gt;
          659 &lt;p&gt;If several programs run at the same time and use the same shared library
          660 (say, &lt;code&gt;libgtk-3.so&lt;/code&gt;), the operating system can load a single copy of
          661 the library in memory and share the read-only parts of the code/data
          662 through the magic of virtual memory.&lt;/p&gt;
          663 &lt;p&gt;&lt;em&gt;In theory&lt;/em&gt;, if a library gets a bugfix but does not change its
          664 interface, one can just recompile the library, stick the new &lt;code&gt;.so&lt;/code&gt; in
          665 &lt;code&gt;/usr/lib&lt;/code&gt; or whatever, and be done with it.  Programs that depend on
          666 the library do not need to be recompiled.&lt;/p&gt;
          667 &lt;p&gt;If libraries limit their public interface to a plain C ABI
          668 (application binary interface), they are relatively easy to consume
          669 from other programming languages.  Those languages don't have to deal
          670 with name mangling of C++ symbols, exception handlers, constructors,
          671 and all that complexity.  Pretty much every language has some form of
          672 C FFI (foreign function interface), which roughly means "call C
          673 functions without too much trouble".&lt;/p&gt;
          674 &lt;p&gt;For the purposes of a library, what's an
          675 &lt;a href="https://en.wikipedia.org/wiki/Application_binary_interface"&gt;ABI&lt;/a&gt;?
          676 Wikipedia says, "An ABI defines how data structures or computational
          677 routines are accessed in machine code [...] A common aspect of an
          678 ABI is the calling convention", which means that to call a function in
          679 machine code you need to frob the call and stack pointers, pass some
          680 function arguments in registers or push some others to the stack, etc.
          681 Really low-level stuff.  Each machine architecture or operating system
          682 usually defines a C standard ABI.&lt;/p&gt;
          683 &lt;p&gt;For libraries, we commonly understand an ABI to mean the machine-code
          684 implications of their programming interface.  Which functions are
          685 available as public symbols in the &lt;code&gt;.so&lt;/code&gt; file?  To which numeric
          686 values do C enum values correspond, so that they can be passed to
          687 those functions?  What is the exact order and type of arguments that
          688 the functions take?  What are the struct sizes, and the order and
          689 types and padding of the fields that those functions take?  Does one
          690 pass arguments in CPU registers or on the stack?  Does the caller or
          691 the callee clean up the stack after a function call?&lt;/p&gt;
          692 &lt;h2&gt;Bug fixes and security fixes&lt;/h2&gt;
          693 &lt;p&gt;Linux distributions generally try &lt;em&gt;really hard&lt;/em&gt; to have a single
          694 version of each shared library installed in the system:  a single
          695 &lt;code&gt;libjpeg.so&lt;/code&gt;, a single &lt;code&gt;libpng.so&lt;/code&gt;, a single &lt;code&gt;libc.so&lt;/code&gt;, etc.&lt;/p&gt;
          696 &lt;p&gt;This is helpful when there needs to be an update to fix a bug,
          697 security-related or not: users can just download the updated package
          698 for the library, which when installed will just stick in a new &lt;code&gt;.so&lt;/code&gt;
          699 in the right place, and the calling software won't need to be updated.&lt;/p&gt;
          700 &lt;p&gt;This is possible only if the bug &lt;em&gt;really only changes the internal
          701 code&lt;/em&gt; without changing behavior or interface.  If a bug fix requires
          702 part of the public API or ABI to change, then you are screwed; all
          703 calling software needs to be recompiled.  "Irresponsible" library
          704 authors either learn really fast when distros complain loudly about
          705 this sort of change, or they don't learn and get forever marked by
          706 distros as "that irresponsible library" which always requires special
          707 handling in order not to break other software.&lt;/p&gt;
          708 &lt;p&gt;Sidenote: sometimes it's more complicated.  Poppler (the PDF
          709 rendering library) ships at least two stable APIs, one Glib-based in
          710 C, and one Qt-based in C++.  However, some software like texlive uses
          711 Poppler's internals library directly, which of course does not have a
          712 stable API, and thus texlive breaks frequently as Poppler evolves.
          713 Someone should extend the public, stable API so that texlive doesn't
          714 have to use the library's internals!&lt;/p&gt;
          715 &lt;h2&gt;Bundled libraries&lt;/h2&gt;
          716 &lt;p&gt;Sometimes it is not irresponsible authors of libraries, but rather
          717 that people who use the libraries find out that over time the behavior
          718 of the library changes subtly, maybe without breaking the API or ABI,
          719 and they are better off bundling a specific version of the library
          720 with their software.  That version is what they test their software
          721 against, and they try to learn its quirks.&lt;/p&gt;
          722 &lt;p&gt;Distros inevitably complain about this, and either patch the calling
          723 software by hand to force it to use the system's shared library, or
          724 succeed in getting patches accepted by the software so that they have
          725 a &lt;code&gt;--use-system-libjpeg&lt;/code&gt; option or similar.&lt;/p&gt;
          726 &lt;p&gt;This doesn't work very well if the bundled version of the library has
          727 extra patches that are not in a distro's usual patches.  Or
          728 vice-versa; it may actually work better to use the distro's version of
          729 the library, if it has extra fixes that the bundled library doesn't.
          730 Who knows!  It's a case-by-case situation.&lt;/p&gt;
          731 &lt;h2 id="rust_does_not_have_a_stable_abi"&gt;Rust does not have a stable ABI&lt;/h2&gt;
          732 &lt;p&gt;By default indeed it doesn't, because the compiler team wants to have
          733 the freedom to change the data layout and Rust-to-Rust calling
          734 conventions, often for performance reasons, at any time.  For example,
          735 it is not guaranteed that struct fields will be laid out in memory in
          736 the same order as they are written in the code:&lt;/p&gt;
          737 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          738 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          739 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;baz&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          740 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;beep&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          741 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;qux&lt;/span&gt;: &lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          742 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          743 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
          744 
          745 &lt;p&gt;The compiler is free to rearrange the struct fields in memory as it
          746 sees fit.  Maybe it decides to put the two &lt;code&gt;bool&lt;/code&gt; fields next to each
          747 other to save on inter-field padding due to alignment requirements;
          748 maybe it does static analysis or profile-guided optimizations and
          749 picks an optmal ordering.&lt;/p&gt;
          750 &lt;p&gt;But we can override this!  Let's look at data layout first, and then
          751 calling conventions.&lt;/p&gt;
          752 &lt;h3&gt;Data layout for C versus Rust&lt;/h3&gt;
          753 &lt;p&gt;The following is the same struct as above, but with an extra &lt;code&gt;#[repr(C)]&lt;/code&gt; attribute:&lt;/p&gt;
          754 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[repr(C)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          755 &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          756 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          757 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;baz&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          758 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;beep&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          759 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;qux&lt;/span&gt;: &lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          760 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          761 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
          762 
          763 &lt;p&gt;With that attribute, the struct will be laid out just as this C struct:&lt;/p&gt;
          764 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdbool.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
          765 &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
          766 
          767 &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          768     &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          769     &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          770     &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;beep&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          771     &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;qux&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          772 &lt;span class="p"&gt;}&lt;/span&gt;
          773 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
          774 
          775 &lt;p&gt;(Aside: it is unfortunate that &lt;a href="https://people.gnome.org/~federico/news-2017-04.html#gboolean-is-not-rust-bool"&gt;&lt;code&gt;gboolean&lt;/code&gt; is not &lt;code&gt;bool&lt;/code&gt;&lt;/a&gt;,
          776 but that's because &lt;code&gt;gboolean&lt;/code&gt; predates C99, and clearly standards from
          777 20 years ago are &lt;em&gt;too new&lt;/em&gt; to use.  (Aside aside: since I wrote that
          778 other post, Rust's repr(C) for bool is actually defined as C99's bool;
          779 it's no longer undefined.))&lt;/p&gt;
          780 &lt;p&gt;Even Rust's data-carrying enums can be laid out in a manner friendly
          781 to C and C++:&lt;/p&gt;
          782 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[repr(C, u8)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          783 &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;MyEnum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          784 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          785 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          786 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          787 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
          788 
          789 &lt;p&gt;This means, use C layout, and a &lt;code&gt;u8&lt;/code&gt; for the enum's discriminant.  It
          790 will be laid out like this:&lt;/p&gt;
          791 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdbool.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
          792 &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
          793 
          794 &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;MyEnumTag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          795         &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          796         &lt;span class="n"&gt;B&lt;/span&gt;
          797 &lt;span class="p"&gt;};&lt;/span&gt;
          798 
          799 &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;MyEnumPayloadA&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          800 
          801 &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          802         &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          803         &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          804 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;MyEnumPayloadB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          805 
          806 &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          807         &lt;span class="n"&gt;MyEnumPayloadA&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          808         &lt;span class="n"&gt;MyEnumPayloadB&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          809 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;MyEnumPayload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          810 
          811 &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          812         &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          813         &lt;span class="n"&gt;MyEnumPayload&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          814 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;MyEnum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          815 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
          816 
          817 &lt;p&gt;The gory details of data layout are in the &lt;a href="https://doc.rust-lang.org/nomicon/other-reprs.html"&gt;Alternative Representations section of the
          818 Rustonomicon&lt;/a&gt; and
          819 the &lt;a href="https://rust-lang.github.io/unsafe-code-guidelines/introduction.html"&gt;Unsafe Code
          820 Guidelines&lt;/a&gt;.&lt;/p&gt;
          821 &lt;h3&gt;Calling conventions&lt;/h3&gt;
          822 &lt;p&gt;An ABI's calling conventions detail things like how to call functions
          823 in machine code, and how to lay out function arguments in registers or
          824 the stack.  &lt;a href="https://en.wikipedia.org/wiki/X86_calling_conventions"&gt;The wikipedia page on X86 calling
          825 conventions&lt;/a&gt;
          826 has a good cheat-sheet, useful when you are looking at assembly code
          827 and registers in a low-level debugger.&lt;/p&gt;
          828 &lt;p&gt;I've already written about how it is possible to write Rust code to
          829 export functions callable from C; one uses the &lt;code&gt;extern "C"&lt;/code&gt; in the
          830 function definition and a &lt;code&gt;#[no_mangle]&lt;/code&gt; attribute to keep the symbol
          831 name pristine.  This is how librsvg is able to have the following:&lt;/p&gt;
          832 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          833 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;rsvg_handle_new_from_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          834 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc&lt;/span&gt;::&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          835 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib_sys&lt;/span&gt;::&lt;span class="n"&gt;GError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          836 &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RsvgHandle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          837 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
          838 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
          839 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
          840 
          841 &lt;p&gt;Which compiles to what a C compiler would produce for this:&lt;/p&gt;
          842 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;RsvgHandle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;rsvg_handle_new_from_file&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;gchar&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GError&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          843 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
          844 
          845 &lt;p&gt;(Aside: librsvg &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/416"&gt;still uses an intermediate C library full of
          846 stubs&lt;/a&gt; that just
          847 call the Rust-exported functions, but there is now &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/552"&gt;tooling to produce a .so
          848 directly from
          849 Rust&lt;/a&gt; which I
          850 just haven't had time to investigate.  Help is appreciated!)&lt;/p&gt;
          851 &lt;h3&gt;Summary of ABI so far&lt;/h3&gt;
          852 &lt;p&gt;It is &lt;em&gt;one's decision&lt;/em&gt; to export a stable C ABI from a Rust library.
          853 There is some awkwardness in how types are laid out in C, because the
          854 Rust type system is richer, but things can be made to work well with a
          855 little thought.  Certainly no more thought than the burden of
          856 designing and maintaining a stable API/ABI in plain C.&lt;/p&gt;
          857 &lt;p&gt;I'll fold the second concern into here — "we can't have shared
          858 libraries in traditional distro fashion".  Yes, we can, API/ABI-wise,
          859 but read on.&lt;/p&gt;
          860 &lt;h2&gt;Rust bundles its entire standard library with Rust-built .so's&lt;/h2&gt;
          861 &lt;p&gt;I.e. it statically links all the Rust dependencies.  This produces a
          862 large .so:&lt;/p&gt;
          863 &lt;ul&gt;
          864 &lt;li&gt;librsvg-2.so (version 2.40.21, C only) - 1408840 bytes&lt;/li&gt;
          865 &lt;li&gt;librsvg-2.so (version 2.49.3, Rust only) - 9899120 bytes&lt;/li&gt;
          866 &lt;/ul&gt;
          867 &lt;p&gt;Holy crap!  What's all that?&lt;/p&gt;
          868 &lt;p&gt;(And I'm cheating: this is both with link-time optimization turned on,
          869 and by running &lt;code&gt;strip(1)&lt;/code&gt; on the .so.  If you just &lt;code&gt;autogen.sh &amp;amp;&amp;amp; make&lt;/code&gt;
          870 it will be bigger.)&lt;/p&gt;
          871 &lt;p&gt;This has Rust's standard library statically linked (or at least the
          872 bits of that librsvg actually uses), plus all the Rust dependencies
          873 (cssparser, selectors, nalgebra, glib-rs, cairo-rs, locale_config,
          874 rayon, xml5ever, and an assload of crates).  I could explain why each
          875 one is needed:&lt;/p&gt;
          876 &lt;ul&gt;
          877 &lt;li&gt;cssparser - librsvg needs to parse CSS.&lt;/li&gt;
          878 &lt;li&gt;selectors - librsvg needs to run the CSS selector matching
          879   algorithm.&lt;/li&gt;
          880 &lt;li&gt;nalgebra - the code for SVG filter effects uses vectors and
          881   matrices.&lt;/li&gt;
          882 &lt;li&gt;glib-rs, cairo-rs - draw to Cairo and export GObject types.&lt;/li&gt;
          883 &lt;li&gt;locale_config - so that localized SVG files can work.&lt;/li&gt;
          884 &lt;li&gt;rayon - so filters can use all your CPU cores instead of processing
          885   one pixel at a time.&lt;/li&gt;
          886 &lt;li&gt;Etcetera.  SVG is big and requires a lot of helper code!&lt;/li&gt;
          887 &lt;/ul&gt;
          888 &lt;p&gt;Is this a problem?&lt;/p&gt;
          889 &lt;p&gt;Or more exactly, why does this happen, and why do people perceive it
          890 as a problem?&lt;/p&gt;
          891 &lt;h3&gt;Stable APIs/ABIs and distros&lt;/h3&gt;
          892 &lt;p&gt;Many Linux distributions have worked &lt;em&gt;really hard&lt;/em&gt; to ensure that
          893 there is a single copy of "system libraries" in an installation.
          894 There is Just One Copy of &lt;code&gt;/usr/lib/libc.so&lt;/code&gt;, &lt;code&gt;/usr/lib/libjpeg.so&lt;/code&gt;,
          895 etc., and packages are compiled with special options to tell them to
          896 really use the sytem libraries instead of their bundled versions, or
          897 patched to do so if they don't provide build-time options for that.&lt;/p&gt;
          898 &lt;p&gt;In a way, this works well for distros:&lt;/p&gt;
          899 &lt;ul&gt;
          900 &lt;li&gt;
          901 &lt;p&gt;A bug in a library can be fixed in a single place, and all
          902   applications that use it get the fix automatically.&lt;/p&gt;
          903 &lt;/li&gt;
          904 &lt;li&gt;
          905 &lt;p&gt;A security bug can be patched in a single place, and in theory
          906   applications don't need to be audited further.&lt;/p&gt;
          907 &lt;/li&gt;
          908 &lt;/ul&gt;
          909 &lt;p&gt;If you maintain a library that is shipped in Linux distros, and you
          910 break the ABI, you'll get complaints from distros very quickly.&lt;/p&gt;
          911 &lt;p&gt;This is good because it creates responsible maintainers for libraries
          912 that can be depended on.  It's how Inkscape/GIMP can have a stable
          913 toolkit to be written in.&lt;/p&gt;
          914 &lt;p&gt;This is bad because it encourages stagnation in the long term.  It's
          915 how we get a horrible, unsafe, error-prone API in libjpeg that can
          916 never ever be improved because it would requires changes in tons of
          917 software; it's why &lt;code&gt;gboolean&lt;/code&gt; is still a 32-bit &lt;code&gt;int&lt;/code&gt; after
          918 twenty-something years, even though everything else close to C has
          919 decided that booleans are 1 byte.  It's how Inkscape/GIMP take many
          920 years to move from GTK2 to GTK3 (okay, that's lack of paid developers
          921 to do the grunt work, but it is enabled by having forever-stable APIs).&lt;/p&gt;
          922 &lt;p&gt;However, a long-term stable API/ABI has a &lt;strong&gt;lot of value&lt;/strong&gt;.  It is why
          923 the Windows API is the crown jewels; it is why people can rely on glib
          924 and glibc to not break their code for many years and take them for granted.&lt;/p&gt;
          925 &lt;h3&gt;But we only have a single stable ABI anyway&lt;/h3&gt;
          926 &lt;p&gt;And that is the C ABI.  Even C++ libraries have trouble with this, and
          927 people sometimes write the internals of a library in C++ for
          928 convenience, but export a stable C API/ABI from it.&lt;/p&gt;
          929 &lt;p&gt;High level languages like Python have &lt;em&gt;real trouble&lt;/em&gt; calling C++ code
          930 precisely because of ABI issues.&lt;/p&gt;
          931 &lt;h3&gt;Actually, in GNOME we have gone further than that&lt;/h3&gt;
          932 &lt;p&gt;In GNOME we have constructed a sweet little universe where &lt;a href="https://people.gnome.org/~federico/blog/magic-of-gobject-introspection.html"&gt;GObject
          933 Introspection&lt;/a&gt; is
          934 basically a C ABI with a ton of machine-generated annotations to make
          935 it friendly to language bindings.&lt;/p&gt;
          936 &lt;p&gt;Still, we rely on a C ABI underneath.  See &lt;a href="https://twitter.com/federicomena/status/1286447929880801280"&gt;this exploratory twitter
          937 thread on advancing the C ABI from Rust&lt;/a&gt; for
          938 lots of food for thought.&lt;/p&gt;
          939 &lt;h3&gt;Single copies of libraries with a C ABI&lt;/h3&gt;
          940 &lt;p&gt;Okay, let's go back to this.  What price do we pay for single copies
          941 of libraries that, by necessity, must export a C ABI?&lt;/p&gt;
          942 &lt;ul&gt;
          943 &lt;li&gt;
          944 &lt;p&gt;Code that can be conveniently called from C, maybe from C++, and
          945   moderately to very inconvently from ANYTHING ELSE.  With most new
          946   application code being written definitely not in C, maybe we should
          947   reconsider our priorities here.&lt;/p&gt;
          948 &lt;/li&gt;
          949 &lt;li&gt;
          950 &lt;p&gt;No language facilities like generics or field visibility, which are
          951   not even "modern language" features.  Even C++ templates get
          952   compiled and statically linked into the calling code, because
          953   there's no way to pass information like the size of &lt;code&gt;T&lt;/code&gt; in
          954   &lt;code&gt;Array&amp;lt;T&amp;gt;&lt;/code&gt; across a C ABI.  You wanted to make some struct fields
          955   public and some private?  You are out of luck.&lt;/p&gt;
          956 &lt;/li&gt;
          957 &lt;li&gt;
          958 &lt;p&gt;No knowledge of data ownership except by careful reading of the C
          959   function's documentation.  Does the function free its arguments?
          960   How - with &lt;code&gt;free()&lt;/code&gt; or &lt;code&gt;g_free()&lt;/code&gt; or &lt;code&gt;my_thing_free()&lt;/code&gt;?  Or does the
          961   caller just lend it a reference?  Can the data be copied bit-by-bit
          962   or must a special function be called to make a copy?
          963   GObject-Introspection carries this information in its annotations,
          964   while the C ABI has no idea and just ships raw pointers around.&lt;/p&gt;
          965 &lt;/li&gt;
          966 &lt;/ul&gt;
          967 &lt;p&gt;More food for thought note: &lt;a href="https://twitter.com/hsivonen/status/1232204147740508162"&gt;this twitter
          968 thread&lt;/a&gt; says
          969 this about the C++ ABI: "Also, the ABI matters for whether the actual
          970 level of practicality of complying with LGPL matches the level of
          971 practicality intended years ago when some project picked LGPL as its
          972 license. Of course, the standard does not talk about LGPL, either.
          973 LGPL has rather different implications for Rust and Go than it does
          974 for C and Java. It was obviously written with C in mind."&lt;/p&gt;
          975 &lt;h2&gt;Monomorphization and template bloat&lt;/h2&gt;
          976 &lt;p&gt;While C++ had the problem of "lots of template code in header files",
          977 Rust has the problem that &lt;a href="https://pingcap.com/blog/generics-and-compile-time-in-rust#monomorphized-generics"&gt;monomorphization of generics creates a lot
          978 of compiled
          979 code&lt;/a&gt;.
          980 There are tricks to avoid this and they are all the decision of the
          981 library/crate author.  Both share the root cause that templated or
          982 generic code must be recompiled for every specific use, and thus
          983 cannot live in a shared library.&lt;/p&gt;
          984 &lt;p&gt;Also, see this wonderful &lt;a href="https://thume.ca/2019/07/14/a-tour-of-metaprogramming-models-for-generics/"&gt;article on how different languages implement
          985 generics&lt;/a&gt;,
          986 and think that a plain C ABI means we have NOTHING of the sort.&lt;/p&gt;
          987 &lt;p&gt;Also, see &lt;a href="https://gankra.github.io/blah/swift-abi/"&gt;How Swift Achieved Dynamic Linking Where Rust
          988 Couldn't&lt;/a&gt; for more food for
          989 thought.  This is extremely roughly equivalent to GObject's boxed
          990 types; callers keep values on the heap but know the type layout via
          991 annotation magic, while the library's actual implementation
          992 is free to have the values on the stack or wherever for its own use.&lt;/p&gt;
          993 &lt;h2&gt;Should all libraries export APIs with generics and exotic types?&lt;/h2&gt;
          994 &lt;p&gt;No!&lt;/p&gt;
          995 &lt;p&gt;You probably want something like a low-level array of values,
          996 &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt;, to be inlined everywhere and with code that knows the
          997 type of the vector's elements.  Element accesses can be inlined to a
          998 single machine instruction in the best case.&lt;/p&gt;
          999 &lt;p&gt;But not everything requires this absolute raw performance with
         1000 everything inlined everywhere.  It is fine to pass references or
         1001 pointers to things and do dynamic dispatch from a vtable if you are
         1002 not in a super-tight loop, as we love to do in the GObject world.&lt;/p&gt;
         1003 &lt;h2&gt;Library sizes&lt;/h2&gt;
         1004 &lt;p&gt;I don't have a good answer to librsvg's compiled size.  If gnome-shell
         1005 merges my branch to rustify the CSS code, it will also grow its binary
         1006 size by quite a bit.&lt;/p&gt;
         1007 &lt;p&gt;It is my intention to have a Rust crate that both librsvg and
         1008 gnome-shell share for their CSS styling needs, but right now I have no
         1009 idea if this would be a shared library or just a normal Rust crate.
         1010 Maybe it's possible to have a very general CSS library, and the
         1011 application registers which properties it can parse and how?  Is it
         1012 possible to do this as a shared library without essentially
         1013 reinventing libcroco?  I don't know yet.  We'll see.&lt;/p&gt;
         1014 &lt;h2&gt;A metaphor which I haven't fully explored&lt;/h2&gt;
         1015 &lt;p&gt;If every application or end-user package is kind of like a living
         1016 organism, with its own cycles and behaviors and organs (dependent
         1017 libraries) that make it possible...&lt;/p&gt;
         1018 &lt;p&gt;Why do distros expect all the living organisms on your machine to
         1019 share The World's Single Lungs Service, and The World's Single Stomach
         1020 Service, and The World's Single Liver Service?&lt;/p&gt;
         1021 &lt;p&gt;You know, instead of letting every organism have its own slightly
         1022 different version of those organs, customized for it?  We humans know
         1023 how to do vaccination campaigns and everything; maybe we need better
         1024 tools to apply bug fixes where they are needed?&lt;/p&gt;
         1025 &lt;p&gt;I know this metaphor is extremely imperfect and not how things work in
         1026 software, but it makes me wonder.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="gnome"></category></entry><entry><title>Looking for candidates for the 2020 GNOME Foundation elections</title><link href="https://people.gnome.org/~federico/blog/looking-for-candidates-2020.html" rel="alternate"></link><published>2020-05-26T17:05:31-05:00</published><updated>2020-05-26T17:05:31-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-05-26:/~federico/blog/looking-for-candidates-2020.html</id><summary type="html">&lt;p&gt;I forgot to write this a few days ago; I hope it is not too late.&lt;/p&gt;
         1027 &lt;p&gt;The GNOME Foundation's &lt;a href="https://mail.gnome.org/archives/foundation-announce/2020-May/msg00000.html"&gt;elections for the Board&lt;/a&gt; are coming
         1028 up, and we are looking for candidates.  Of the 7 directors, we are
         1029 replacing 4, and the 3 remaining positions remain for another year.
         1030 You …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I forgot to write this a few days ago; I hope it is not too late.&lt;/p&gt;
         1031 &lt;p&gt;The GNOME Foundation's &lt;a href="https://mail.gnome.org/archives/foundation-announce/2020-May/msg00000.html"&gt;elections for the Board&lt;/a&gt; are coming
         1032 up, and we are looking for candidates.  Of the 7 directors, we are
         1033 replacing 4, and the 3 remaining positions remain for another year.
         1034 You could be one of those four.&lt;/p&gt;
         1035 &lt;p&gt;I would like it very much if there were candidates and directors that
         1036 fall outside the box of "white male programmer"; it is unfortunate
         1037 that for the current Board we ended up with all dudes.  GNOME has a
         1038 &lt;a href="https://wiki.gnome.org/Foundation/CodeOfConduct"&gt;Code of Conduct&lt;/a&gt; to make it a good place to be.&lt;/p&gt;
         1039 &lt;p&gt;Allan Day wrote a &lt;a href="https://blogs.gnome.org/aday/2020/05/26/gnome-foundation-board-of-directors-a-year-in-review/"&gt;review of the Board's activies for the last
         1040 year&lt;/a&gt;.  We are moving from a model where the Board does a
         1041 little bit of everything, to one with a more strategic role — now that
         1042 the Foundation has full-time employees, they take care of most of the
         1043 executive work.&lt;/p&gt;
         1044 &lt;p&gt;&lt;strong&gt;The call-for-candidates is open until May 29, so hurry up!&lt;/strong&gt;&lt;/p&gt;
         1045 &lt;ul&gt;
         1046 &lt;li&gt;&lt;a href="https://blogs.gnome.org/aday/2020/05/26/gnome-foundation-board-of-directors-a-year-in-review/"&gt;GNOME Foundation Board of Directors: a Year in Review&lt;/a&gt;&lt;/li&gt;
         1047 &lt;li&gt;&lt;a href="https://mail.gnome.org/archives/foundation-announce/2020-May/msg00000.html"&gt;Call for candidates and elections&lt;/a&gt;&lt;/li&gt;
         1048 &lt;/ul&gt;</content><category term="misc"></category><category term="gnome"></category></entry><entry><title>Bringing my Emacs from the past</title><link href="https://people.gnome.org/~federico/blog/bringing-my-emacs-from-the-past.html" rel="alternate"></link><published>2020-04-28T18:03:22-05:00</published><updated>2020-04-28T18:03:22-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-04-28:/~federico/blog/bringing-my-emacs-from-the-past.html</id><summary type="html">&lt;p&gt;I started using Emacs in 1995, and since then I have been carrying a &lt;code&gt;.emacs&lt;/code&gt;
         1049 that by now has a lot of accumulated crap.  It is such an old configuration that
         1050 it didn't even use the modern convention of &lt;code&gt;~/.emacs.d/init.el&lt;/code&gt; (and it looks
         1051 like a newer Emacs …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I started using Emacs in 1995, and since then I have been carrying a &lt;code&gt;.emacs&lt;/code&gt;
         1052 that by now has a lot of accumulated crap.  It is such an old configuration that
         1053 it didn't even use the modern convention of &lt;code&gt;~/.emacs.d/init.el&lt;/code&gt; (and it looks
         1054 like a newer Emacs version will allow &lt;code&gt;.config/emacs&lt;/code&gt; as per the XDG
         1055 standard... at last).&lt;/p&gt;
         1056 &lt;p&gt;I have wanted to change my Emacs configuration for some time, and give it all
         1057 the pretty and modern toys.&lt;/p&gt;
         1058 &lt;p&gt;The things that matter the most to me:&lt;/p&gt;
         1059 &lt;ul&gt;
         1060 &lt;li&gt;Not have a random dumpster in &lt;code&gt;~/.emacs&lt;/code&gt; if possible.&lt;/li&gt;
         1061 &lt;li&gt;Pretty colors.&lt;/li&gt;
         1062 &lt;li&gt;Magit.&lt;/li&gt;
         1063 &lt;li&gt;Rust-mode or whatever the new thing is for rust-analyzer and the Language Server.&lt;/li&gt;
         1064 &lt;/ul&gt;
         1065 &lt;p&gt;After looking at several examples of configurations that mention &lt;code&gt;use-package&lt;/code&gt;
         1066 as a unified way of loading packages and configuring them, I found &lt;a href="https://github.com/alhassy/emacs.d"&gt;this
         1067 configuration&lt;/a&gt; which is extremely well
         1068 documented.  The author does literate programming with org-mode and elisp —
         1069 something which I'm casually interested in, but not just now — but that way
         1070 everything ends up very well explained and easy to read.&lt;/p&gt;
         1071 &lt;p&gt;I extracted bits of that configuration and ended up with the following.&lt;/p&gt;
         1072 &lt;h2&gt;Everything in &lt;code&gt;~/.emacs/init.el&lt;/code&gt; and with &lt;code&gt;use-package&lt;/code&gt;&lt;/h2&gt;
         1073 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;;; Initialize package system&lt;/span&gt;
         1074 
         1075 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;package&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1076 
         1077 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;package-archives&lt;/span&gt;
         1078       &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;org&amp;quot;&lt;/span&gt;     &lt;span class="o"&gt;.&lt;/span&gt;       &lt;span class="s"&gt;&amp;quot;https://orgmode.org/elpa/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1079         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gnu&amp;quot;&lt;/span&gt;     &lt;span class="o"&gt;.&lt;/span&gt;       &lt;span class="s"&gt;&amp;quot;https://elpa.gnu.org/packages/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1080         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;melpa&amp;quot;&lt;/span&gt;   &lt;span class="o"&gt;.&lt;/span&gt;       &lt;span class="s"&gt;&amp;quot;https://melpa.org/packages/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
         1081 
         1082 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;package-initialize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1083 &lt;span class="c1"&gt;;(package-refresh-contents)&lt;/span&gt;
         1084 
         1085 &lt;span class="c1"&gt;;; Use-package for civilized configuration&lt;/span&gt;
         1086 
         1087 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;unless&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;package-installed-p&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;use-package&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1088   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;package-install&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;use-package&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1089 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;use-package&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1090 
         1091 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;use-package-always-ensure&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1092 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1093 
         1094 &lt;h2&gt;&lt;code&gt;~/.emacs.d/custom.el&lt;/code&gt; for &lt;code&gt;M-x customize&lt;/code&gt; stuff&lt;/h2&gt;
         1095 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;;; Set customization data in a specific file, without littering&lt;/span&gt;
         1096 &lt;span class="c1"&gt;;; my init files.&lt;/span&gt;
         1097 
         1098 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;custom-file&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;~/.emacs.d/custom.el&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1099 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt; &lt;span class="nv"&gt;custom-file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1100 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1101 
         1102 &lt;h2&gt;Which-key to get hints when typing command prefixes&lt;/h2&gt;
         1103 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;;; Make it easier to discover key shortcuts&lt;/span&gt;
         1104 
         1105 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;which-key&lt;/span&gt;
         1106   &lt;span class="nb"&gt;:diminish&lt;/span&gt;
         1107   &lt;span class="nb"&gt;:config&lt;/span&gt;
         1108   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;which-key-mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1109   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;which-key-setup-side-window-bottom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1110   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;which-key-idle-delay&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1111 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1112 
         1113 &lt;h2&gt;Don't pollute the modeline with common modes&lt;/h2&gt;
         1114 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;;; Do not show some common modes in the modeline, to save space&lt;/span&gt;
         1115 
         1116 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;diminish&lt;/span&gt;
         1117   &lt;span class="nb"&gt;:defer&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
         1118   &lt;span class="nb"&gt;:config&lt;/span&gt;
         1119   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;diminish&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;org-indent-mode&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1120 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1121 
         1122 &lt;h2&gt;Magit to use git in a civilized fashion&lt;/h2&gt;
         1123 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;;; Magit&lt;/span&gt;
         1124 
         1125 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;magit&lt;/span&gt;
         1126   &lt;span class="nb"&gt;:config&lt;/span&gt;
         1127   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;C-x g&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;magit-status&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1128 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1129 
         1130 &lt;h2&gt;Move between windows with Shift-arrows&lt;/h2&gt;
         1131 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;;; Let me switch windows with shift-arrows instead of &amp;quot;C-x o&amp;quot; all the time&lt;/span&gt;
         1132 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;windmove-default-keybindings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1133 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1134 
         1135 &lt;h2&gt;Pretty colors&lt;/h2&gt;
         1136 &lt;p&gt;I was using &lt;code&gt;solarized-dark&lt;/code&gt; but I like this one even better:&lt;/p&gt;
         1137 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;;; Pretty colors&lt;/span&gt;
         1138 
         1139 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;flatland-theme&lt;/span&gt;
         1140   &lt;span class="nb"&gt;:config&lt;/span&gt;
         1141   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;custom-theme-set-faces&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;flatland&lt;/span&gt;
         1142    &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;show-paren-match&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="no"&gt;t&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;:background&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;dark gray&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;:foreground&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;black&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;:weight&lt;/span&gt; &lt;span class="nv"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
         1143    &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;show-paren-mismatch&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="no"&gt;t&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;:background&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;firebrick&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;:foreground&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;orange&amp;quot;&lt;/span&gt; &lt;span class="nb"&gt;:weight&lt;/span&gt; &lt;span class="nv"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;
         1144 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1145 
         1146 &lt;h2&gt;Nyan cat instead of scrollbars&lt;/h2&gt;
         1147 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;;; Nyan cat instead of scrollbar&lt;/span&gt;
         1148 &lt;span class="c1"&gt;;; scroll-bar-mode is turned off in custom.el&lt;/span&gt;
         1149 
         1150 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;nyan-mode&lt;/span&gt;
         1151   &lt;span class="nb"&gt;:config&lt;/span&gt;
         1152   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;nyan-mode&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1153 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1154 
         1155 &lt;h2&gt;Move buffers to adjacent windows&lt;/h2&gt;
         1156 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;;; Move buffers between windows&lt;/span&gt;
         1157 
         1158 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;buffer-move&lt;/span&gt;
         1159   &lt;span class="nb"&gt;:config&lt;/span&gt;
         1160   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;lt;C-S-up&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="ss"&gt;&amp;#39;buf-move-up&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1161   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;lt;C-S-down&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="ss"&gt;&amp;#39;buf-move-down&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1162   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;lt;C-S-left&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="ss"&gt;&amp;#39;buf-move-left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1163   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;lt;C-S-right&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="ss"&gt;&amp;#39;buf-move-right&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1164 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1165 
         1166 &lt;h2&gt;Change buffer names for files with the same name&lt;/h2&gt;
         1167 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;;; Note that ‘uniquify’ is builtin.&lt;/span&gt;
         1168 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;uniquify&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1169 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;uniquify-separator&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;               &lt;span class="c1"&gt;;; The separator in buffer names.&lt;/span&gt;
         1170       &lt;span class="nv"&gt;uniquify-buffer-name-style&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;forward&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;;; names/in/this/style&lt;/span&gt;
         1171 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1172 
         1173 &lt;h2&gt;Helm to auto-complete in grand style&lt;/h2&gt;
         1174 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;helm&lt;/span&gt;
         1175  &lt;span class="nb"&gt;:diminish&lt;/span&gt;
         1176  &lt;span class="nb"&gt;:init&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;helm-mode&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1177  &lt;span class="nb"&gt;:bind&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;M-x&amp;quot;&lt;/span&gt;     &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;helm-M-x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1178         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C-x C-f&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;helm-find-files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1179         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C-x b&amp;quot;&lt;/span&gt;   &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;helm-mini&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;;; See buffers &amp;amp; recent files; more useful.&lt;/span&gt;
         1180         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C-x r b&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;helm-filtered-bookmarks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1181         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C-x C-r&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;helm-recentf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;;; Search for recently edited files&lt;/span&gt;
         1182         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C-c i&amp;quot;&lt;/span&gt;   &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;helm-imenu&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1183         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C-h a&amp;quot;&lt;/span&gt;   &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;helm-apropos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1184         &lt;span class="c1"&gt;;; Look at what was cut recently &amp;amp; paste it in.&lt;/span&gt;
         1185         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;M-y&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;helm-show-kill-ring&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1186 
         1187         &lt;span class="nb"&gt;:map&lt;/span&gt; &lt;span class="nv"&gt;helm-map&lt;/span&gt;
         1188         &lt;span class="c1"&gt;;; We can list ‘actions’ on the currently selected item by C-z.&lt;/span&gt;
         1189         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C-z&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;helm-select-action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1190         &lt;span class="c1"&gt;;; Let&amp;#39;s keep tab-completetion anyhow.&lt;/span&gt;
         1191         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;TAB&amp;quot;&lt;/span&gt;   &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;helm-execute-persistent-action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1192         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;lt;tab&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;helm-execute-persistent-action&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
         1193 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1194 
         1195 &lt;h2&gt;Ripgrep to search in grand style&lt;/h2&gt;
         1196 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;;; Ripgrep&lt;/span&gt;
         1197 
         1198 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;rg&lt;/span&gt;
         1199   &lt;span class="nb"&gt;:config&lt;/span&gt;
         1200   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;M-s g&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;rg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1201   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;M-s d&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;rg-dwim&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1202 
         1203 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;helm-rg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1204 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1205 
         1206 &lt;h2&gt;Rust mode and Language Server&lt;/h2&gt;
         1207 &lt;p&gt;Now that RLS is in the process of being deprecated, it's getting substituted
         1208 with rust-analyzer.  Also, rust-mode goes away in favor of rustic.&lt;/p&gt;
         1209 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;;; Rustic, LSP&lt;/span&gt;
         1210 
         1211 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;flycheck&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1212 
         1213 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;rustic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1214 
         1215 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;lsp-ui&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1216 
         1217 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;helm-lsp&lt;/span&gt;
         1218   &lt;span class="nb"&gt;:config&lt;/span&gt;
         1219   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define-key&lt;/span&gt; &lt;span class="nv"&gt;lsp-mode-map&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;remap&lt;/span&gt; &lt;span class="nv"&gt;xref-find-apropos&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="nf"&gt;#&amp;#39;&lt;/span&gt;&lt;span class="nv"&gt;helm-lsp-workspace-symbol&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1220 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1221 
         1222 &lt;h2&gt;Performatively not get distracted&lt;/h2&gt;
         1223 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;;;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Show&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;compilation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;finishes&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1224 
         1225 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;setq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;compilation&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;finish&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;functions&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1226 &lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;compilation&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;finish&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;functions&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1227 &lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmq&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compilation&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;finish&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1228 
         1229 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;defun&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fmq&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compilation&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;finish&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1230 &lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Grep&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1231 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;notify-send&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1232 &lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-t&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1233 &lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-i&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;emacs&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1234 &lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Compilation finished in Emacs&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1235 &lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1236 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1237 
         1238 &lt;h2&gt;Stuff from custom.el&lt;/h2&gt;
         1239 &lt;p&gt;The interesting bits here are making LSP work; everything else is preferences.&lt;/p&gt;
         1240 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;custom-set-variables&lt;/span&gt;
         1241  &lt;span class="c1"&gt;;; custom-set-variables was added by Custom.&lt;/span&gt;
         1242  &lt;span class="c1"&gt;;; If you edit it by hand, you could mess it up, so be careful.&lt;/span&gt;
         1243  &lt;span class="c1"&gt;;; Your init file should contain only one such instance.&lt;/span&gt;
         1244  &lt;span class="c1"&gt;;; If there is more than one, they won&amp;#39;t work right.&lt;/span&gt;
         1245  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;column-number-mode&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1246  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;custom-safe-themes&lt;/span&gt;
         1247    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt;
         1248     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;2540689fd0bc5d74c4682764ff6c94057ba8061a98be5dd21116bf7bf301acfb&amp;quot;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;bffa9739ce0752a37d9b1eee78fc00ba159748f50dc328af4be661484848e476&amp;quot;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;0fffa9669425ff140ff2ae8568c7719705ef33b7a927a0ba7c5e2ffcfac09b75&amp;quot;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;2809bcb77ad21312897b541134981282dc455ccd7c14d74cc333b6e549b824f3&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;default&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
         1249  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;delete-selection-mode&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1250  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lsp-rust-analyzer-display-chaining-hints&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1251  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lsp-rust-analyzer-display-parameter-hints&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1252  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lsp-rust-analyzer-macro-expansion-method&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt; &lt;span class="nv"&gt;rustic-analyzer-macro-expand&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1253  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lsp-rust-analyzer-server-command&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/home/federico/.cargo/bin/rust-analyzer&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
         1254  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lsp-rust-analyzer-server-display-inlay-hints&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1255  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lsp-rust-full-docs&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1256  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lsp-rust-server&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt; &lt;span class="nv"&gt;rust-analyzer&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1257  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lsp-ui-doc-alignment&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt; &lt;span class="nv"&gt;window&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1258  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lsp-ui-doc-position&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt; &lt;span class="nv"&gt;top&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1259  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lsp-ui-sideline-enable&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1260  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;menu-bar-mode&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1261  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;package-selected-packages&lt;/span&gt;
         1262    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt;
         1263     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;helm-lsp&lt;/span&gt; &lt;span class="nv"&gt;lsp-ui&lt;/span&gt; &lt;span class="nv"&gt;lsp-mode&lt;/span&gt; &lt;span class="nv"&gt;flycheck&lt;/span&gt; &lt;span class="nv"&gt;rustic&lt;/span&gt; &lt;span class="nv"&gt;rg&lt;/span&gt; &lt;span class="nv"&gt;helm-rg&lt;/span&gt; &lt;span class="nv"&gt;ripgrep&lt;/span&gt; &lt;span class="nv"&gt;helm-projectile&lt;/span&gt; &lt;span class="nv"&gt;helm&lt;/span&gt; &lt;span class="nv"&gt;buffer-move&lt;/span&gt; &lt;span class="nv"&gt;nyan-mode&lt;/span&gt; &lt;span class="nv"&gt;flatland-black-theme&lt;/span&gt; &lt;span class="nv"&gt;flatland-theme&lt;/span&gt; &lt;span class="nv"&gt;afternoon-theme&lt;/span&gt; &lt;span class="nv"&gt;spacemacs-theme&lt;/span&gt; &lt;span class="nv"&gt;solarized-theme&lt;/span&gt; &lt;span class="nv"&gt;magit&lt;/span&gt; &lt;span class="nv"&gt;diminish&lt;/span&gt; &lt;span class="nv"&gt;which-key&lt;/span&gt; &lt;span class="nb"&gt;use-package&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
         1264  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;rustic-lsp-server&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;quote&lt;/span&gt; &lt;span class="nv"&gt;rust-analyzer&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1265  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;scroll-bar-mode&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1266  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;scroll-step&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1267  &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;tool-bar-mode&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         1268 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;custom-set-faces&lt;/span&gt;
         1269  &lt;span class="c1"&gt;;; custom-set-faces was added by Custom.&lt;/span&gt;
         1270  &lt;span class="c1"&gt;;; If you edit it by hand, you could mess it up, so be careful.&lt;/span&gt;
         1271  &lt;span class="c1"&gt;;; Your init file should contain only one such instance.&lt;/span&gt;
         1272  &lt;span class="c1"&gt;;; If there is more than one, they won&amp;#39;t work right.&lt;/span&gt;
         1273  &lt;span class="p"&gt;)&lt;/span&gt;
         1274 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1275 
         1276 &lt;h2&gt;Results&lt;/h2&gt;
         1277 &lt;p&gt;I am very happy with rustic / rust-analyzer and the Language Server.  Having
         1278 documentation on each thing when one moves the cursor around code is something
         1279 that I never thought would work well in Emacs.  I haven't decided if I love &lt;code&gt;M-x
         1280 lsp-rust-analyzer-inlay-hints-mode&lt;/code&gt; or if it drives me nuts; it shows you the
         1281 names of function arguments and inferred types among the code.  I suppose I'll
         1282 turn it off and on as needed.&lt;/p&gt;
         1283 &lt;p&gt;Some days ago, before using helm, I had projectile-mode to work with git
         1284 checkouts and I was quite liking it.  I haven't found how to configure
         1285 helm-projectile to work; I'll have to keep experimenting.&lt;/p&gt;</content><category term="misc"></category><category term="emacs"></category></entry><entry><title>Reducing memory consumption in librsvg, part 4: compact representation for Bézier paths</title><link href="https://people.gnome.org/~federico/blog/reducing-memory-consumption-in-librsvg-4.html" rel="alternate"></link><published>2020-03-26T18:58:36-06:00</published><updated>2020-03-26T18:58:36-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-03-26:/~federico/blog/reducing-memory-consumption-in-librsvg-4.html</id><summary type="html">&lt;p&gt;Let's continue with the &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/574"&gt;enormous SVG&lt;/a&gt; from the last time, a
         1286 map extracted from OpenStreetMap.&lt;/p&gt;
         1287 &lt;p&gt;According to &lt;a href="https://valgrind.org/docs/manual/ms-manual.html"&gt;Massif&lt;/a&gt;, peak memory consumption for that file occurs at
         1288 the following point during the execution of rsvg-convert.  I pasted
         1289 only the part that refers to Bézier paths:&lt;/p&gt;
         1290 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="nt"&gt;--------------------------------------------------------------------------------&lt;/span&gt;
         1291       &lt;span class="nt"&gt;n&lt;/span&gt;        &lt;span class="nt"&gt;time&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;         &lt;span class="nt"&gt;total&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;   &lt;span class="nt"&gt;useful-heap …&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;Let's continue with the &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/574"&gt;enormous SVG&lt;/a&gt; from the last time, a
         1292 map extracted from OpenStreetMap.&lt;/p&gt;
         1293 &lt;p&gt;According to &lt;a href="https://valgrind.org/docs/manual/ms-manual.html"&gt;Massif&lt;/a&gt;, peak memory consumption for that file occurs at
         1294 the following point during the execution of rsvg-convert.  I pasted
         1295 only the part that refers to Bézier paths:&lt;/p&gt;
         1296 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="nt"&gt;--------------------------------------------------------------------------------&lt;/span&gt;
         1297       &lt;span class="nt"&gt;n&lt;/span&gt;        &lt;span class="nt"&gt;time&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;         &lt;span class="nt"&gt;total&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;   &lt;span class="nt"&gt;useful-heap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;extra-heap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;    &lt;span class="nt"&gt;stacks&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1298     &lt;span class="nt"&gt;--------------------------------------------------------------------------------&lt;/span&gt;
         1299 &lt;span class="nt"&gt;1&lt;/span&gt;    &lt;span class="nt"&gt;33&lt;/span&gt; &lt;span class="nt"&gt;24&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;139&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;598&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;653&lt;/span&gt;    &lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;416&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;831&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;176&lt;/span&gt;    &lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;329&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;943&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;212&lt;/span&gt;    &lt;span class="nt"&gt;86&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;887&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;964&lt;/span&gt;            &lt;span class="nt"&gt;0&lt;/span&gt;
         1300 &lt;span class="nt"&gt;2&lt;/span&gt;   &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;24&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;88&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;352&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;523&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;448B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x4A2727E&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;alloc&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;84&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1301     &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;24&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;88&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;352&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;523&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;448B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x4A2727E&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;alloc&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;172&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1302     &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;24&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;88&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;352&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;523&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;448B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x4A2727E&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;allocate_in&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rsvg_internals&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;path_builder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;PathCommand&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;Global&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;raw_vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;98&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1303     &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;24&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;88&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;352&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;523&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;448B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x4A2727E&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;with_capacity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rsvg_internals&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;path_builder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;PathCommand&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;raw_vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;167&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1304     &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;24&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;88&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;352&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;523&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;448B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x4A2727E&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;with_capacity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rsvg_internals&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;path_builder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;PathCommand&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;358&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1305     &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;24&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;88&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;352&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;523&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;448B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x4A2727E&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;as&lt;/span&gt; &lt;span class="nt"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;SpecExtend&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;T&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;I&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;from_iter&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;1992&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1306     &lt;span class="o"&gt;|&lt;/span&gt;           &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;24&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;88&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;352&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;523&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;448B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x49D212C&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;from_iter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rsvg_internals&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;path_builder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;PathCommand&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;smallvec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;IntoIter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cp"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rsvg_internals&lt;/span&gt;&lt;span class="nl"&gt;::path_builder::PathCommand&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="cp"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;1901&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1307     &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;24&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;88&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;352&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;523&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;448B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x49D212C&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;collect&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;smallvec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;IntoIter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cp"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rsvg_internals&lt;/span&gt;&lt;span class="nl"&gt;::path_builder::PathCommand&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="cp"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt;&lt;span class="nt"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rsvg_internals&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;path_builder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;PathCommand&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;1493&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1308     &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;24&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;88&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;352&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;523&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;448B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x49D212C&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;into_vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cp"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rsvg_internals&lt;/span&gt;&lt;span class="nl"&gt;::path_builder::PathCommand&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="cp"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;893&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1309     &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;24&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;88&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;352&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;523&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;448B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x49D212C&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;smallvec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;SmallVec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;into_boxed_slice&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;902&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1310 &lt;span class="nt"&gt;3&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;24&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;88&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;352&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;523&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;016B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x4A0394C&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;into_path&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;path_builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;320&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1311     &lt;span class="o"&gt;|&lt;/span&gt;
         1312 &lt;span class="nt"&gt;4&lt;/span&gt;   &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;03&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;50&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;990&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;328B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x4A242F0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;realloc&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;128&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1313     &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;03&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;50&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;990&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;328B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x4A242F0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;realloc&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;187&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1314     &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;03&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;50&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;990&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;328B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x4A242F0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;shrink_to_fit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rsvg_internals&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;path_builder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;PathCommand&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;Global&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;raw_vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;633&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1315     &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;03&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;50&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;990&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;328B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x4A242F0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;shrink_to_fit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rsvg_internals&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;path_builder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;PathCommand&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;623&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1316     &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;03&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;50&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;990&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;328B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x4A242F0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;into_boxed_slice&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;679&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1317     &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;03&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;50&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;990&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;328B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x49D2136&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;smallvec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;SmallVec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;into_boxed_slice&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;902&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1318 &lt;span class="nt"&gt;5&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;           &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;03&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;60&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;50&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;990&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;328B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;0x4A0394C&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;into_path&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;path_builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;320&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         1319 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1320 
         1321 &lt;p&gt;Line 1 has the totals, and we see that at that point the program uses
         1322 1,329,943,212 bytes on the heap.&lt;/p&gt;
         1323 &lt;p&gt;Lines 3 and 5 give us a hint that &lt;code&gt;into_path&lt;/code&gt; is being called; this is
         1324 the function that converts a temporary/mutable &lt;code&gt;PathBuilder&lt;/code&gt; into a
         1325 permanent/immutable &lt;code&gt;Path&lt;/code&gt;.&lt;/p&gt;
         1326 &lt;p&gt;Lines 2 and 4 indicate that the arrays of &lt;code&gt;PathCommand&lt;/code&gt;, which are
         1327 inside those immutable &lt;code&gt;Path&lt;/code&gt;s, use 24.88% + 3.60% = 28.48% of the
         1328 program's memory; between both they use
         1329 352,523,448 + 50,990,328 = 403,513,776 bytes.&lt;/p&gt;
         1330 &lt;p&gt;That is about 400 MB of &lt;code&gt;PathCommand&lt;/code&gt;.  Let's see what's going on.&lt;/p&gt;
         1331 &lt;h2&gt;What is in a PathCommand?&lt;/h2&gt;
         1332 &lt;p&gt;A &lt;code&gt;Path&lt;/code&gt; is a list of commands similar to PostScript, which get used
         1333 in SVG to draw Bézier paths.  It is a flat array of &lt;code&gt;PathCommand&lt;/code&gt;:&lt;/p&gt;
         1334 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1335 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;path_commands&lt;/span&gt;: &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1336 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1337 
         1338 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;PathCommand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1339 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;MoveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1340 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;LineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1341 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;CurveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CubicBezierCurve&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1342 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EllipticalArc&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1343 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ClosePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1344 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1345 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1346 
         1347 &lt;p&gt;Let's see the variants of &lt;code&gt;PathCommand&lt;/code&gt;:&lt;/p&gt;
         1348 &lt;ul&gt;
         1349 &lt;li&gt;&lt;code&gt;MoveTo&lt;/code&gt;: 2 double-precision floating-point numbers.&lt;/li&gt;
         1350 &lt;li&gt;&lt;code&gt;LineTo&lt;/code&gt;: same.&lt;/li&gt;
         1351 &lt;li&gt;&lt;code&gt;CurveTo&lt;/code&gt;: 6 double-precision floating-point numbers.&lt;/li&gt;
         1352 &lt;li&gt;&lt;code&gt;EllipticalArc&lt;/code&gt;: 7 double-precision floating-point numbers, plus 2
         1353   flags (see below).&lt;/li&gt;
         1354 &lt;li&gt;&lt;code&gt;ClosePath&lt;/code&gt;: no extra data.&lt;/li&gt;
         1355 &lt;/ul&gt;
         1356 &lt;p&gt;These variants vary a lot in terms of size, and each element of the
         1357 &lt;code&gt;Path.path_commands&lt;/code&gt; array occupies the maximum of their sizes
         1358 (i.e. &lt;code&gt;sizeof::&amp;lt;EllipticalArc&amp;gt;&lt;/code&gt;).&lt;/p&gt;
         1359 &lt;h2&gt;A more compact representation&lt;/h2&gt;
         1360 &lt;p&gt;Ideally, each command in the array would only occupy as much space as
         1361 it needs.&lt;/p&gt;
         1362 &lt;p&gt;We can represent a &lt;code&gt;Path&lt;/code&gt; in a different way, as two separate arrays:&lt;/p&gt;
         1363 &lt;ul&gt;
         1364 &lt;li&gt;A very compact array of commands without coordinates.&lt;/li&gt;
         1365 &lt;li&gt;An array with coordinates only.&lt;/li&gt;
         1366 &lt;/ul&gt;
         1367 &lt;p&gt;That is, the following:&lt;/p&gt;
         1368 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1369 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;commands&lt;/span&gt;: &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PackedCommand&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1370 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;: &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1371 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1372 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1373 
         1374 &lt;p&gt;The &lt;code&gt;coords&lt;/code&gt; array is obvious; it is just a flat array with all the
         1375 coordinates in the &lt;code&gt;Path&lt;/code&gt; in the order in which they appear.&lt;/p&gt;
         1376 &lt;p&gt;And the &lt;code&gt;commands&lt;/code&gt; array?&lt;/p&gt;
         1377 &lt;h3&gt;PackedCommand&lt;/h3&gt;
         1378 &lt;p&gt;We saw above that the biggest variant in &lt;code&gt;PathCommand&lt;/code&gt; is
         1379 &lt;code&gt;Arc(EllipticalArc)&lt;/code&gt;.  Let's look inside it:&lt;/p&gt;
         1380 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;EllipticalArc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1381 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;: &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1382 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x_axis_rotation&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1383 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;large_arc&lt;/span&gt;: &lt;span class="nc"&gt;LargeArc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1384 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sweep&lt;/span&gt;: &lt;span class="nc"&gt;Sweep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1385 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;: &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1386 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;: &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1387 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1388 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1389 
         1390 &lt;p&gt;There are 7 &lt;code&gt;f64&lt;/code&gt; floating-point numbers there.  The other two fields,
         1391 &lt;code&gt;large_arc&lt;/code&gt; and &lt;code&gt;sweep&lt;/code&gt;, are effectively booleans (they are just enums
         1392 with two variants, with pretty names instead of just &lt;code&gt;true&lt;/code&gt; and
         1393 &lt;code&gt;false&lt;/code&gt;).&lt;/p&gt;
         1394 &lt;p&gt;Thus, we have 7 doubles and two flags.  Between the two flags there
         1395 are 4 possibilities.&lt;/p&gt;
         1396 &lt;p&gt;Since no other &lt;code&gt;PathCommand&lt;/code&gt; variant has flags, we can have the
         1397 following enum, which fits in a single byte:&lt;/p&gt;
         1398 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[repr(u8)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1399 &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;PackedCommand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1400 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;MoveTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1401 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;LineTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1402 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;CurveTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1403 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ArcSmallNegative&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1404 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ArcSmallPositive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1405 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ArcLargeNegative&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1406 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ArcLargePositive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1407 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ClosePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1408 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1409 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1410 
         1411 &lt;p&gt;That is, simple values for &lt;code&gt;MoveTo&lt;/code&gt;/etc. and four special values for
         1412 the different types of &lt;code&gt;Arc&lt;/code&gt;.&lt;/p&gt;
         1413 &lt;h2&gt;Packing a PathCommand into a PackedCommand&lt;/h2&gt;
         1414 &lt;p&gt;In order to pack the array of &lt;code&gt;PathCommand&lt;/code&gt;, we must first know how
         1415 many coordinates each of its variants will produce:&lt;/p&gt;
         1416 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1417 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;num_coordinates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;usize&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1418 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1419 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;::&lt;span class="n"&gt;MoveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1420 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;::&lt;span class="n"&gt;LineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1421 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;::&lt;span class="n"&gt;CurveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1422 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;::&lt;span class="n"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1423 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;::&lt;span class="n"&gt;ClosePath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1424 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1425 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1426 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1427 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1428 
         1429 &lt;p&gt;Then, we need to convert each &lt;code&gt;PathCommand&lt;/code&gt; into a &lt;code&gt;PackedCommand&lt;/code&gt; and
         1430 write its coordinates into an array:&lt;/p&gt;
         1431 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1432 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;to_packed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;PackedCommand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1433 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1434 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;::&lt;span class="n"&gt;MoveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1435 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1436 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1437 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;PackedCommand&lt;/span&gt;::&lt;span class="n"&gt;MoveTo&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1438 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1439 
         1440 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;// etc. for the other simple commands&lt;/span&gt;
         1441 
         1442 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;::&lt;span class="n"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_packed_and_coords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1443 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1444 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1445 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1446 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1447 
         1448 &lt;p&gt;Let's look at that &lt;code&gt;to_packed_and_coords&lt;/code&gt; more closely:&lt;/p&gt;
         1449 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EllipticalArc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1450 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;to_packed_and_coords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;PackedCommand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1451 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1452 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1453 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x_axis_rotation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1454 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1455 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1456 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1457 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1458 
         1459 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;large_arc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sweep&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1460 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LargeArc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sweep&lt;/span&gt;::&lt;span class="n"&gt;Negative&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PackedCommand&lt;/span&gt;::&lt;span class="n"&gt;ArcSmallNegative&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1461 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LargeArc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sweep&lt;/span&gt;::&lt;span class="n"&gt;Positive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PackedCommand&lt;/span&gt;::&lt;span class="n"&gt;ArcSmallPositive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1462 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LargeArc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sweep&lt;/span&gt;::&lt;span class="n"&gt;Negative&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PackedCommand&lt;/span&gt;::&lt;span class="n"&gt;ArcLargeNegative&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1463 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LargeArc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sweep&lt;/span&gt;::&lt;span class="n"&gt;Positive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PackedCommand&lt;/span&gt;::&lt;span class="n"&gt;ArcLargePositive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1464 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1465 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1466 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1467 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1468 
         1469 &lt;h2&gt;Creating the compact Path&lt;/h2&gt;
         1470 &lt;p&gt;Let's look at &lt;code&gt;PathBuilder::into_path&lt;/code&gt; line by line:&lt;/p&gt;
         1471 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PathBuilder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1472 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;into_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1473 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num_commands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path_commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1474 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num_coords&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1475 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path_commands&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1476 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1477 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_coordinates&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1478 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1479 
         1480 &lt;p&gt;First we compute the total number of coordinates using &lt;code&gt;fold&lt;/code&gt;; we ask
         1481 each command &lt;code&gt;cmd&lt;/code&gt; its &lt;code&gt;num_coordinates()&lt;/code&gt; and add it into the &lt;code&gt;acc&lt;/code&gt;
         1482 accumulator.&lt;/p&gt;
         1483 &lt;p&gt;Now we know how much memory to allocate:&lt;/p&gt;
         1484 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;packed_commands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;::&lt;span class="n"&gt;with_capacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_commands&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1485 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num_coords&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1486 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1487 
         1488 &lt;p&gt;We use &lt;code&gt;Vec::with_capacity&lt;/code&gt; to allocate exactly as much memory as we will
         1489 need for the &lt;code&gt;packed_commands&lt;/code&gt;; adding elements will not need a
         1490 &lt;code&gt;realloc()&lt;/code&gt;, since we already know how many elements we will have.&lt;/p&gt;
         1491 &lt;p&gt;We use the &lt;code&gt;vec!&lt;/code&gt; macro to create an array of &lt;code&gt;0.0&lt;/code&gt; repeated
         1492 &lt;code&gt;num_coords&lt;/code&gt; times; that macro uses &lt;code&gt;with_capacity&lt;/code&gt; internally.  That is the
         1493 array we will use to store the coordinates for all the commands.&lt;/p&gt;
         1494 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords_slice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_mut_slice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1495 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1496 
         1497 &lt;p&gt;We get a mutable slice out of the whole array of coordinates.&lt;/p&gt;
         1498 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path_commands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1499 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_coordinates&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1500 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;packed_commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_packed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coords_slice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_mut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1501 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;coords_slice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords_slice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1502 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1503 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1504 
         1505 &lt;p&gt;For each command, we see how many coordinates it will generate and we
         1506 put that number in &lt;code&gt;n&lt;/code&gt;.  We get a mutable sub-slice from
         1507 &lt;code&gt;coords_slice&lt;/code&gt; with only that number of elements, and pass it to
         1508 &lt;code&gt;to_packed&lt;/code&gt; for each command.&lt;/p&gt;
         1509 &lt;p&gt;At the end of each iteration we move the mutable slice to where the
         1510 next command's coordinates will go.&lt;/p&gt;
         1511 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1512 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;commands&lt;/span&gt;: &lt;span class="nc"&gt;packed_commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;into_boxed_slice&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1513 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;: &lt;span class="nc"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;into_boxed_slice&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1514 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1515 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1516 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1517 
         1518 &lt;p&gt;At the end, we create the final and immutable &lt;code&gt;Path&lt;/code&gt; by converting
         1519 each array &lt;code&gt;into_boxed_slice&lt;/code&gt; like the last time.  That way each of
         1520 the two arrays, the one with &lt;code&gt;PackedCommand&lt;/code&gt;s and the one with
         1521 coordinates, occupy the minimum space they need.&lt;/p&gt;
         1522 &lt;h2&gt;An iterator for Path&lt;/h2&gt;
         1523 &lt;p&gt;This is all very well, but we also want it to be easy to iterate on
         1524 that compact representation; the &lt;code&gt;PathCommand&lt;/code&gt; enums from the
         1525 beginning are very convenient to use and that's what the rest of the
         1526 code already uses.  Let's make an iterator that unpacks what is inside
         1527 a &lt;code&gt;Path&lt;/code&gt; and produces a &lt;code&gt;PathCommand&lt;/code&gt; for each element.&lt;/p&gt;
         1528 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;PathIter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1529 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;commands&lt;/span&gt;: &lt;span class="nc"&gt;slice&lt;/span&gt;::&lt;span class="n"&gt;Iter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PackedCommand&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1530 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1531 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1532 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1533 
         1534 &lt;p&gt;We need an iterator over the array of &lt;code&gt;PackedCommand&lt;/code&gt; so we can visit
         1535 each command.  However, to get elements of &lt;code&gt;coords&lt;/code&gt;, I am going to
         1536 use a slice of &lt;code&gt;f64&lt;/code&gt; instead of an iterator.&lt;/p&gt;
         1537 &lt;p&gt;Let's look at the implementation of the iterator:&lt;/p&gt;
         1538 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Iterator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PathIter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1539 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1540 
         1541 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1542 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1543 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;::&lt;span class="n"&gt;from_packed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1544 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num_coords&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_coordinates&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1545 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;num_coords&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1546 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1547 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1548 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1549 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1550 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1551 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1552 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1553 
         1554 &lt;p&gt;Since we want each iteration to produce a &lt;code&gt;PathCommand&lt;/code&gt;, we declare it
         1555 as having the associated &lt;code&gt;type Item =  PathCommand&lt;/code&gt;.&lt;/p&gt;
         1556 &lt;p&gt;If the &lt;code&gt;self.commands&lt;/code&gt; iterator has another element, it means there is
         1557 another &lt;code&gt;PackedCommand&lt;/code&gt; available.&lt;/p&gt;
         1558 &lt;p&gt;We call &lt;code&gt;PathCommand::from_packed&lt;/code&gt; with the &lt;code&gt;self.coords&lt;/code&gt; slice to
         1559 unpack a command and its coordinates.  We see how many coordinates the
         1560 command consumed and re-slice &lt;code&gt;self.coords&lt;/code&gt; according to the number of
         1561 commands, so that it now points to the coordinates for the next
         1562 command.&lt;/p&gt;
         1563 &lt;p&gt;We return &lt;code&gt;Some(cmd)&lt;/code&gt; if there was an element, or &lt;code&gt;None&lt;/code&gt; if the
         1564 iterator is empty.&lt;/p&gt;
         1565 &lt;p&gt;The implementation of &lt;code&gt;from_packed&lt;/code&gt; is obvious and I'll just paste a
         1566 bit from it:&lt;/p&gt;
         1567 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1568 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_packed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packed&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;PackedCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;PathCommand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1569 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;packed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1570 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;PackedCommand&lt;/span&gt;::&lt;span class="n"&gt;MoveTo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1571 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1572 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1573 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;::&lt;span class="n"&gt;MoveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1574 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1575 
         1576 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;// etc. for the other variants in PackedCommand&lt;/span&gt;
         1577 
         1578 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;PackedCommand&lt;/span&gt;::&lt;span class="n"&gt;ArcSmallNegative&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;::&lt;span class="n"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EllipticalArc&lt;/span&gt;::&lt;span class="n"&gt;from_coords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1579 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;LargeArc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1580 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;Sweep&lt;/span&gt;::&lt;span class="n"&gt;Negative&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1581 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1582 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1583 
         1584 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;PackedCommand&lt;/span&gt;::&lt;span class="n"&gt;ArcSmallPositive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// etc.&lt;/span&gt;
         1585 
         1586 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;PackedCommand&lt;/span&gt;::&lt;span class="n"&gt;ArcLargeNegative&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// etc.&lt;/span&gt;
         1587 
         1588 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;PackedCommand&lt;/span&gt;::&lt;span class="n"&gt;ArcLargePositive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// etc.&lt;/span&gt;
         1589 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1590 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1591 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1592 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1593 
         1594 &lt;h2&gt;Results&lt;/h2&gt;
         1595 &lt;p&gt;Before the changes (this is the same Massif heading as above):&lt;/p&gt;
         1596 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         1597 &lt;span class="c"&gt;  n        time(i)         total(B)   useful&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;heap(B) extra&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;heap(B)    stacks(B)&lt;/span&gt;
         1598 &lt;span class="nb"&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         1599 &lt;span class="c"&gt; 33 24&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;139&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;598&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;653    1&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;416&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;831&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;176    1&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;329&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;943&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;212    86&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;887&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;964            0&lt;/span&gt;
         1600 &lt;span class="c"&gt;                                       ^^^^^^^^^^^^^&lt;/span&gt;
         1601 &lt;span class="c"&gt;                                           boo&lt;/span&gt;
         1602 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1603 
         1604 &lt;p&gt;After:&lt;/p&gt;
         1605 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         1606 &lt;span class="c"&gt;  n        time(i)         total(B)   useful&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;heap(B) extra&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;heap(B)    stacks(B)&lt;/span&gt;
         1607 &lt;span class="nb"&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         1608 &lt;span class="c"&gt; 28 26&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;611&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;886&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;993    1&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;093&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;747&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;888    1&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;023&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;147&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;907    70&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;599&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;981            0&lt;/span&gt;
         1609 &lt;span class="c"&gt;                                       ^^^^^^^^^^^^^&lt;/span&gt;
         1610 &lt;span class="c"&gt;                                          oh yeah&lt;/span&gt;
         1611 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1612 
         1613 &lt;p&gt;We went from using 1,329,943,212 bytes down to 1,023,147,907 bytes,
         1614 that is, we knocked it down by 300 MB.&lt;/p&gt;
         1615 &lt;p&gt;However, that is for the whole program.  Above we saw that &lt;code&gt;Path&lt;/code&gt; data
         1616 occupies 403,513,776 bytes; how about now?&lt;/p&gt;
         1617 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="mf"&gt;07.45&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;328&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mh"&gt;0x4A34C6F&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;alloc&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1618 &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="mf"&gt;07.45&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;328&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mh"&gt;0x4A34C6F&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;alloc&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;172&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1619 &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="mf"&gt;07.45&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;328&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mh"&gt;0x4A34C6F&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;allocate_in&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kr"&gt;Global&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;98&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1620 &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="mf"&gt;07.45&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;328&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mh"&gt;0x4A34C6F&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;with_capacity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;f64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;167&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1621 &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="mf"&gt;07.45&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;328&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mh"&gt;0x4A34C6F&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;with_capacity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;f64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;358&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1622 &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="mf"&gt;07.45&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;328&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mh"&gt;0x4A34C6F&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rsvg_internals&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;path_builder&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PathBuilder&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;into_path&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path_builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;486&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         1623 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1624 
         1625 &lt;p&gt;Perfect.  We went from occupying 403,513,776 bytes to just
         1626 81,525,328 bytes.  Instead of &lt;code&gt;Path&lt;/code&gt; data amounting to 28.48% of the
         1627 heap, it is just 7.45%.&lt;/p&gt;
         1628 &lt;p&gt;I think we can stop worrying about &lt;code&gt;Path&lt;/code&gt; data for now.  I like how
         1629 this turned out without having to use &lt;code&gt;unsafe&lt;/code&gt;.&lt;/p&gt;
         1630 &lt;h2&gt;References&lt;/h2&gt;
         1631 &lt;ul&gt;
         1632 &lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/commit/e9db621cdc79d31b8694d0f42cee4e02628ee145"&gt;Refactoring to use an iterator&lt;/a&gt;&lt;/li&gt;
         1633 &lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/commit/cb4cde7140cd6ecfd8a78483278dcb1ab8217612"&gt;Adding tests for Path/PathBuilder&lt;/a&gt;&lt;/li&gt;
         1634 &lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/commit/b183ac1e3207bd8110d60ded8878a22daed3f891"&gt;Using a more compact representation for Path&lt;/a&gt;&lt;/li&gt;
         1635 &lt;/ul&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category><category term="gnome"></category><category term="performance"></category></entry><entry><title>Reducing memory consumption in librsvg, part 3: slack space in Bézier paths</title><link href="https://people.gnome.org/~federico/blog/reducing-memory-consumption-in-librsvg-3.html" rel="alternate"></link><published>2020-03-24T17:14:55-06:00</published><updated>2020-03-24T17:14:55-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-03-24:/~federico/blog/reducing-memory-consumption-in-librsvg-3.html</id><summary type="html">&lt;p&gt;We got a &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/574"&gt;bug with a gigantic SVG&lt;/a&gt; of a map extracted from
         1636 OpenStreetMap, and it has about 600,000 elements.  Most of them are
         1637 &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt;, that is, specifications for Bézier paths.&lt;/p&gt;
         1638 &lt;p&gt;A &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt; can look like this:&lt;/p&gt;
         1639 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;m 2239.05,1890.28 5.3,-1.81&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         1640 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1641 
         1642 &lt;p&gt;The …&lt;/p&gt;</summary><content type="html">&lt;p&gt;We got a &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/574"&gt;bug with a gigantic SVG&lt;/a&gt; of a map extracted from
         1643 OpenStreetMap, and it has about 600,000 elements.  Most of them are
         1644 &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt;, that is, specifications for Bézier paths.&lt;/p&gt;
         1645 &lt;p&gt;A &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt; can look like this:&lt;/p&gt;
         1646 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;m 2239.05,1890.28 5.3,-1.81&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         1647 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1648 
         1649 &lt;p&gt;The &lt;code&gt;d&lt;/code&gt; attribute contains a &lt;a href="https://www.w3.org/TR/SVG2/paths.html#TheDProperty"&gt;list of commands&lt;/a&gt; to
         1650 create a Bézier path, very similar to PostScript's operators.  Librsvg
         1651 has the following to represent those commands:&lt;/p&gt;
         1652 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;PathCommand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1653 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;MoveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1654 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;LineTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1655 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;CurveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CubicBezierCurve&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1656 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EllipticalArc&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1657 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ClosePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1658 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1659 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1660 
         1661 &lt;p&gt;Those commands get stored in an array, a &lt;code&gt;Vec&lt;/code&gt; inside a &lt;code&gt;PathBuilder&lt;/code&gt;:&lt;/p&gt;
         1662 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;PathBuilder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1663 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;path_commands&lt;/span&gt;: &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1664 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1665 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1666 
         1667 &lt;p&gt;Librsvg translates each of the commands inside a &lt;code&gt;&amp;lt;path d="..."/&amp;gt;&lt;/code&gt;
         1668 into a &lt;code&gt;PathCommand&lt;/code&gt; and pushes it into the &lt;code&gt;Vec&lt;/code&gt; in the
         1669 &lt;code&gt;PathBuilder&lt;/code&gt;.  When it is done parsing the attribute, the
         1670 &lt;code&gt;PathBuilder&lt;/code&gt; remains as the final version of the path.&lt;/p&gt;
         1671 &lt;p&gt;To let a &lt;code&gt;Vec&lt;/code&gt; grow efficiently as items are pushed into
         1672 it, Rust makes the &lt;code&gt;Vec&lt;/code&gt; grow by powers of 2.  When we add an item, if
         1673 the &lt;em&gt;capacity&lt;/em&gt; of the &lt;code&gt;Vec&lt;/code&gt; is full, its buffer gets &lt;code&gt;realloc()&lt;/code&gt;ed to
         1674 twice its capacity.  That way there are only O(log₂n) calls to
         1675 &lt;code&gt;realloc()&lt;/code&gt;, where &lt;code&gt;n&lt;/code&gt; is the total number of items in the array.&lt;/p&gt;
         1676 &lt;p&gt;However, this means that once we are done adding items to the &lt;code&gt;Vec&lt;/code&gt;,
         1677 there may still be some free space in it:  &lt;em&gt;the capacity exceeds the
         1678 length of the array&lt;/em&gt;.  The invariant is that
         1679 &lt;code&gt;vec.capacity() &amp;gt;= vec.len()&lt;/code&gt;.&lt;/p&gt;
         1680 &lt;p&gt;First I wanted to shrink the &lt;code&gt;PathBuilder&lt;/code&gt;s so that they have no extra
         1681 capacity in the end.&lt;/p&gt;
         1682 &lt;h2&gt;First step: convert to Box&amp;lt;[T]&amp;gt;&lt;/h2&gt;
         1683 &lt;p&gt;A "boxed slice" is a contiguous array in the heap, that cannot grow or
         1684 shrink.  That is, it has no extra capacity, only a length.&lt;/p&gt;
         1685 &lt;p&gt;&lt;code&gt;Vec&lt;/code&gt; has a method &lt;a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.into_boxed_slice"&gt;&lt;code&gt;into_boxed_slice&lt;/code&gt;&lt;/a&gt; which does
         1686 eactly that:  it consumes the vector and converts it into a boxed
         1687 slice without extra capacity.  In its innards, it does a &lt;code&gt;realloc()&lt;/code&gt;
         1688 on the &lt;code&gt;Vec&lt;/code&gt;'s buffer to match its length.&lt;/p&gt;
         1689 &lt;p&gt;Let's see the numbers that Massif reports:&lt;/p&gt;
         1690 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         1691 &lt;span class="c"&gt;  n        time(i)         total(B)   useful&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;heap(B) extra&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;heap(B)    stacks(B)&lt;/span&gt;
         1692 &lt;span class="nb"&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         1693 &lt;span class="c"&gt; 23 22&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;751&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;613&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;855    1&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;560&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;916&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;408    1&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;493&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;746&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;540    67&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;169&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;868            0&lt;/span&gt;
         1694 &lt;span class="c"&gt;                                       ^^^^^^^^^^^^^&lt;/span&gt;
         1695 &lt;span class="c"&gt;                                           before&lt;/span&gt;
         1696 
         1697 &lt;span class="c"&gt; 30 22&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;796&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;106&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;012    1&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;553&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;581&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;072    1&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;329&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;943&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;324   223&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;637&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;748            0&lt;/span&gt;
         1698 &lt;span class="c"&gt;                                       ^^^^^^^^^^^^^&lt;/span&gt;
         1699 &lt;span class="c"&gt;                                           after&lt;/span&gt;
         1700 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1701 
         1702 &lt;p&gt;That is, we went from using 1,493,746,540 bytes on the heap to using
         1703 1,329,943,324 bytes.  Simply removing extra capacity from the path
         1704 commands saves about 159 MB for this particular file.&lt;/p&gt;
         1705 &lt;h2&gt;Second step: make the allocator do less work&lt;/h2&gt;
         1706 &lt;p&gt;However, the &lt;code&gt;extra-heap&lt;/code&gt; column in that table has a number I don't
         1707 like:  there are 223,637,748 bytes in &lt;code&gt;malloc()&lt;/code&gt; metadata and unused
         1708 space in the heap.&lt;/p&gt;
         1709 &lt;p&gt;I suppose that so many calls to &lt;code&gt;realloc()&lt;/code&gt; make the heap a bit
         1710 fragmented.&lt;/p&gt;
         1711 &lt;p&gt;It would be good to be able to read most of the &lt;code&gt;&amp;lt;path d="..."/&amp;gt;&lt;/code&gt; to
         1712 temporary buffers that don't need so many calls to &lt;code&gt;realloc()&lt;/code&gt;, and
         1713 that in the end get copied to exact-sized buffers, without extra
         1714 capacity.&lt;/p&gt;
         1715 &lt;p&gt;We can do just that with the &lt;a href="https://docs.rs/smallvec/1.2.0/smallvec/"&gt;smallvec&lt;/a&gt; crate.  A &lt;code&gt;SmallVec&lt;/code&gt; has the
         1716 same API as &lt;code&gt;Vec&lt;/code&gt;, but it can store small arrays directly in the
         1717 stack, without an extra heap allocation.  Once the capacity is full,
         1718 the stack buffer "spills" into a heap buffer automatically.&lt;/p&gt;
         1719 &lt;p&gt;Most of the &lt;code&gt;d&lt;/code&gt; attributes in the huge file in the &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/issues/574"&gt;bug&lt;/a&gt; have
         1720 fewer than 32 commands.  That is, if we use the following:&lt;/p&gt;
         1721 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;PathBuilder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1722 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;path_commands&lt;/span&gt;: &lt;span class="nc"&gt;SmallVec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1723 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1724 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1725 
         1726 &lt;p&gt;We are saying that there can be up to 32 items in the &lt;code&gt;SmallVec&lt;/code&gt;
         1727 without causing a heap allocation; once that is exceeded, it will work
         1728 like a normal &lt;code&gt;Vec&lt;/code&gt;.&lt;/p&gt;
         1729 &lt;p&gt;At the end we still do &lt;code&gt;into_boxed_slice&lt;/code&gt; to turn it into an
         1730 independent heap allocation with an exact size.&lt;/p&gt;
         1731 &lt;p&gt;This reduces the &lt;code&gt;extra-heap&lt;/code&gt; quite a bit:&lt;/p&gt;
         1732 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         1733 &lt;span class="c"&gt;  n        time(i)         total(B)   useful&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;heap(B) extra&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;heap(B)    stacks(B)&lt;/span&gt;
         1734 &lt;span class="nb"&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         1735 &lt;span class="c"&gt; 33 24&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;139&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;598&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;653    1&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;416&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;831&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;176    1&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;329&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;943&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;212    86&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;887&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt;964            0&lt;/span&gt;
         1736 &lt;span class="c"&gt;                                                        ^^^^^^^^^^&lt;/span&gt;
         1737 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1738 
         1739 &lt;p&gt;Also, the total bytes shrink from 1,553,581,072 to
         1740 1,416,831,176 — we have a smaller heap because there is not so much
         1741 work for the allocator, and there are a lot fewer temporary blocks
         1742 when parsing the &lt;code&gt;d&lt;/code&gt; attributes.&lt;/p&gt;
         1743 &lt;h2&gt;Making the code prettier&lt;/h2&gt;
         1744 &lt;p&gt;I put in the following:&lt;/p&gt;
         1745 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="sd"&gt;/// This one is mutable&lt;/span&gt;
         1746 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;PathBuilder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1747 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;path_commands&lt;/span&gt;: &lt;span class="nc"&gt;SmallVec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1748 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1749 
         1750 &lt;span class="sd"&gt;/// This one is immutable&lt;/span&gt;
         1751 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1752 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;path_commands&lt;/span&gt;: &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PathCommand&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1753 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1754 
         1755 &lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PathBuilder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1756 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;/// Consumes the PathBuilder and converts it into an immutable Path&lt;/span&gt;
         1757 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;into_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1758 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1759 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;path_commands&lt;/span&gt;: &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path_commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;into_boxed_slice&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1760 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1761 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1762 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1763 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1764 
         1765 &lt;p&gt;With that, &lt;code&gt;PathBuilder&lt;/code&gt; is just a temporary struct that turns into an
         1766 immutable &lt;code&gt;Path&lt;/code&gt; once we are done feeding it.  &lt;code&gt;Path&lt;/code&gt; contains a boxed
         1767 slice of the exact size, without any extra capacity.&lt;/p&gt;
         1768 &lt;h2&gt;Next steps&lt;/h2&gt;
         1769 &lt;p&gt;All the coordinates in librsvg are stored as &lt;code&gt;f64&lt;/code&gt;, double-precision
         1770 floating point numbers.  The SVG/CSS spec says that single-precision
         1771 floats are enough, and that 64-bit floats should be used only for
         1772 geometric transformations.&lt;/p&gt;
         1773 &lt;p&gt;I'm a bit scared to make that change; I'll have to look closely at the
         1774 results of the test suite to see if rendered files change very much.
         1775 I suppose even big maps require only as much precision as &lt;code&gt;f32&lt;/code&gt; —
         1776 after all, that is what OpenStreetMap uses.&lt;/p&gt;
         1777 &lt;h2&gt;References&lt;/h2&gt;
         1778 &lt;ul&gt;
         1779 &lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/commit/fc44abd1a8a85b7d8c474260e315cf4c73e4ac01"&gt;Convert the Vec into a
         1780   Box&amp;lt;[T]&amp;gt;&lt;/a&gt;&lt;/li&gt;
         1781 &lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/commit/ee63041d012406a9b05204ef604eb5411a8cf7ae"&gt;Convert to SmallVec&lt;/a&gt;&lt;/li&gt;
         1782 &lt;/ul&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category><category term="gnome"></category><category term="performance"></category></entry><entry><title>Reducing memory consumption in librsvg, part 2: SpecifiedValues</title><link href="https://people.gnome.org/~federico/blog/reducing-memory-consumption-in-librsvg-2.html" rel="alternate"></link><published>2020-03-20T14:29:16-06:00</published><updated>2020-03-20T14:29:16-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-03-20:/~federico/blog/reducing-memory-consumption-in-librsvg-2.html</id><summary type="html">&lt;p&gt;To continue with &lt;a href="https://people.gnome.org/~federico/blog/reducing-memory-consumption-in-librsvg-1-es.html"&gt;last time's topic&lt;/a&gt;, let's see how to make
         1783 librsvg's DOM nodes smaller in memory.  Since that time, there have
         1784 been some changes to the code; that is why in this post some of the
         1785 type names are different from last time's.&lt;/p&gt;
         1786 &lt;p&gt;Every SVG element is represented with …&lt;/p&gt;</summary><content type="html">&lt;p&gt;To continue with &lt;a href="https://people.gnome.org/~federico/blog/reducing-memory-consumption-in-librsvg-1-es.html"&gt;last time's topic&lt;/a&gt;, let's see how to make
         1787 librsvg's DOM nodes smaller in memory.  Since that time, there have
         1788 been some changes to the code; that is why in this post some of the
         1789 type names are different from last time's.&lt;/p&gt;
         1790 &lt;p&gt;Every SVG element is represented with this struct:&lt;/p&gt;
         1791 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1792 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;element_type&lt;/span&gt;: &lt;span class="nc"&gt;ElementType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1793 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;element_name&lt;/span&gt;: &lt;span class="nc"&gt;QualName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1794 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;: &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1795 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;: &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1796 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;specified_values&lt;/span&gt;: &lt;span class="nc"&gt;SpecifiedValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1797 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;important_styles&lt;/span&gt;: &lt;span class="nc"&gt;HashSet&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;QualName&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1798 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;: &lt;span class="nc"&gt;ElementResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1799 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;: &lt;span class="nc"&gt;Transform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1800 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;: &lt;span class="nc"&gt;ComputedValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1801 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1802 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;style_attr&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1803 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;element_impl&lt;/span&gt;: &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ElementTrait&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1804 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1805 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1806 
         1807 &lt;p&gt;The two biggest fields are the ones with types &lt;code&gt;SpecifiedValues&lt;/code&gt; and
         1808 &lt;code&gt;ComputedValues&lt;/code&gt;.  These are the sizes of the whole &lt;code&gt;Element&lt;/code&gt; struct
         1809 and those two types:&lt;/p&gt;
         1810 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sizeof Element: 1808
         1811 sizeof SpecifiedValues: 824
         1812 sizeof ComputedValues: 704
         1813 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1814 
         1815 &lt;p&gt;In this post, we'll reduce the size of &lt;code&gt;SpecifiedValues&lt;/code&gt;.&lt;/p&gt;
         1816 &lt;h2&gt;What is SpecifiedValues?&lt;/h2&gt;
         1817 &lt;p&gt;If we have an element like this:&lt;/p&gt;
         1818 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;circle&lt;/span&gt; &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;r=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;stroke-width=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;blue&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         1819 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1820 
         1821 &lt;p&gt;The values of the style properties &lt;code&gt;stroke-width&lt;/code&gt; and &lt;code&gt;stroke&lt;/code&gt; get
         1822 stored in a &lt;code&gt;SpecifiedValues&lt;/code&gt; struct.  This struct has a bunch of
         1823 fields, one for each possible style property:&lt;/p&gt;
         1824 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;SpecifiedValues&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1825 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;baseline_shift&lt;/span&gt;:              &lt;span class="nc"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BaselineShift&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1826 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;clip_path&lt;/span&gt;:                   &lt;span class="nc"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ClipPath&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1827 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;clip_rule&lt;/span&gt;:                   &lt;span class="nc"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ClipRule&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1828 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;/// ...&lt;/span&gt;
         1829 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;stroke&lt;/span&gt;:                      &lt;span class="nc"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Stroke&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1830 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;stroke_width&lt;/span&gt;:                &lt;span class="nc"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;StrokeWidth&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1831 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;/// ...&lt;/span&gt;
         1832 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1833 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1834 
         1835 &lt;p&gt;Each field is a &lt;code&gt;SpecifiedValue&amp;lt;T&amp;gt;&lt;/code&gt; for the following reason.  In
         1836 CSS/SVG, a style property can be unspecified, or it can have an
         1837 &lt;code&gt;inherit&lt;/code&gt; value to force the property to be copied from the element's
         1838 parent, or it can actually have a specified value.  Librsvg represents
         1839 these as follows:&lt;/p&gt;
         1840 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1841 &lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1842 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;: &lt;span class="c1"&gt;// some trait bounds here&lt;/span&gt;
         1843 &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1844 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Unspecified&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1845 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Inherit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1846 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Specified&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1847 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1848 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1849 
         1850 &lt;p&gt;Now, &lt;code&gt;SpecifiedValues&lt;/code&gt; has a bunch of fields, 47 of them to be exact —
         1851 one for each of the style properties that librsvg supports.  That is
         1852 why &lt;code&gt;SpecifiedValues&lt;/code&gt; has a size of 824 bytes; it is the largest
         1853 sub-structure within &lt;code&gt;Element&lt;/code&gt;, and it would be good to reduce its
         1854 size.&lt;/p&gt;
         1855 &lt;h2&gt;Not all properties are specified&lt;/h2&gt;
         1856 &lt;p&gt;Let's go back to the chunk of SVG from above:&lt;/p&gt;
         1857 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;circle&lt;/span&gt; &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;r=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;stroke-width=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;blue&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         1858 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1859 
         1860 &lt;p&gt;Here we only have two specified properties, so the &lt;code&gt;stroke_width&lt;/code&gt; and
         1861 &lt;code&gt;stroke&lt;/code&gt; fields of &lt;code&gt;SpecifiedValues&lt;/code&gt; will be set as
         1862 &lt;code&gt;SpecifiedValue::Specified(something)&lt;/code&gt; and all the other fields will
         1863 be left as &lt;code&gt;SpecifiedValue::Unspecified&lt;/code&gt;.&lt;/p&gt;
         1864 &lt;p&gt;It would be good to store only complete values for the properties that
         1865 are specified, and just a small flag for unset properties.&lt;/p&gt;
         1866 &lt;h2&gt;Another way to represent the set of properties&lt;/h2&gt;
         1867 &lt;p&gt;Since there is a maximum of 47 properties per element (or more if
         1868 librsvg adds support for extra ones), we can have a small array of
         1869 47 bytes.  Each byte contains the index within another array that
         1870 contains only the values of specified properties, or a sentinel value
         1871 for properties that are unset.&lt;/p&gt;
         1872 &lt;p&gt;First, I made an enum that fits in a &lt;code&gt;u8&lt;/code&gt; for all the properties, plus
         1873 the sentinel value, which also gives us the total number of
         1874 properties.  The &lt;code&gt;#[repr(u8)]&lt;/code&gt; guarantees that this enum fits in a
         1875 byte.&lt;/p&gt;
         1876 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[repr(u8)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1877 &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;PropertyId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1878 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;BaselineShift&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1879 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ClipPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1880 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ClipRule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1881 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1882 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
         1883 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;WritingMode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1884 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;XmlLang&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1885 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;XmlSpace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1886 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;UnsetProperty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// the number of properties and also the sentinel value&lt;/span&gt;
         1887 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1888 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1889 
         1890 &lt;p&gt;Also, since before these changes there was the following monster to
         1891 represent "which property is this" plus the property's value:&lt;/p&gt;
         1892 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;ParsedProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1893 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;BaselineShift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BaselineShift&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1894 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ClipPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ClipPath&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1895 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ClipRule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ClipRule&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1896 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1897 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
         1898 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1899 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1900 
         1901 &lt;p&gt;I changed the definition of &lt;code&gt;SpecifiedValues&lt;/code&gt; to have two arrays, one
         1902 to store which properties are specified, and another only with the
         1903 values for the properties that are actually specified:&lt;/p&gt;
         1904 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;SpecifiedValues&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1905 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;indices&lt;/span&gt;: &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PropertyId&lt;/span&gt;::&lt;span class="n"&gt;UnsetProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1906 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;: &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ParsedProperty&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1907 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1908 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1909 
         1910 &lt;p&gt;There is a thing that is awkward in Rust, or which I haven't found how
         1911 to solve in a nicer way:  given a &lt;code&gt;ParsedProperty&lt;/code&gt;, find the
         1912 corresponding &lt;code&gt;PropertyId&lt;/code&gt; for its discriminant.  I did the obvious
         1913 thing:&lt;/p&gt;
         1914 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParsedProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1915 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_property_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;PropertyId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1916 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParsedProperty&lt;/span&gt;::&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1917 
         1918 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1919 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;BaselineShift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PropertyId&lt;/span&gt;::&lt;span class="n"&gt;BaselineShift&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1920 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;ClipPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PropertyId&lt;/span&gt;::&lt;span class="n"&gt;ClipPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1921 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;ClipRule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PropertyId&lt;/span&gt;::&lt;span class="n"&gt;ClipRule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1922 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PropertyId&lt;/span&gt;::&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1923 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
         1924 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1925 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1926 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1927 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1928 
         1929 &lt;h2&gt;Initialization&lt;/h2&gt;
         1930 &lt;p&gt;First, we want to initialize an empty &lt;code&gt;SpecifiedValues&lt;/code&gt;, where every
         1931 element of the the &lt;code&gt;indices&lt;/code&gt; array is set to the sentinel value that
         1932 means that the corresponding property is not set:&lt;/p&gt;
         1933 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SpecifiedValues&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1934 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Self&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1935 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;SpecifiedValues&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1936 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;indices&lt;/span&gt;: &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PropertyId&lt;/span&gt;::&lt;span class="n"&gt;UnsetProperty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_u8&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PropertyId&lt;/span&gt;::&lt;span class="n"&gt;UnsetProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1937 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;: &lt;span class="nb"&gt;Vec&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1938 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1939 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1940 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1941 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1942 
         1943 &lt;p&gt;That sets the &lt;code&gt;indices&lt;/code&gt; field to an array full of the same
         1944 &lt;code&gt;PropertyId::UnsetProperty&lt;/code&gt; sentinel value.  Also, the &lt;code&gt;props&lt;/code&gt; array
         1945 is empty; it hasn't even had a block of memory allocated for it yet.
         1946 That way, SVG elements without style properties don't use any extra
         1947 memory.&lt;/p&gt;
         1948 &lt;h2&gt;Which properties are specified and what are their indices?&lt;/h2&gt;
         1949 &lt;p&gt;Second, we want a function that will give us the index in &lt;code&gt;props&lt;/code&gt; for
         1950 some property, or that will tell us if the property has not been set
         1951 yet:&lt;/p&gt;
         1952 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SpecifiedValues&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1953 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;property_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;: &lt;span class="nc"&gt;PropertyId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1954 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_usize&lt;/span&gt;&lt;span class="p"&gt;()];&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1955 
         1956 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PropertyId&lt;/span&gt;::&lt;span class="n"&gt;UnsetProperty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_u8&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1957 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1958 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1959 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1960 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1961 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1962 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1963 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1964 
         1965 &lt;p&gt;(If someone passes &lt;code&gt;id = PropertyId::UnsetProperty&lt;/code&gt;, the array access
         1966 to &lt;code&gt;indices&lt;/code&gt; will panic, which is what we want, since &lt;em&gt;that&lt;/em&gt; is not a
         1967 valid property id.)&lt;/p&gt;
         1968 &lt;h2&gt;Change a property's value&lt;/h2&gt;
         1969 &lt;p&gt;Third, we want to set the value of a property that has not been set,
         1970 or change the value of one that was already specified:&lt;/p&gt;
         1971 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SpecifiedValues&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1972 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;replace_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prop&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;ParsedProperty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1973 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_property_id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1974 
         1975 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;property_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1976 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1977 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1978 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1979 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1980 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_usize&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1981 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1982 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1983 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         1984 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1985 
         1986 &lt;p&gt;In the first case in the &lt;code&gt;if&lt;/code&gt;, the property was already set and we
         1987 just replace its value.  In the second case, the property was not set;
         1988 we add it to the &lt;code&gt;props&lt;/code&gt; array and store its resulting index in
         1989 &lt;code&gt;indices&lt;/code&gt;.&lt;/p&gt;
         1990 &lt;h2&gt;Results&lt;/h2&gt;
         1991 &lt;p&gt;Before:&lt;/p&gt;
         1992 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sizeof Element: 1808
         1993 sizeof SpecifiedValues: 824
         1994 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         1995 
         1996 &lt;p&gt;After:&lt;/p&gt;
         1997 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sizeof Element: 1056
         1998 sizeof SpecifiedValues: 72
         1999 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2000 
         2001 &lt;p&gt;The pathological file &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/42"&gt;from the last time&lt;/a&gt; used
         2002 463,412,720 bytes in memory before these changes.  After the changes,
         2003 it uses 314,526,136 bytes.&lt;/p&gt;
         2004 &lt;p&gt;I also measured memory consumption for a normal file, in this case
         2005 &lt;a href="https://gitlab.gnome.org/Teams/Design/icon-development-kit/-/blob/master/src/icons.svg"&gt;one with a bunch of GNOME's symbolic icons&lt;/a&gt;.  The old version
         2006 uses 17 MB; the new version only 13 MB.&lt;/p&gt;
         2007 &lt;h2&gt;How to keep fine-tuning this&lt;/h2&gt;
         2008 &lt;p&gt;For now, I am satisfied with &lt;code&gt;SpecifiedValues&lt;/code&gt;, although it could
         2009 still be made smaller:&lt;/p&gt;
         2010 &lt;ul&gt;
         2011 &lt;li&gt;
         2012 &lt;p&gt;The crate &lt;a href="https://lib.rs/crates/tagged-box"&gt;tagged-box&lt;/a&gt; converts an enum like &lt;code&gt;ParsedProperty&lt;/code&gt; into
         2013   an enum-of-boxes, and codifies the enum's discriminant into the
         2014   box's pointer.  This way each variant occupies the minimum possible
         2015   memory, although in a separately-allocated block, and the container
         2016   itself uses only a pointer.  I am not sure if this is worth it; each
         2017   &lt;code&gt;ParsedProperty&lt;/code&gt; is 64 bytes, but the flat array &lt;code&gt;props:
         2018   Vec&amp;lt;ParsedProperty&amp;gt;&lt;/code&gt; is very appealing in a single block of memory.
         2019   I have not checked the sizes of each individual property to see if
         2020   they vary a lot among them.&lt;/p&gt;
         2021 &lt;/li&gt;
         2022 &lt;li&gt;
         2023 &lt;p&gt;Look for a crate that lets us have the properties in a single memory
         2024   block, a kind of arena with variable types.  This can be implemented
         2025   with a bit of &lt;code&gt;unsafe&lt;/code&gt;, but one has to be careful with the alignment
         2026   of different types.&lt;/p&gt;
         2027 &lt;/li&gt;
         2028 &lt;li&gt;
         2029 &lt;p&gt;The crate &lt;a href="https://lib.rs/crates/enum_set2"&gt;enum_set2&lt;/a&gt; represents an array of field-less enums as a
         2030   compact bit array.  If we changed the representation of
         2031   &lt;code&gt;SpecifiedValue&lt;/code&gt;, this would reduce the &lt;code&gt;indices&lt;/code&gt; array to a
         2032   minimum.&lt;/p&gt;
         2033 &lt;/li&gt;
         2034 &lt;/ul&gt;
         2035 &lt;p&gt;If someone wants to dedicate some time to implement and measure this,
         2036 I would be very grateful.&lt;/p&gt;
         2037 &lt;h2&gt;Next steps&lt;/h2&gt;
         2038 &lt;p&gt;According to Massif, the next thing is to keep making &lt;code&gt;Element&lt;/code&gt; 
         2039 smaller.  The next thing to shrink is &lt;code&gt;ComputedValues&lt;/code&gt;.  The obvious
         2040 route is to do exactly the same as I did for &lt;code&gt;SpecifiedValues&lt;/code&gt;.  I am
         2041 not sure if it would be better to try to &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/570"&gt;share the style
         2042 structs&lt;/a&gt; between elements.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category><category term="gnome"></category><category term="performance"></category></entry><entry><title>Librsvg accepting interns for Summer of Code 2020</title><link href="https://people.gnome.org/~federico/blog/librsvg-soc-2020.html" rel="alternate"></link><published>2020-03-16T17:53:17-06:00</published><updated>2020-03-16T17:53:17-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-03-16:/~federico/blog/librsvg-soc-2020.html</id><summary type="html">&lt;p&gt;Are you a student qualified to run for Summer of Code 2020?  I'm
         2043 willing to mentor the following project for librsvg.&lt;/p&gt;
         2044 &lt;h2&gt;Project: Revamp the text engine in librsvg&lt;/h2&gt;
         2045 &lt;p&gt;Librsvg supports only a few features of the &lt;a href="https://www.w3.org/TR/SVG2/text.html"&gt;SVG Text
         2046 specification&lt;/a&gt;. It requires
         2047 extra features to be really useful:&lt;/p&gt;
         2048 &lt;ul&gt;
         2049 &lt;li&gt;
         2050 &lt;p&gt;&lt;strong&gt;Proper bidirectional support …&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Are you a student qualified to run for Summer of Code 2020?  I'm
         2051 willing to mentor the following project for librsvg.&lt;/p&gt;
         2052 &lt;h2&gt;Project: Revamp the text engine in librsvg&lt;/h2&gt;
         2053 &lt;p&gt;Librsvg supports only a few features of the &lt;a href="https://www.w3.org/TR/SVG2/text.html"&gt;SVG Text
         2054 specification&lt;/a&gt;. It requires
         2055 extra features to be really useful:&lt;/p&gt;
         2056 &lt;ul&gt;
         2057 &lt;li&gt;
         2058 &lt;p&gt;&lt;strong&gt;Proper bidirectional support.&lt;/strong&gt;  Librsvg supports the &lt;code&gt;direction&lt;/code&gt; and
         2059 &lt;code&gt;unicode-bidi&lt;/code&gt; properties for text elements, among others, but in a
         2060 very rudimentary fashion.  It just translates those properties to
         2061 Pango terminology and asks &lt;code&gt;PangoLayout&lt;/code&gt; to lay out the text.  SVG
         2062 really wants finer control of that, for which...&lt;/p&gt;
         2063 &lt;/li&gt;
         2064 &lt;li&gt;
         2065 &lt;p&gt;... ideally you would make librsvg &lt;strong&gt;use Harfbuzz directly&lt;/strong&gt;, or a
         2066 wrapper that is close to its level of operation.  Pango is a bit too high
         2067 level for the needs of SVG.&lt;/p&gt;
         2068 &lt;/li&gt;
         2069 &lt;li&gt;
         2070 &lt;p&gt;Manual layout of text glyphs.  After a text engine like Harfbuzz
         2071 does the shaping, librsvg would need to lay out the produced glyphs in
         2072 the way of the SVG attributes &lt;code&gt;dx, dy, x, y&lt;/code&gt;, etc.  The SVG Text
         2073 specification has the algorithms for this.&lt;/p&gt;
         2074 &lt;/li&gt;
         2075 &lt;li&gt;
         2076 &lt;p&gt;The cherry on top: text-on-a-path.  Again, the spec has the details.
         2077 You would make Wikimedia content creators very happy with this!&lt;/p&gt;
         2078 &lt;/li&gt;
         2079 &lt;/ul&gt;
         2080 &lt;p&gt;&lt;strong&gt;Requirements:&lt;/strong&gt; Rust for programming language; some familiarity with
         2081 Unicode concepts and text layout.  Familiarity with Cairo and Harfbuzz
         2082 would help a lot.  Preference will be given to people who can write a
         2083 right-to-left human language, &lt;strong&gt;or&lt;/strong&gt; a language that requires complex
         2084 shaping.&lt;/p&gt;
         2085 &lt;p&gt;&lt;a href="https://wiki.gnome.org/Outreach/SummerOfCode/Students"&gt;Details for students&lt;/a&gt;&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="mentoring"></category><category term="gnome"></category></entry><entry><title>Reducing memory consumption in librsvg, part 1: text nodes</title><link href="https://people.gnome.org/~federico/blog/reducing-memory-consumption-in-librsvg-1.html" rel="alternate"></link><published>2020-03-12T18:57:35-06:00</published><updated>2020-03-12T18:57:35-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-03-12:/~federico/blog/reducing-memory-consumption-in-librsvg-1.html</id><summary type="html">&lt;p&gt;Librsvg's memory consumption has not been a problem so far for GNOME's
         2086 use cases, which is basically rendering icons.  But for SVG files with
         2087 thousands of elements, it could do a lot better.&lt;/p&gt;
         2088 &lt;h2&gt;Memory consumption in the DOM&lt;/h2&gt;
         2089 &lt;p&gt;Librsvg shares some common problems with web browsers:  it must
         2090 construct a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Librsvg's memory consumption has not been a problem so far for GNOME's
         2091 use cases, which is basically rendering icons.  But for SVG files with
         2092 thousands of elements, it could do a lot better.&lt;/p&gt;
         2093 &lt;h2&gt;Memory consumption in the DOM&lt;/h2&gt;
         2094 &lt;p&gt;Librsvg shares some common problems with web browsers:  it must
         2095 construct a DOM tree in memory with SVG elements, and keep a bunch of
         2096 information for each of the tree's nodes.  For example, each SVG
         2097 element may have an &lt;code&gt;id&lt;/code&gt; attribute, or a &lt;code&gt;class&lt;/code&gt;; each one has a
         2098 transformation matrix; etc.&lt;/p&gt;
         2099 &lt;p&gt;Apart from the tree node metadata (pointers to sibling and parent
         2100 nodes), each node has this:&lt;/p&gt;
         2101 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="sd"&gt;/// Contents of a tree node&lt;/span&gt;
         2102 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;NodeData&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2103 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;node_type&lt;/span&gt;: &lt;span class="nc"&gt;NodeType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2104 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;element_name&lt;/span&gt;: &lt;span class="nc"&gt;QualName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2105 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;: &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// id attribute from XML element&lt;/span&gt;
         2106 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;: &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// class attribute from XML element&lt;/span&gt;
         2107 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;specified_values&lt;/span&gt;: &lt;span class="nc"&gt;SpecifiedValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2108 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;important_styles&lt;/span&gt;: &lt;span class="nc"&gt;HashSet&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;QualName&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2109 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;: &lt;span class="nc"&gt;NodeResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2110 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;: &lt;span class="nc"&gt;Transform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2111 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;: &lt;span class="nc"&gt;ComputedValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2112 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2113 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;style_attr&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2114 
         2115 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;node_impl&lt;/span&gt;: &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;NodeTrait&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// concrete struct for node types&lt;/span&gt;
         2116 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2117 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2118 
         2119 &lt;p&gt;On a 64-bit box, that &lt;code&gt;NodeData&lt;/code&gt; struct is 1808 bytes.  And the biggest fields
         2120 are the &lt;code&gt;SpecifiedValues&lt;/code&gt; (824 bytes) and &lt;code&gt;ComputedValues&lt;/code&gt; (704 bytes).&lt;/p&gt;
         2121 &lt;p&gt;Librsvg represents &lt;em&gt;all&lt;/em&gt; tree nodes with that struct.  Consider an SVG
         2122 like this:&lt;/p&gt;
         2123 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.w3.org/2000/svg&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;100&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;100&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         2124   &lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;20&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         2125   &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;...&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         2126   &lt;span class="nt"&gt;&amp;lt;text&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;20&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Hello&lt;span class="nt"&gt;&amp;lt;/text&amp;gt;&lt;/span&gt;
         2127   &lt;span class="c"&gt;&amp;lt;!-- etc --&amp;gt;&lt;/span&gt;
         2128 &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
         2129 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2130 
         2131 &lt;p&gt;There are 4 elements in that file.  However, there are also tree nodes
         2132 for the XML text nodes, that is, the whitespace between tags and the
         2133 "&lt;code&gt;Hello&lt;/code&gt;" inside the &lt;code&gt;&amp;lt;text&amp;gt;&lt;/code&gt; element.&lt;/p&gt;
         2134 &lt;p&gt;The contents of each of those text nodes is tiny (a newline and maybe
         2135 a couple of spaces), but each node still takes up at least 1808 bytes
         2136 from the &lt;code&gt;NodeData&lt;/code&gt; struct, plus the size of the text string.&lt;/p&gt;
         2137 &lt;p&gt;Let's refactor this to make it easier to remove that overhead.&lt;/p&gt;
         2138 &lt;h2&gt;First step: separate text nodes from element nodes&lt;/h2&gt;
         2139 &lt;p&gt;Internally, librsvg represents XML text nodes with a &lt;code&gt;NodeChars&lt;/code&gt; struct
         2140 which is basically a string with some extra stuff.  All the concrete
         2141 structs for tree node types must implement a trait called &lt;code&gt;NodeTrait&lt;/code&gt;,
         2142 and &lt;code&gt;NodeChars&lt;/code&gt; is no exception:&lt;/p&gt;
         2143 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;NodeChars&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2144 &lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// a string with the text node&amp;#39;s contents&lt;/span&gt;
         2145 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2146 
         2147 &lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;NodeTrait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;NodeChars&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2148 &lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// a mostly empty impl with methods that do nothing&lt;/span&gt;
         2149 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2150 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2151 
         2152 &lt;p&gt;You don't see it in the definition of &lt;code&gt;NodeData&lt;/code&gt; in the previous
         2153 section, but for a text node, the &lt;code&gt;NodeData.node_impl&lt;/code&gt; field would
         2154 point to a heap-allocated &lt;code&gt;NodeChars&lt;/code&gt; (it can do that, since
         2155 &lt;code&gt;NodeChars&lt;/code&gt; implements &lt;code&gt;NodeTrait&lt;/code&gt;, so it can go into &lt;code&gt;node_impl:
         2156 Box&amp;lt;dyn NodeTrait&amp;gt;&lt;/code&gt;).&lt;/p&gt;
         2157 &lt;p&gt;First, I turned the &lt;code&gt;NodeData&lt;/code&gt; struct into an enum with two variants,
         2158 and moved all of its previous fields to an &lt;code&gt;Element&lt;/code&gt; struct:&lt;/p&gt;
         2159 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// This one is new&lt;/span&gt;
         2160 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;NodeData&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2161 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2162 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NodeChars&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2163 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2164 
         2165 &lt;span class="c1"&gt;// This is the old struct with a different name&lt;/span&gt;
         2166 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2167 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;node_type&lt;/span&gt;: &lt;span class="nc"&gt;NodeType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2168 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;element_name&lt;/span&gt;: &lt;span class="nc"&gt;QualName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2169 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;: &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2170 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;: &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2171 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;specified_values&lt;/span&gt;: &lt;span class="nc"&gt;SpecifiedValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2172 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;important_styles&lt;/span&gt;: &lt;span class="nc"&gt;HashSet&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;QualName&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2173 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;: &lt;span class="nc"&gt;NodeResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2174 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;: &lt;span class="nc"&gt;Transform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2175 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;: &lt;span class="nc"&gt;ComputedValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2176 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2177 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;style_attr&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2178 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;node_impl&lt;/span&gt;: &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;NodeTrait&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2179 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2180 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2181 
         2182 &lt;p&gt;The size of a Rust enum is the maximum of the sizes of its variants,
         2183 plus a little extra for the discriminant (you can think of a C struct
         2184 with an int for the discriminant, and a union of variants).&lt;/p&gt;
         2185 &lt;p&gt;The code &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/commit/741a0c0bb4c9bc5dc4b246a92d9ba2e26275d45d"&gt;needed a few
         2186 changes&lt;/a&gt;
         2187 to split &lt;code&gt;NodeData&lt;/code&gt; in this way, by adding accessor
         2188 functions to each of the &lt;code&gt;Element&lt;/code&gt; or &lt;code&gt;Text&lt;/code&gt; cases conveniently.  This
         2189 is one of those refactors where you can just change the declaration,
         2190 and walk down the compiler's errors to make each case use the accesors
         2191 instead of whatever was done before.&lt;/p&gt;
         2192 &lt;h2&gt;Second step: move the Element variant to a separate allocation&lt;/h2&gt;
         2193 &lt;p&gt;Now, &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/commit/8312bc00b6a4abbac82fef0596fb25cad3a56eaf"&gt;we turn &lt;code&gt;NodeData&lt;/code&gt; into
         2194 this&lt;/a&gt;:&lt;/p&gt;
         2195 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;NodeData&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2196 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// This goes inside a Box&lt;/span&gt;
         2197 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NodeChars&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2198 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2199 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2200 
         2201 &lt;p&gt;That way, the &lt;code&gt;Element&lt;/code&gt; variant is the size of a pointer (i.e. a
         2202 pointer to the heap-allocated &lt;code&gt;Box&lt;/code&gt;), and the &lt;code&gt;Text&lt;/code&gt; variant is as big
         2203 as &lt;code&gt;NodeChars&lt;/code&gt; as usual.&lt;/p&gt;
         2204 &lt;p&gt;This means that &lt;code&gt;Element&lt;/code&gt; nodes are just as big as before, plus an
         2205 extra pointer, plus an extra heap allocation.&lt;/p&gt;
         2206 &lt;p&gt;However, the &lt;code&gt;Text&lt;/code&gt; nodes get a lot smaller!&lt;/p&gt;
         2207 &lt;ul&gt;
         2208 &lt;li&gt;Before: &lt;code&gt;sizeof::&amp;lt;NodeData&amp;gt;() = 1808&lt;/code&gt;&lt;/li&gt;
         2209 &lt;li&gt;After: &lt;code&gt;sizeof::&amp;lt;NodeData&amp;gt;() = 72&lt;/code&gt;&lt;/li&gt;
         2210 &lt;/ul&gt;
         2211 &lt;p&gt;By making the &lt;code&gt;Element&lt;/code&gt; variant a lot smaller (the size of a &lt;code&gt;Box&lt;/code&gt;,
         2212 which is just a pointer), it has no extra overhead on the &lt;code&gt;Text&lt;/code&gt;
         2213 variant.&lt;/p&gt;
         2214 &lt;p&gt;This means that in the SVG file, all the whitespace between XML
         2215 elements now takes a lot less memory.&lt;/p&gt;
         2216 &lt;h2&gt;Some numbers from a pathological file&lt;/h2&gt;
         2217 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/42"&gt;Issue 42&lt;/a&gt; is about
         2218 an SVG file that is just a &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; element repeated many times, once
         2219 per line:&lt;/p&gt;
         2220 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.w3.org/2000/svg&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         2221   &lt;span class="nt"&gt;&amp;lt;defs&amp;gt;&lt;/span&gt;
         2222     &lt;span class="nt"&gt;&amp;lt;symbol&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;glyph0-0&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         2223       &lt;span class="c"&gt;&amp;lt;!-- a few elements here --&amp;gt;&lt;/span&gt;
         2224     &lt;span class="nt"&gt;&amp;lt;/symbol&amp;gt;&lt;/span&gt;
         2225   &lt;span class="nt"&gt;&amp;lt;/defs&amp;gt;&lt;/span&gt;
         2226 
         2227   &lt;span class="nt"&gt;&amp;lt;use&lt;/span&gt; &lt;span class="na"&gt;xlink:href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#glyph0-0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         2228   &lt;span class="nt"&gt;&amp;lt;use&lt;/span&gt; &lt;span class="na"&gt;xlink:href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#glyph0-0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         2229   &lt;span class="nt"&gt;&amp;lt;use&lt;/span&gt; &lt;span class="na"&gt;xlink:href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#glyph0-0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         2230   &lt;span class="c"&gt;&amp;lt;!-- about 196,000 similar lines --&amp;gt;&lt;/span&gt;
         2231 &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
         2232 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2233 
         2234 &lt;p&gt;So we have around 196,000 elements.  According to &lt;a href="https://valgrind.org/docs/manual/ms-manual.html"&gt;Valgrind's Massif
         2235 tool&lt;/a&gt;, this makes &lt;code&gt;rsvg-convert&lt;/code&gt; allocate 800,501,568 bytes in the
         2236 old version, versus 463,412,720 bytes in the new version, or about 60%
         2237 of the space.&lt;/p&gt;
         2238 &lt;h2&gt;Next steps&lt;/h2&gt;
         2239 &lt;p&gt;There is a lot of repetition in the text nodes of a typical SVG file.
         2240 For example, in that pathological file above, most of the whitespace is
         2241 identical: between each element there is a newline and two spaces.
         2242 Instead of having thousands of little allocations, all with the same
         2243 string, there could be a pool of shared strings.  Files with "real"
         2244 indentation could get benefits from sharing the whitespace-only text
         2245 nodes.&lt;/p&gt;
         2246 &lt;p&gt;Real browser engines are very careful to share the style structs
         2247 across elements if possible.  Look for "style struct sharing" in
         2248 &lt;a href="https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-engine-quantum-css-aka-stylo/"&gt;"Inside a super fast CSS engine: Quantum CSS"&lt;/a&gt;.  This is
         2249 going to take some good work in librsvg, but we can get there
         2250 gradually.&lt;/p&gt;
         2251 &lt;h2&gt;References&lt;/h2&gt;
         2252 &lt;ul&gt;
         2253 &lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/302/commits"&gt;Commits for the whole
         2254   refactoring&lt;/a&gt;&lt;/li&gt;
         2255 &lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/commit/741a0c0bb4c9bc5dc4b246a92d9ba2e26275d45d"&gt;Turn the NodeData struct into an enum with variants for Element and
         2256   Text&lt;/a&gt;&lt;/li&gt;
         2257 &lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/commit/8312bc00b6a4abbac82fef0596fb25cad3a56eaf"&gt;Box the Element variant to make Text nodes
         2258   smaller&lt;/a&gt;.
         2259   The commit message has parts of the massif log with all the
         2260   interesting numbers.&lt;/li&gt;
         2261 &lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/528"&gt;Tracker bug for memory
         2262   consumption&lt;/a&gt;&lt;/li&gt;
         2263 &lt;/ul&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category><category term="gnome"></category><category term="performance"></category></entry><entry><title>Exposing C and Rust APIs: some thoughts from librsvg</title><link href="https://people.gnome.org/~federico/blog/exposing-c-and-rust-apis.html" rel="alternate"></link><published>2020-01-15T11:15:06-06:00</published><updated>2020-01-15T11:15:06-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2020-01-15:/~federico/blog/exposing-c-and-rust-apis.html</id><summary type="html">&lt;p&gt;Librsvg exports two public APIs: the &lt;a href="https://developer.gnome.org/rsvg/stable/"&gt;C API&lt;/a&gt; that is in turn available
         2264 to other languages through &lt;a href="https://people.gnome.org/~federico/blog/magic-of-gobject-introspection.html"&gt;GObject Introspection&lt;/a&gt;, and the &lt;a href="https://gnome.pages.gitlab.gnome.org/librsvg/doc/librsvg/"&gt;Rust API&lt;/a&gt;.&lt;/p&gt;
         2265 &lt;p&gt;You could call this a use of the &lt;a href="https://en.wikipedia.org/wiki/Facade_pattern"&gt;facade pattern&lt;/a&gt; on top of the
         2266 &lt;a href="https://gnome.pages.gitlab.gnome.org/librsvg/doc/rsvg_internals/index.html"&gt;rsvg_internals crate&lt;/a&gt;.  That crate &lt;em&gt;is&lt;/em&gt; the actual
         2267 implementation of librsvg, and exports an …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Librsvg exports two public APIs: the &lt;a href="https://developer.gnome.org/rsvg/stable/"&gt;C API&lt;/a&gt; that is in turn available
         2268 to other languages through &lt;a href="https://people.gnome.org/~federico/blog/magic-of-gobject-introspection.html"&gt;GObject Introspection&lt;/a&gt;, and the &lt;a href="https://gnome.pages.gitlab.gnome.org/librsvg/doc/librsvg/"&gt;Rust API&lt;/a&gt;.&lt;/p&gt;
         2269 &lt;p&gt;You could call this a use of the &lt;a href="https://en.wikipedia.org/wiki/Facade_pattern"&gt;facade pattern&lt;/a&gt; on top of the
         2270 &lt;a href="https://gnome.pages.gitlab.gnome.org/librsvg/doc/rsvg_internals/index.html"&gt;rsvg_internals crate&lt;/a&gt;.  That crate &lt;em&gt;is&lt;/em&gt; the actual
         2271 implementation of librsvg, and exports an interface with many knobs
         2272 that are not exposed from the public APIs.  The knobs are to allow for
         2273 the variations in each of those APIs.&lt;/p&gt;
         2274 &lt;p&gt;This post is about some interesting things that have come up during
         2275 the creation/separation of those public APIs, and the implications of
         2276 having an internals library that implements both.&lt;/p&gt;
         2277 &lt;h2&gt;Initial code organization&lt;/h2&gt;
         2278 &lt;p&gt;When librsvg was being ported to Rust, it just had an &lt;code&gt;rsvg_internals&lt;/code&gt;
         2279 crate that compiled as a &lt;code&gt;staticlib&lt;/code&gt; to a &lt;code&gt;.a&lt;/code&gt; library, which was
         2280 later linked into the final &lt;code&gt;librsvg.so&lt;/code&gt;.&lt;/p&gt;
         2281 &lt;p&gt;Eventually the code got to the point where it was feasible to port the
         2282 toplevel C API to Rust.  This was relatively easy to do, since
         2283 everything else underneath was already in Rust.  At that point I
         2284 became interested &lt;a href="https://people.gnome.org/~federico/blog/a-rust-api-for-librsvg.html"&gt;in also having a Rust API&lt;/a&gt; for librsvg —
         2285 first to port the test suite to Rust and be able to run tests in
         2286 parallel, and then to actually have a public API in Rust with more
         2287 modern idioms than the historical, GObject-based API in C.&lt;/p&gt;
         2288 &lt;p&gt;Version &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/-/tags/2.45.5"&gt;2.45.5&lt;/a&gt;, from February 2019, is the last release that only had
         2289 a C API.&lt;/p&gt;
         2290 &lt;p&gt;Most of the C API of librsvg is in the &lt;code&gt;RsvgHandle&lt;/code&gt; class.  An
         2291 &lt;code&gt;RsvgHandle&lt;/code&gt; gets loaded with SVG data from a file or a stream, and
         2292 then gets rendered to a Cairo context.  The naming of Rust source
         2293 files more or less matched the C source files, so where there was
         2294 &lt;code&gt;rsvg-handle.c&lt;/code&gt; initially, later we had &lt;code&gt;handle.rs&lt;/code&gt; with the Rustified
         2295 part of that code.&lt;/p&gt;
         2296 &lt;p&gt;So, &lt;code&gt;handle.rs&lt;/code&gt; had the Rust internals of the &lt;code&gt;RsvgHandle&lt;/code&gt; class, and
         2297 a bunch of &lt;code&gt;extern "C"&lt;/code&gt; functions callable from C.  For example, for
         2298 this function in the public C API:&lt;/p&gt;
         2299 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;rsvg_handle_set_base_gfile&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RsvgHandle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2300                                  &lt;span class="n"&gt;GFile&lt;/span&gt;      &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;base_file&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         2301 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2302 
         2303 &lt;p&gt;The corresponding Rust implementation &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/3d6d42fe1387588354291595585fbf498a89704e/rsvg_internals/src/handle.rs#L614-626"&gt;was this&lt;/a&gt;:&lt;/p&gt;
         2304 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2305 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;rsvg_handle_rust_set_base_gfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2306 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;raw_handle&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RsvgHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2307 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;raw_gfile&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gio_sys&lt;/span&gt;::&lt;span class="n"&gt;GFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2308 &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2309 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rhandle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get_rust_handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// 1&lt;/span&gt;
         2310 
         2311 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;raw_gfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="c1"&gt;// 2&lt;/span&gt;
         2312 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;: &lt;span class="nc"&gt;gio&lt;/span&gt;::&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;from_glib_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_gfile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// 3&lt;/span&gt;
         2313 
         2314 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;rhandle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_base_gfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="c1"&gt;// 4&lt;/span&gt;
         2315 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2316 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2317 
         2318 &lt;ol&gt;
         2319 &lt;li&gt;Get the Rust struct corresponding to the C GObject.&lt;/li&gt;
         2320 &lt;li&gt;Check the arguments.&lt;/li&gt;
         2321 &lt;li&gt;Convert from C GObject reference to Rust reference.&lt;/li&gt;
         2322 &lt;li&gt;Call the actual implementation of &lt;code&gt;set_base_gfile&lt;/code&gt; in the Rust
         2323    struct.&lt;/li&gt;
         2324 &lt;/ol&gt;
         2325 &lt;p&gt;You can see that this function takes in arguments with C types, and
         2326 converts them to Rust types.  It's basically just glue between the C
         2327 code and the actual implementation.&lt;/p&gt;
         2328 &lt;p&gt;Then, the actual implementation of &lt;code&gt;set_base_gfile&lt;/code&gt; looked &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/3d6d42fe1387588354291595585fbf498a89704e/rsvg_internals/src/handle.rs#L202-208"&gt;like
         2329 this&lt;/a&gt;:&lt;/p&gt;
         2330 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2331 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;set_base_gfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;gio&lt;/span&gt;::&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2332 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_uri&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2333 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_base_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2334 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2335 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;rsvg_g_warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;file has no URI; will not set the base URI&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2336 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2337 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2338 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2339 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2340 
         2341 &lt;p&gt;This is an actual method for a Rust &lt;code&gt;Handle&lt;/code&gt; struct, and takes Rust
         2342 types as arguments — no conversions are necessary here.  However,
         2343 there is a pesky call to &lt;code&gt;rsvg_g_warning&lt;/code&gt;, about which I'll talk later.&lt;/p&gt;
         2344 &lt;p&gt;I found it cleanest, although not the shortest code, to structure
         2345 things like this:&lt;/p&gt;
         2346 &lt;ul&gt;
         2347 &lt;li&gt;
         2348 &lt;p&gt;C code: bunch of stub functions where &lt;code&gt;rsvg_blah&lt;/code&gt; just calls a
         2349   corresponding &lt;code&gt;rsvg_rust_blah&lt;/code&gt;.&lt;/p&gt;
         2350 &lt;/li&gt;
         2351 &lt;li&gt;
         2352 &lt;p&gt;Toplevel Rust code: bunch of &lt;code&gt;#[no_mangle] unsafe extern "C" fn rust_blah()&lt;/code&gt; that
         2353   convert from C argument types to Rust types, and call safe Rust
         2354   functions — for librsvg, these happened to be methods for a struct.
         2355   Before returning, the toplevel functions convert Rust return values
         2356   to C return values, and do things like converting the &lt;code&gt;Err(E)&lt;/code&gt; of a
         2357   &lt;code&gt;Result&amp;lt;&amp;gt;&lt;/code&gt; into a &lt;code&gt;GError&lt;/code&gt; or a boolean or whatever the traditional
         2358   C API required.&lt;/p&gt;
         2359 &lt;/li&gt;
         2360 &lt;/ul&gt;
         2361 &lt;p&gt;In the very first versions of the code where the public API was
         2362 implemented in Rust, the &lt;code&gt;extern "C"&lt;/code&gt; functions actually contained
         2363 their implementation.  However, after some refactoring, it turned out
         2364 to be cleaner to leave those functions just with the task of
         2365 converting C to Rust types and vice-versa, and put the actual
         2366 implementation in very Rust-y code.  This made it easier to keep the 
         2367 &lt;code&gt;unsafe&lt;/code&gt; conversion code (unsafe because it deals with raw pointers
         2368 coming from C) only in the toplevel functions.&lt;/p&gt;
         2369 &lt;h2&gt;Growing out a Rust API&lt;/h2&gt;
         2370 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/cd848439e01378461647dd848918262bf6639193"&gt;This commit&lt;/a&gt; is where the new, public Rust API
         2371 started.  That commit just created a &lt;a href="https://doc.rust-lang.org/cargo/reference/manifest.html#the-workspace-section"&gt;Cargo workspace&lt;/a&gt;
         2372 with two crates; the &lt;code&gt;rsvg_internals&lt;/code&gt; crate that we already had, and a
         2373 &lt;code&gt;librsvg_crate&lt;/code&gt; with the public Rust API.&lt;/p&gt;
         2374 &lt;p&gt;The commits over the subsequent couple of months are of intense
         2375 refactoring:&lt;/p&gt;
         2376 &lt;ul&gt;
         2377 &lt;li&gt;
         2378 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/d01f75ed310b0a7b8d62fc7de65465357f20f535"&gt;This commit&lt;/a&gt; moves the &lt;code&gt;unsafe extern "C"&lt;/code&gt;
         2379   functions to a separate &lt;code&gt;c_api.rs&lt;/code&gt; source file.  This leaves
         2380   &lt;code&gt;handle.rs&lt;/code&gt; with only the safe Rust implementation of the toplevel
         2381   API, and &lt;code&gt;c_api.rs&lt;/code&gt; with the unsafe entry points that mostly just
         2382   convert argument types, return values, and errors.&lt;/p&gt;
         2383 &lt;/li&gt;
         2384 &lt;li&gt;
         2385 &lt;p&gt;The API primitives get expanded to allow for a public Rust API that
         2386   is "hard to misuse" unlike the C API, which needs to be called
         2387   in a certain order.&lt;/p&gt;
         2388 &lt;/li&gt;
         2389 &lt;/ul&gt;
         2390 &lt;h2&gt;Needing to call a C macro&lt;/h2&gt;
         2391 &lt;p&gt;However, there was a little problem.  The Rust code cannot call
         2392 &lt;a href="https://developer.gnome.org/glib/stable/glib-Message-Logging.html#g-warning"&gt;&lt;code&gt;g_warning&lt;/code&gt;&lt;/a&gt;, a C macro in glib that prints a message to
         2393 stderr or uses structured logging.  Librsvg used that to signal
         2394 conditions where something went (recoverably) wrong, but there was no
         2395 way to return a proper error code to the caller — it's mainly used as
         2396 a debugging aid.&lt;/p&gt;
         2397 &lt;p&gt;This is what the &lt;code&gt;rsvg_internals&lt;/code&gt; used to be able to call that C macro:&lt;/p&gt;
         2398 &lt;p&gt;First, the C code exports a function that just calls the macro:&lt;/p&gt;
         2399 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cm"&gt;/* This function exists just so that we can effectively call g_warning() from Rust,&lt;/span&gt;
         2400 &lt;span class="cm"&gt; * since glib-rs doesn&amp;#39;t bind the g_log functions yet.&lt;/span&gt;
         2401 &lt;span class="cm"&gt; */&lt;/span&gt;
         2402 &lt;span class="kt"&gt;void&lt;/span&gt;
         2403 &lt;span class="nf"&gt;rsvg_g_warning_from_c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         2404 &lt;span class="p"&gt;{&lt;/span&gt;
         2405     &lt;span class="n"&gt;g_warning&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%s&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         2406 &lt;span class="p"&gt;}&lt;/span&gt;
         2407 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2408 
         2409 &lt;p&gt;Second, the Rust code binds that function to be callable from Rust:&lt;/p&gt;
         2410 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;rsvg_g_warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2411 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2412 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;rsvg_g_warning_from_c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc&lt;/span&gt;::&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2413 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2414 
         2415 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2416 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;rsvg_g_warning_from_c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_glib_none&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2417 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2418 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2419 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2420 
         2421 &lt;p&gt;However!  Since the standalone &lt;code&gt;librsvg_crate&lt;/code&gt; does not link to the C
         2422 code from the public &lt;code&gt;librsvg.so&lt;/code&gt;, the helper &lt;code&gt;rsvg_g_warning_from_c&lt;/code&gt;
         2423 is not available!&lt;/p&gt;
         2424 &lt;h3&gt;A configuration feature for the internals library&lt;/h3&gt;
         2425 &lt;p&gt;And yet!  Those warnings are only meaningful for the C API, which is
         2426 not able to return error codes from all situations.  However, the Rust
         2427 API &lt;em&gt;is&lt;/em&gt; able to do that, and so doesn't need the warnings printed to
         2428 stderr.  My first solution was to add a build-time option for whether
         2429 the &lt;code&gt;rsvg_internals&lt;/code&gt; library is being build for the C library, or for
         2430 the Rust one.&lt;/p&gt;
         2431 &lt;p&gt;In case we are building for the C library, the code calls
         2432 &lt;code&gt;rsvg_g_warning_from_c&lt;/code&gt; as usual.&lt;/p&gt;
         2433 &lt;p&gt;But in case we are building for the Rust library, that code is a
         2434 no-op.&lt;/p&gt;
         2435 &lt;p&gt;This is the &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/4df0ef3d6dd8c277ef484b33104e9666ea6ea38c/rsvg_internals/Cargo.toml#L81-83"&gt;bit in rsvg_internals/Cargo.toml&lt;/a&gt; to declare the feature:&lt;/p&gt;
         2436 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[features]&lt;/span&gt;
         2437 &lt;span class="c1"&gt;# Enables calling g_warning() when built as part of librsvg.so&lt;/span&gt;
         2438 &lt;span class="n"&gt;c-library&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;[]&lt;/span&gt;
         2439 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2440 
         2441 &lt;p&gt;And &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/4df0ef3d6dd8c277ef484b33104e9666ea6ea38c/rsvg_internals/src/util.rs#L31-48"&gt;this is the corresponding code&lt;/a&gt;:&lt;/p&gt;
         2442 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[cfg(feature = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;c-library&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2443 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;rsvg_g_warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2444 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2445 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2446 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;rsvg_g_warning_from_c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc&lt;/span&gt;::&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2447 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2448 
         2449 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;rsvg_g_warning_from_c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_glib_none&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2450 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2451 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2452 
         2453 &lt;span class="cp"&gt;#[cfg(not(feature = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;c-library&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;))]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2454 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;rsvg_g_warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_msg&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2455 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// The only callers of this are in handle.rs. When those functions&lt;/span&gt;
         2456 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// are called from the Rust API, they are able to return a&lt;/span&gt;
         2457 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// meaningful error code, but the C API isn&amp;#39;t - so they issues a&lt;/span&gt;
         2458 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// g_warning() instead.&lt;/span&gt;
         2459 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2460 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2461 
         2462 &lt;p&gt;The first function is the one that is compiled when the &lt;code&gt;c-library&lt;/code&gt;
         2463 feature is enabled; this happens when building &lt;code&gt;rsvg_internals&lt;/code&gt; to
         2464 link into &lt;code&gt;librsvg.so&lt;/code&gt;.&lt;/p&gt;
         2465 &lt;p&gt;The second function does nothing; it is what is compiled when
         2466 &lt;code&gt;rsvg_internals&lt;/code&gt; is being used just from the &lt;code&gt;librsvg_crate&lt;/code&gt; crate
         2467 with the Rust API.&lt;/p&gt;
         2468 &lt;p&gt;While this worked well, it meant that &lt;strong&gt;the internals library was
         2469 built twice&lt;/strong&gt; on each compilation run of the whole librsvg module:
         2470 once for &lt;code&gt;librsvg.so&lt;/code&gt;, and once for &lt;code&gt;librsvg_crate&lt;/code&gt;.&lt;/p&gt;
         2471 &lt;h2&gt;Making programming errors a &lt;code&gt;g_critical&lt;/code&gt;&lt;/h2&gt;
         2472 &lt;p&gt;While &lt;code&gt;g_warning()&lt;/code&gt; means "something went wrong, but the program will
         2473 continue", &lt;code&gt;g_critical()&lt;/code&gt; means "there is a programming error".  For
         2474 historical reasons Glib does not abort when &lt;code&gt;g_critical()&lt;/code&gt; is called,
         2475 except by setting &lt;a href="https://developer.gnome.org/glib/stable/glib-running.html#G-DEBUG:CAPS"&gt;&lt;code&gt;G_DEBUG=fatal-criticals&lt;/code&gt;&lt;/a&gt;, or by
         2476 running a development version of Glib.&lt;/p&gt;
         2477 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/9d26e03dc64342978ab8273dcf6a474af3843b9f"&gt;This commit&lt;/a&gt; turned warnings into critical errors when the
         2478 C API was called out of order, by using a similar
         2479 &lt;code&gt;rsvg_g_critical_from_c()&lt;/code&gt; wrapper for a C macro.&lt;/p&gt;
         2480 &lt;h2&gt;Separating the C-callable code into yet another crate&lt;/h2&gt;
         2481 &lt;p&gt;To recapitulate, at that point we had this:&lt;/p&gt;
         2482 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;librsvg&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
         2483 &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="nv"&gt;Cargo&lt;/span&gt;.&lt;span class="nv"&gt;toml&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;declares&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;Cargo&lt;/span&gt; &lt;span class="nv"&gt;workspace&lt;/span&gt;
         2484 &lt;span class="o"&gt;|&lt;/span&gt;
         2485 &lt;span class="o"&gt;+-&lt;/span&gt; &lt;span class="nv"&gt;rsvg_internals&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
         2486 &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="nv"&gt;Cargo&lt;/span&gt;.&lt;span class="nv"&gt;toml&lt;/span&gt;
         2487 &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+-&lt;/span&gt; &lt;span class="nv"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
         2488 &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="nv"&gt;c_api&lt;/span&gt;.&lt;span class="nv"&gt;rs&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;convert&lt;/span&gt; &lt;span class="nv"&gt;types&lt;/span&gt; &lt;span class="nv"&gt;and&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;values&lt;/span&gt;, &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nl"&gt;into&lt;/span&gt; &lt;span class="nv"&gt;implementation&lt;/span&gt;
         2489 &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="nv"&gt;handle&lt;/span&gt;.&lt;span class="nv"&gt;rs&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;actual&lt;/span&gt; &lt;span class="nv"&gt;implementation&lt;/span&gt;
         2490 &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;*&lt;/span&gt;.&lt;span class="nv"&gt;rs&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;all&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;other&lt;/span&gt; &lt;span class="nv"&gt;internals&lt;/span&gt;
         2491 &lt;span class="o"&gt;|&lt;/span&gt;
         2492 &lt;span class="o"&gt;+-&lt;/span&gt; &lt;span class="nv"&gt;librsvg&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
         2493 &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;*&lt;/span&gt;.&lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;stub&lt;/span&gt; &lt;span class="nv"&gt;functions&lt;/span&gt; &lt;span class="nv"&gt;that&lt;/span&gt; &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nl"&gt;into&lt;/span&gt; &lt;span class="nv"&gt;Rust&lt;/span&gt;
         2494 &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="nv"&gt;rsvg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;base&lt;/span&gt;.&lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;contains&lt;/span&gt; &lt;span class="nv"&gt;rsvg_g_warning_from_c&lt;/span&gt;&lt;span class="ss"&gt;()&lt;/span&gt; &lt;span class="nv"&gt;among&lt;/span&gt; &lt;span class="nv"&gt;others&lt;/span&gt;
         2495 &lt;span class="o"&gt;|&lt;/span&gt;
         2496 &lt;span class="o"&gt;+-&lt;/span&gt; &lt;span class="nv"&gt;librsvg_crate&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
         2497    &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="nv"&gt;Cargo&lt;/span&gt;.&lt;span class="nv"&gt;toml&lt;/span&gt;
         2498    &lt;span class="o"&gt;+-&lt;/span&gt; &lt;span class="nv"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
         2499    &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="nv"&gt;lib&lt;/span&gt;.&lt;span class="nv"&gt;rs&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;Rust&lt;/span&gt; &lt;span class="nv"&gt;API&lt;/span&gt;
         2500    &lt;span class="o"&gt;+-&lt;/span&gt; &lt;span class="nv"&gt;tests&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;tests&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;Rust&lt;/span&gt; &lt;span class="nv"&gt;API&lt;/span&gt;
         2501         &lt;span class="o"&gt;*&lt;/span&gt;.&lt;span class="nv"&gt;rs&lt;/span&gt;
         2502 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2503 
         2504 &lt;p&gt;At this point &lt;code&gt;c_api.rs&lt;/code&gt; with all the &lt;code&gt;unsafe&lt;/code&gt; functions looked out of
         2505 place.  That code is only relevant to &lt;code&gt;librsvg.so&lt;/code&gt; — the public C API
         2506 —, not to the Rust API in &lt;code&gt;librsvg_crate&lt;/code&gt;.&lt;/p&gt;
         2507 &lt;p&gt;I started moving the C API glue to a separate &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/78219898d17440a41d21a206afa5a5d982dcbf9f"&gt;&lt;code&gt;librsvg_c_api&lt;/code&gt; crate&lt;/a&gt; that lives
         2508 along with the C stubs:&lt;/p&gt;
         2509 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;+- librsvg/
         2510 |    *.c - stub functions that call into Rust
         2511 |    rsvg-base.c - contains rsvg_g_warning_from_c() among others
         2512 |    Cargo.toml
         2513 |    c_api.rs - what we had before
         2514 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2515 
         2516 &lt;p&gt;This made the dependencies look like the following:&lt;/p&gt;
         2517 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;      rsvg_internals
         2518        ^           ^
         2519        |             \
         2520        |               \
         2521 librsvg_crate     librsvg_c_api
         2522   (Rust API)             ^
         2523                          |
         2524                     librsvg.so
         2525                       (C API)
         2526 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2527 
         2528 &lt;p&gt;And also, this made it possible to &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/38fe68c2c3165a923dee9cfaa9a9f57960fb9b95"&gt;remove the configuration feature&lt;/a&gt;
         2529 for &lt;code&gt;rsvg_internals&lt;/code&gt;, since the code that calls
         2530 &lt;code&gt;rsvg_g_warning_from_c&lt;/code&gt; now lives in &lt;code&gt;librsvg_c_api&lt;/code&gt;.&lt;/p&gt;
         2531 &lt;p&gt;With that, &lt;code&gt;rsvg_internals&lt;/code&gt; is compiled only once, as it should be.&lt;/p&gt;
         2532 &lt;p&gt;This also helped clean up some code in the internals library.
         2533 Deprecated functions that render SVGs directly to &lt;code&gt;GdkPixbuf&lt;/code&gt; are now
         2534 in &lt;code&gt;librsvg_c_api&lt;/code&gt; and don't clutter the &lt;code&gt;rsvg_internals&lt;/code&gt; library.
         2535 All the GObject boilerplate is there as well now; &lt;code&gt;rsvg_internals&lt;/code&gt; is
         2536 mostly safe code except for the glue to libxml2.&lt;/p&gt;
         2537 &lt;h2&gt;Summary&lt;/h2&gt;
         2538 &lt;p&gt;It was useful to move all the code that dealt with incoming C types,
         2539 our outgoing C return values and errors, into the same place, and
         2540 separate it from the "pure Rust" code.&lt;/p&gt;
         2541 &lt;p&gt;This took gradual refactoring and was not done in a single step, but
         2542 it left the resulting Rust code rather nice and clean.&lt;/p&gt;
         2543 &lt;p&gt;When we added a new public Rust API, we had to shuffle some code
         2544 around that could only be linked in the context of a C library.&lt;/p&gt;
         2545 &lt;p&gt;Compile-time configuration features are useful (like &lt;code&gt;#ifdef&lt;/code&gt; in the C
         2546 world), but they do cause double compilation if you need a C-internals
         2547 and a Rust-internals library from the same code.&lt;/p&gt;
         2548 &lt;p&gt;Having proper error reporting throughout the Rust code is a lot of
         2549 work, but pretty much invaluable.  The glue code to C can then convert
         2550 and expose those errors as needed.&lt;/p&gt;
         2551 &lt;p&gt;If you need both C and Rust APIs into the same code base, you may end
         2552 up naturally using a facade pattern for each.  It helps to gradually
         2553 refactor the internals to be as "pure idiomatic Rust" as possible,
         2554 while letting API idiosyncrasies bubble up to each individual facade.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category></entry><entry><title>Moving gnome-shell's styles to Rust</title><link href="https://people.gnome.org/~federico/blog/moving-gnome-shell-styles-to-rust.html" rel="alternate"></link><published>2019-11-25T21:10:06-06:00</published><updated>2019-11-25T21:10:06-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-11-25:/~federico/blog/moving-gnome-shell-styles-to-rust.html</id><summary type="html">&lt;p&gt;Gnome-shell uses CSS processing code that dates from
         2555 &lt;a href="https://blog.ometer.com/2006/10/14/text-layout-that-works-properly/"&gt;HippoCanvas&lt;/a&gt;,
         2556 a CSS-aware canvas from around 2006.  It uses libcroco to parse CSS,
         2557 and implements selector matching by hand in C.&lt;/p&gt;
         2558 &lt;p&gt;This code is getting rather dated, and libcroco is unmaintained.&lt;/p&gt;
         2559 &lt;p&gt;I've been reading the code for
         2560 &lt;a href="https://gitlab.gnome.org/GNOME/gnome-shell/blob/66fc5c07/src/st/st-theme.c"&gt;&lt;code&gt;StTheme&lt;/code&gt;&lt;/a&gt;
         2561 and
         2562 &lt;a href="https://gitlab.gnome.org/GNOME/gnome-shell/blob/66fc5c07/src/st/st-theme-node.c"&gt;&lt;code&gt;StThemeNode&lt;/code&gt;&lt;/a&gt;,
         2563 and it …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Gnome-shell uses CSS processing code that dates from
         2564 &lt;a href="https://blog.ometer.com/2006/10/14/text-layout-that-works-properly/"&gt;HippoCanvas&lt;/a&gt;,
         2565 a CSS-aware canvas from around 2006.  It uses libcroco to parse CSS,
         2566 and implements selector matching by hand in C.&lt;/p&gt;
         2567 &lt;p&gt;This code is getting rather dated, and libcroco is unmaintained.&lt;/p&gt;
         2568 &lt;p&gt;I've been reading the code for
         2569 &lt;a href="https://gitlab.gnome.org/GNOME/gnome-shell/blob/66fc5c07/src/st/st-theme.c"&gt;&lt;code&gt;StTheme&lt;/code&gt;&lt;/a&gt;
         2570 and
         2571 &lt;a href="https://gitlab.gnome.org/GNOME/gnome-shell/blob/66fc5c07/src/st/st-theme-node.c"&gt;&lt;code&gt;StThemeNode&lt;/code&gt;&lt;/a&gt;,
         2572 and it looks very feasible to port it gradually to Rust, by using the
         2573 same crates that librsvg uses, and eventually removing libcroco
         2574 altogether:  &lt;strong&gt;gnome-shell is the last module that uses libcroco in
         2575 distro packages&lt;/strong&gt;.&lt;/p&gt;
         2576 &lt;h2&gt;Strategy&lt;/h2&gt;
         2577 &lt;p&gt;&lt;code&gt;StTheme&lt;/code&gt; and &lt;code&gt;StThemeNode&lt;/code&gt; use libcroco to load CSS stylesheets and
         2578 keep them in memory.  The values of individual properties are just
         2579 tokenized and kept around as a linked list of &lt;code&gt;CRTerm&lt;/code&gt;; this struct
         2580 represents a single token.&lt;/p&gt;
         2581 &lt;p&gt;Later, the drawing code uses functions like
         2582 &lt;code&gt;st_theme_node_lookup_color(node, "property_name")&lt;/code&gt; or
         2583 &lt;code&gt;st_theme_node_lookup_length()&lt;/code&gt; to query the various properties that
         2584 it needs.  It is &lt;em&gt;then&lt;/em&gt; that the type of each property gets
         2585 determined:  prior to that step, property values are just tokenized,
         2586 not parsed into usable values.&lt;/p&gt;
         2587 &lt;p&gt;I am going to start by porting the individual parsers to Rust, similar
         2588 to what Paolo and I did for librsvg.  It turns out that there's some
         2589 code we can share.&lt;/p&gt;
         2590 &lt;p&gt;So far I have the &lt;a href="https://gitlab.gnome.org/federico/stylish/blob/master/src/color.rs"&gt;parser for
         2591 colors&lt;/a&gt;
         2592 implemented in Rust.  This &lt;a href="https://gitlab.gnome.org/federico/gnome-shell/commit/f1bc7b8ece4dd3384a76c46492d61de70b3d670a"&gt;removes a little bunch of
         2593 code&lt;/a&gt;
         2594 from the C parsers, and replaces it with a little Rust code, since the
         2595 cssparser crate can already parse CSS colors with alpha with no extra
         2596 work — libcroco didn't support alpha.&lt;/p&gt;
         2597 &lt;p&gt;As a bonus, this supports &lt;code&gt;hsl()&lt;/code&gt; colors in addition to &lt;code&gt;rgb()&lt;/code&gt; ones
         2598 out of the box!&lt;/p&gt;
         2599 &lt;p&gt;After all the parsers are done, the next step would be to convert the
         2600 representation of complete stylesheets into pure Rust code.&lt;/p&gt;
         2601 &lt;h2&gt;What can we expect?&lt;/h2&gt;
         2602 &lt;p&gt;&lt;strong&gt;A well-maintained CSS stack.&lt;/strong&gt;  Firefox and Servo both use the
         2603 crates in question, so librsvg and gnome-shell should get maintenance
         2604 of a robust CSS stack "for free", for the foreseeable future.&lt;/p&gt;
         2605 &lt;p&gt;&lt;strong&gt;Speed.&lt;/strong&gt;  Caveat: I have no profile data for gnome-shell yet, so I don't
         2606 know how much time it spends doing CSS parsing and cascading, but it
         2607 looks like the Rust version has a good chance of being more efficient.&lt;/p&gt;
         2608 &lt;p&gt;The &lt;a href="https://docs.rs/selectors/"&gt;selectors crate&lt;/a&gt; has some very
         2609 interesting
         2610 &lt;a href="https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-engine-quantum-css-aka-stylo/"&gt;optimizations&lt;/a&gt;
         2611 from Mozilla Servo, and it is also now used in Firefox.  It supports
         2612 doing selector matching using Bloom filters, and can also avoid
         2613 re-cascading child nodes if a change to a parent would not cause its
         2614 children to change.&lt;/p&gt;
         2615 &lt;p&gt;All the parsing is done with zero-copy parsers thanks to Rust's string
         2616 slices; without so many &lt;code&gt;malloc()&lt;/code&gt; calls in the parsing code path,
         2617 the parsing stage should really fly.&lt;/p&gt;
         2618 &lt;p&gt;&lt;strong&gt;More CSS features.&lt;/strong&gt; The selectors crate can do matching on
         2619 basically all kinds of selectors as defined by recent CSS specs; one
         2620 just has to provide the correct hooks into the calling code's
         2621 representation of the DOM tree.  The kind of matching that &lt;code&gt;StTheme&lt;/code&gt;
         2622 can do is somewhat limited; the rustification should make it match
         2623 much more closely to what people expect from CSS engines in web
         2624 browsers.&lt;/p&gt;
         2625 &lt;p&gt;&lt;strong&gt;A well-defined model of property inheritance.&lt;/strong&gt; &lt;code&gt;StThemeNode&lt;/code&gt;'s
         2626 model for CSS property inheritance is a bit ad-hoc and inconsistent.
         2627 I haven't quite tested it, but from looking at the code, it seems that
         2628 not all properties get inherited in the same way.  I hope to move it
         2629 to something closer to what librsvg already does, which should make it
         2630 match people's expectations from the web.&lt;/p&gt;
         2631 &lt;h2&gt;In the meantime&lt;/h2&gt;
         2632 &lt;p&gt;I have a merge request ready to simply move the libcroco source code
         2633 directly inside gnome-shell's source tree.  This should let distros
         2634 remove their libcroco package as soon as possible.  That MR does not
         2635 require Rust yet.&lt;/p&gt;
         2636 &lt;p&gt;My playground is here:&lt;/p&gt;
         2637 &lt;ul&gt;
         2638 &lt;li&gt;&lt;a href="https://gitlab.gnome.org/federico/gnome-shell/commits/rustify-styles"&gt;Gnome-shell branch to rustify the
         2639   styles&lt;/a&gt;&lt;/li&gt;
         2640 &lt;li&gt;&lt;a href="https://gitlab.gnome.org/federico/stylish"&gt;Stylish&lt;/a&gt;, a Rust
         2641   library that will implement gnome-shell's styling code.&lt;/li&gt;
         2642 &lt;/ul&gt;
         2643 &lt;p&gt;This does not compile yet!  I'll plug things together tomorrow.&lt;/p&gt;
         2644 &lt;p&gt;(Oh, yes, the project to redo Firefox's CSS stack in Rust used to be
         2645 called Stylo.  I'm calling this Stylish, as in Styles for the Shell.)&lt;/p&gt;</content><category term="misc"></category><category term="gnome-shell"></category><category term="rust"></category><category term="gnome"></category></entry><entry><title>Refactoring the Length type</title><link href="https://people.gnome.org/~federico/blog/refactoring-the-length-type.html" rel="alternate"></link><published>2019-11-19T10:01:14-06:00</published><updated>2019-11-19T10:01:14-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-11-19:/~federico/blog/refactoring-the-length-type.html</id><summary type="html">&lt;p&gt;&lt;a href="https://www.w3.org/TR/css3-values/#lengths"&gt;CSS length values&lt;/a&gt; have a number and a unit, e.g. &lt;code&gt;5cm&lt;/code&gt;
         2646 or &lt;code&gt;6px&lt;/code&gt;.  Sometimes the unit is a &lt;strong&gt;percentage&lt;/strong&gt;, like &lt;code&gt;50%&lt;/code&gt;, and SVG
         2647 says that lengths with percentage units should be resolved with
         2648 respect to a certain rectangle.  For example, consider this circle
         2649 element:&lt;/p&gt;
         2650 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;circle&lt;/span&gt; &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;50%&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;75 …&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://www.w3.org/TR/css3-values/#lengths"&gt;CSS length values&lt;/a&gt; have a number and a unit, e.g. &lt;code&gt;5cm&lt;/code&gt;
         2651 or &lt;code&gt;6px&lt;/code&gt;.  Sometimes the unit is a &lt;strong&gt;percentage&lt;/strong&gt;, like &lt;code&gt;50%&lt;/code&gt;, and SVG
         2652 says that lengths with percentage units should be resolved with
         2653 respect to a certain rectangle.  For example, consider this circle
         2654 element:&lt;/p&gt;
         2655 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;circle&lt;/span&gt; &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;50%&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;75%&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;r=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4px&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;black&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         2656 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2657 
         2658 &lt;p&gt;This means, draw a solid black circle whose center is at 50% of the
         2659 width and 75% of the height of the current viewport.  The circle
         2660 should have a 4-pixel radius.&lt;/p&gt;
         2661 &lt;p&gt;The process of converting that kind of units into absolute pixels for
         2662 the final drawing is called &lt;strong&gt;normalization&lt;/strong&gt;.  In SVG, percentage
         2663 units sometimes need to be normalized with respect to the current
         2664 viewport (a local coordinate system), or with respect to the size of
         2665 another object (e.g. when a clipping path is used to cut the current
         2666 shape in half).&lt;/p&gt;
         2667 &lt;p&gt;One detail about normalization is that it can be with respect to the
         2668 horizontal dimension of the current viewport, the vertical dimension,
         2669 or both.  Keep this in mind: at normalization time, we need to be able
         2670 to distinguish between those three modes.&lt;/p&gt;
         2671 &lt;h2&gt;The original C version&lt;/h2&gt;
         2672 &lt;p&gt;I have &lt;a href="https://people.gnome.org/~federico/news-2016-11.html#03"&gt;talked about the original C code for lengths&lt;/a&gt; before; the
         2673 following is a small summary.&lt;/p&gt;
         2674 &lt;p&gt;The original C code had &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/ef720eeabf6a1bf2bca9b31756398578d75998a6/rsvg-private.h#L256-259"&gt;this struct&lt;/a&gt; to represent lengths:&lt;/p&gt;
         2675 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         2676     &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2677     &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2678 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;RsvgLength&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2679 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2680 
         2681 &lt;p&gt;The &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/ef720eeabf6a1bf2bca9b31756398578d75998a6/rsvg-css.c#L181-205"&gt;parsing code&lt;/a&gt; would set the &lt;code&gt;factor&lt;/code&gt; field to a
         2682 character depending on the length's unit:  &lt;code&gt;'p'&lt;/code&gt; for percentages, &lt;code&gt;'i'&lt;/code&gt;
         2683 for inches, etc., and &lt;code&gt;'\0'&lt;/code&gt; for the default unit, which is pixels.&lt;/p&gt;
         2684 &lt;p&gt;Along with that, the &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/ef720eeabf6a1bf2bca9b31756398578d75998a6/rsvg-css.c#L181-205"&gt;normalization code&lt;/a&gt; needed to know
         2685 the direction (horizontal, vertical, both) to which the length in
         2686 question refers.  It did this by taking another character as an
         2687 argument to the normalization function:&lt;/p&gt;
         2688 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;double&lt;/span&gt;
         2689 &lt;span class="nf"&gt;_rsvg_css_normalize_length&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;RsvgLength&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RsvgDrawingCtx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         2690 &lt;span class="p"&gt;{&lt;/span&gt;
         2691     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;factor&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="cm"&gt;/* pixels, no need to normalize */&lt;/span&gt;
         2692         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2693     &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;factor&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;p&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;      &lt;span class="cm"&gt;/* percentages; need to consider direction */&lt;/span&gt;
         2694         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;h&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                                     &lt;span class="cm"&gt;/* horizontal */&lt;/span&gt;
         2695             &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2696         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;v&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                                     &lt;span class="cm"&gt;/* vertical */&lt;/span&gt;
         2697             &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2698         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;o&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                                     &lt;span class="cm"&gt;/* both */&lt;/span&gt;
         2699             &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rsvg_viewport_percentage&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2700                                                           &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         2701     &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
         2702 &lt;span class="p"&gt;}&lt;/span&gt;
         2703 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2704 
         2705 &lt;p&gt;&lt;a href="https://people.gnome.org/~federico/news-2016-11.html#03"&gt;The original post&lt;/a&gt; talks about how I found a couple of bugs with
         2706 how the directions are identified at normalization time.  The function
         2707 above expects one of &lt;code&gt;'h'/'v'/'o'&lt;/code&gt; for horizontal/vertical/both, and one or
         2708 two places in the code passed the wrong character.&lt;/p&gt;
         2709 &lt;h2&gt;Making the C version cleaner&lt;/h2&gt;
         2710 &lt;p&gt;Before converting that code to Rust, I &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/b7768db1a9cd129298737f0d0ea9fd7cd7d444a0"&gt;removed the pesky
         2711 characters&lt;/a&gt; and made the code use proper enums to
         2712 identify a length's units.&lt;/p&gt;
         2713 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         2714 &lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="n"&gt;LENGTH_UNIT_DEFAULT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2715 &lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="n"&gt;LENGTH_UNIT_PERCENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2716 &lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="n"&gt;LENGTH_UNIT_FONT_EM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2717 &lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="n"&gt;LENGTH_UNIT_FONT_EX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2718 &lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="n"&gt;LENGTH_UNIT_INCH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2719 &lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="n"&gt;LENGTH_UNIT_RELATIVE_LARGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2720 &lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="n"&gt;LENGTH_UNIT_RELATIVE_SMALLER&lt;/span&gt;
         2721 &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;LengthUnit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2722 &lt;span class="o"&gt;+&lt;/span&gt;
         2723  &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         2724      &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2725 &lt;span class="o"&gt;-&lt;/span&gt;    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2726 &lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="n"&gt;LengthUnit&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2727  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;RsvgLength&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2728 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2729 
         2730 &lt;p&gt;Then, &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/cb166d90d1b4370108ce57b8651a6a7f61ccd89d"&gt;do the same for the normalization function&lt;/a&gt;, so it will get the
         2731 direction in which to normalize as an enum instead of a char.&lt;/p&gt;
         2732 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         2733 &lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="n"&gt;LENGTH_DIR_HORIZONTAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2734 &lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="n"&gt;LENGTH_DIR_VERTICAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2735 &lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="n"&gt;LENGTH_DIR_BOTH&lt;/span&gt;
         2736 &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;LengthDir&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2737 
         2738  &lt;span class="kt"&gt;double&lt;/span&gt;
         2739 &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;_rsvg_css_normalize_length&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;RsvgLength&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RsvgDrawingCtx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         2740 &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;_rsvg_css_normalize_length&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;RsvgLength&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RsvgDrawingCtx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LengthDir&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         2741 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2742 
         2743 &lt;h2&gt;Making the C version easier to get right&lt;/h2&gt;
         2744 &lt;p&gt;While doing the last change above, I found a place in the code that
         2745 used the wrong direction by mistake, probably due to a cut&amp;amp;paste
         2746 error.  Part of the problem here is that the code was specifying the
         2747 direction at normalization time.&lt;/p&gt;
         2748 &lt;p&gt;I decided to change it so that &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/5a85e7cf2ecc90486346debc9a5a426163348f52"&gt;each direction value carried its own
         2749 direction since initialization&lt;/a&gt;, so that subsequent
         2750 code wouldn't have to worry about that.  Hopefully, initializing a
         2751 &lt;code&gt;width&lt;/code&gt; field should make it obvious that it needed
         2752 &lt;code&gt;LENGTH_DIR_HORIZONTAL&lt;/code&gt;.&lt;/p&gt;
         2753 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt; &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         2754      &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2755      &lt;span class="n"&gt;LengthUnit&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2756 &lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="n"&gt;LengthDir&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2757  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;RsvgLength&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2758 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2759 
         2760 &lt;p&gt;That is, so that instead of&lt;/p&gt;
         2761 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;  &lt;span class="cm"&gt;/* at initialization time */&lt;/span&gt;
         2762   &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_rsvg_css_parse_length&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         2763 
         2764   &lt;span class="p"&gt;...&lt;/span&gt;
         2765 
         2766   &lt;span class="cm"&gt;/* at rendering time */&lt;/span&gt;
         2767   &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;final_width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_rsvg_css_normalize_length&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LENGTH_DIR_HORIZONTAL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         2768 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2769 
         2770 &lt;p&gt;we would instead do this:&lt;/p&gt;
         2771 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;  &lt;span class="cm"&gt;/* at initialization time */&lt;/span&gt;
         2772   &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_rsvg_css_parse_length&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LENGTH_DIR_HORIZONTAL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         2773 
         2774   &lt;span class="p"&gt;...&lt;/span&gt;
         2775 
         2776   &lt;span class="cm"&gt;/* at rendering time */&lt;/span&gt;
         2777   &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;final_width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_rsvg_css_normalize_length&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         2778 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2779 
         2780 &lt;p&gt;This made the drawing code, which deals with a lot of coordinates at
         2781 the same time, a lot less noisy.&lt;/p&gt;
         2782 &lt;h2&gt;Initial port to Rust&lt;/h2&gt;
         2783 &lt;p&gt;To recap, this was the state of the structs after the initial
         2784 refactoring in C:&lt;/p&gt;
         2785 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         2786     &lt;span class="n"&gt;LENGTH_UNIT_DEFAULT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2787     &lt;span class="n"&gt;LENGTH_UNIT_PERCENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2788     &lt;span class="n"&gt;LENGTH_UNIT_FONT_EM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2789     &lt;span class="n"&gt;LENGTH_UNIT_FONT_EX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2790     &lt;span class="n"&gt;LENGTH_UNIT_INCH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2791     &lt;span class="n"&gt;LENGTH_UNIT_RELATIVE_LARGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2792     &lt;span class="n"&gt;LENGTH_UNIT_RELATIVE_SMALLER&lt;/span&gt;
         2793 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;LengthUnit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2794 
         2795 &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         2796     &lt;span class="n"&gt;LENGTH_DIR_HORIZONTAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2797     &lt;span class="n"&gt;LENGTH_DIR_VERTICAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         2798     &lt;span class="n"&gt;LENGTH_DIR_BOTH&lt;/span&gt;
         2799 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;LengthDir&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2800 
         2801 &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         2802     &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2803     &lt;span class="n"&gt;LengthUnit&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2804     &lt;span class="n"&gt;LengthDir&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2805 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;RsvgLength&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         2806 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2807 
         2808 &lt;p&gt;This &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/03d7716b4dd2e4e7cb04f58b14f00d2bff42c0d4"&gt;ported to Rust&lt;/a&gt; in a straightforward fashion:&lt;/p&gt;
         2809 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;LengthUnit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2810 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2811 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Percent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2812 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;FontEm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2813 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;FontEx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2814 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Inch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2815 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;RelativeLarger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2816 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;RelativeSmaller&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2817 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2818 
         2819 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;LengthDir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2820 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Horizontal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2821 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Vertical&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2822 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Both&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2823 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2824 
         2825 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;RsvgLength&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2826 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2827 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;: &lt;span class="nc"&gt;LengthUnit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2828 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;: &lt;span class="nc"&gt;LengthDir&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2829 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2830 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2831 
         2832 &lt;p&gt;It &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/822459f29b74e4e154d721c80f6e16fe6f05e0f2"&gt;got a similar constructor&lt;/a&gt; that took the
         2833 direction and produced an &lt;code&gt;RsvgLength&lt;/code&gt;:&lt;/p&gt;
         2834 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RsvgLength&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2835 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;: &lt;span class="nc"&gt;LengthDir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;RsvgLength&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2836 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2837 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2838 
         2839 &lt;p&gt;(This was &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/e299ef0e285f7d1267528a38d8c41596b89da526"&gt;before using &lt;code&gt;Result&lt;/code&gt;&lt;/a&gt;; remember that the original
         2840 C code did very little error checking!)&lt;/p&gt;
         2841 &lt;h2&gt;The initial Parse trait&lt;/h2&gt;
         2842 &lt;p&gt;It was at that point that it seemed convenient to &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/5510e4c3f9c9c84bac4a05f6d93a09c9b4862544"&gt;introduce a &lt;code&gt;Parse&lt;/code&gt;
         2843 trait&lt;/a&gt;, which all CSS value types would implement to
         2844 parse themselves from string.&lt;/p&gt;
         2845 &lt;p&gt;However, parsing an &lt;code&gt;RsvgLength&lt;/code&gt; also needed an extra piece of data,
         2846 the &lt;code&gt;LengthDir&lt;/code&gt;.  My initial version of the &lt;code&gt;Parse&lt;/code&gt; trait had an
         2847 associated called &lt;code&gt;Data&lt;/code&gt;, through which one could pass an extra piece
         2848 of data during parsing/initialization:&lt;/p&gt;
         2849 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;: &lt;span class="nb"&gt;Sized&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2850 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2851 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2852 
         2853 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;: &lt;span class="nc"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;::&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2854 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2855 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2856 
         2857 &lt;p&gt;This was explicitly to be able to &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/0cd2fb2145c25898f296fe2c268f7527f58834c8"&gt;pass a &lt;code&gt;LengthDir&lt;/code&gt; to the parser&lt;/a&gt; for
         2858 &lt;code&gt;RsvgLength&lt;/code&gt;:&lt;/p&gt;
         2859 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RsvgLength&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2860 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LengthDir&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2861 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;Err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2862 
         2863 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;: &lt;span class="nc"&gt;LengthDir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RsvgLength&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AttributeError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2864 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2865 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2866 
         2867 &lt;p&gt;This was okay for lengths, but &lt;em&gt;very noisy&lt;/em&gt; for everything else that
         2868 didn't require an extra bit of data.  In the rest of the code, the
         2869 helper type was &lt;code&gt;Data = ()&lt;/code&gt; and there was a pair of extra parentheses &lt;code&gt;()&lt;/code&gt;
         2870 in every place that &lt;code&gt;parse()&lt;/code&gt; was called.&lt;/p&gt;
         2871 &lt;h2&gt;Removing the helper Data type&lt;/h2&gt;
         2872 &lt;h3&gt;Introducing one type per direction&lt;/h3&gt;
         2873 &lt;p&gt;Over a year later, that &lt;code&gt;()&lt;/code&gt; bit of data everywhere was driving me
         2874 nuts.  I started refactoring the &lt;code&gt;Length&lt;/code&gt; module to remove it.&lt;/p&gt;
         2875 &lt;p&gt;First, I &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/cab989b9f749ca71551ad1fb68411bb2e96d96b8"&gt;introduced three newtypes&lt;/a&gt; to wrap &lt;code&gt;Length&lt;/code&gt;, and indicate
         2876 their direction at the same time:&lt;/p&gt;
         2877 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;LengthHorizontal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2878 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;LengthVertical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2879 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;LengthBoth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2880 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2881 
         2882 &lt;p&gt;This was &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/cab989b9f749ca71551ad1fb68411bb2e96d96b8"&gt;done with a macro&lt;/a&gt; because now each wrapper type
         2883 needed to know the relevant &lt;code&gt;LengthDir&lt;/code&gt;.&lt;/p&gt;
         2884 &lt;p&gt;Now, for example, the declaration for the &lt;code&gt;&amp;lt;circle&amp;gt;&lt;/code&gt; element looked
         2885 like this:&lt;/p&gt;
         2886 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;NodeCircle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2887 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt;: &lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LengthHorizontal&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2888 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cy&lt;/span&gt;: &lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LengthVertical&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2889 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;: &lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LengthBoth&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2890 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2891 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2892 
         2893 &lt;p&gt;(Ignore the &lt;code&gt;Cell&lt;/code&gt; everywhere; we got rid of that later.)&lt;/p&gt;
         2894 &lt;h3&gt;Removing the &lt;code&gt;dir&lt;/code&gt; field&lt;/h3&gt;
         2895 &lt;p&gt;Since now the information about the length's direction is embodied in
         2896 the &lt;code&gt;LengthHorizontal/LengthVertical/LengthBoth&lt;/code&gt; types, this made it
         2897 possible to &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/78f39807ce75e176840ec049539d9897f53316d5"&gt;remove the &lt;code&gt;dir&lt;/code&gt; field&lt;/a&gt; from the inner
         2898 &lt;code&gt;Length&lt;/code&gt; struct.&lt;/p&gt;
         2899 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;RsvgLength&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2900 &lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2901 &lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;: &lt;span class="nc"&gt;LengthUnit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2902 &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;: &lt;span class="nc"&gt;LengthDir&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2903 &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2904 
         2905 &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;LengthHorizontal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2906 &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;LengthVertical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2907 &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;LengthBoth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2908 &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2909 &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;define_length_type&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LengthHorizontal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LengthDir&lt;/span&gt;::&lt;span class="n"&gt;Horizontal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2910 &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;define_length_type&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LengthVertical&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LengthDir&lt;/span&gt;::&lt;span class="n"&gt;Vertical&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2911 &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;define_length_type&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LengthBoth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LengthDir&lt;/span&gt;::&lt;span class="n"&gt;Both&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2912 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2913 
         2914 &lt;p&gt;Note the use of a &lt;code&gt;define_length_type!&lt;/code&gt; macro to generate code for
         2915 those three newtypes.&lt;/p&gt;
         2916 &lt;h3&gt;Removing the &lt;code&gt;Data&lt;/code&gt; associated type&lt;/h3&gt;
         2917 &lt;p&gt;And finally, this made it possible to &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/0532d20d92971e7346fade2c48483b06dd49762c"&gt;remove the &lt;code&gt;Data&lt;/code&gt; associated
         2918 type&lt;/a&gt; from the &lt;code&gt;Parse&lt;/code&gt; trait.&lt;/p&gt;
         2919 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;: &lt;span class="nb"&gt;Sized&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2920 &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2921 &lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2922 
         2923 &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="nb"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nb"&gt;_&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;: &lt;span class="nc"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;::&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2924 &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="nb"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nb"&gt;_&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;::&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2925 &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2926 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2927 
         2928 &lt;p&gt;The resulting mega-commit removed a bunch of stray parentheses &lt;code&gt;()&lt;/code&gt;
         2929 from all calls to &lt;code&gt;parse()&lt;/code&gt;, and the code ended up a lot easier to
         2930 read.&lt;/p&gt;
         2931 &lt;h2&gt;Removing the newtypes&lt;/h2&gt;
         2932 &lt;p&gt;This was fine for a while.  Recently, however, I figured out that it
         2933 would be possible to embody the information for a length's direction
         2934 in a different way.&lt;/p&gt;
         2935 &lt;p&gt;But to get there, I first needed a temporary refactor.&lt;/p&gt;
         2936 &lt;h3&gt;Replacing the macro with a trait with a default implementation&lt;/h3&gt;
         2937 &lt;p&gt;Deep in the guts of &lt;code&gt;length.rs&lt;/code&gt;, the key function that does something
         2938 different based on &lt;code&gt;LengthDir&lt;/code&gt; is its &lt;code&gt;scaling_factor&lt;/code&gt; method:&lt;/p&gt;
         2939 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;LengthDir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2940 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Horizontal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2941 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Vertical&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2942 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Both&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2943 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2944 
         2945 &lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LengthDir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2946 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;scaling_factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;f64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2947 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2948 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;LengthDir&lt;/span&gt;::&lt;span class="n"&gt;Horizontal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2949 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;LengthDir&lt;/span&gt;::&lt;span class="n"&gt;Vertical&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2950 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;LengthDir&lt;/span&gt;::&lt;span class="n"&gt;Both&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;viewport_percentage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2951 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2952 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2953 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2954 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2955 
         2956 &lt;p&gt;That method gets passed, for example, the &lt;code&gt;width/height&lt;/code&gt; of the
         2957 current viewport for the &lt;code&gt;x/y&lt;/code&gt; arguments.  The method decides whether
         2958 to use the width, height, or a combination of both.&lt;/p&gt;
         2959 &lt;p&gt;And of course, the interesting part of the &lt;code&gt;define_length_type!&lt;/code&gt; macro
         2960 was to generate code for calling &lt;code&gt;LengthDir::Horizontal::scaling_factor()&lt;/code&gt;/etc. as
         2961 appropriate depending on the &lt;code&gt;LengthDir&lt;/code&gt; in question.&lt;/p&gt;
         2962 &lt;p&gt;First I made a trait called &lt;code&gt;Orientation&lt;/code&gt; with a &lt;code&gt;scaling_factor&lt;/code&gt;
         2963 method, and three zero-sized types that implement that trait.  Note
         2964 how each of these three implementations corresponds to one of the
         2965 &lt;code&gt;match&lt;/code&gt; arms above:&lt;/p&gt;
         2966 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2967 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;scaling_factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2968 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2969 
         2970 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Horizontal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2971 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Vertical&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2972 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Both&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2973 
         2974 &lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Horizontal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2975 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;scaling_factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_y&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;f64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2976 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2977 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2978 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2979 
         2980 &lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Vertical&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2981 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;scaling_factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_x&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;f64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2982 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2983 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2984 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2985 
         2986 &lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Both&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2987 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;scaling_factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;f64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2988 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;viewport_percentage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2989 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2990 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2991 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         2992 
         2993 &lt;p&gt;Now most of the contents of the &lt;code&gt;define_length_type!&lt;/code&gt; macro can go in
         2994 the &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/21a40f4ef801eecfe58c7602835c37f436f0e926"&gt;default implementation of a new trait
         2995 &lt;code&gt;LengthTrait&lt;/code&gt;&lt;/a&gt;.  Crucially, this trait has an
         2996 &lt;code&gt;Orientation&lt;/code&gt; associated type, &lt;strong&gt;which it uses to call into the
         2997 Orientation trait&lt;/strong&gt;:&lt;/p&gt;
         2998 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LengthTrait&lt;/span&gt;: &lt;span class="nb"&gt;Sized&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         2999 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Orientation&lt;/span&gt;: &lt;span class="nc"&gt;Orientation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3000 
         3001 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3002 
         3003 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;ComputedValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;ViewParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;f64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3004 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3005 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;LengthUnit&lt;/span&gt;::&lt;span class="n"&gt;Px&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3006 
         3007 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;LengthUnit&lt;/span&gt;::&lt;span class="n"&gt;Percent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3008 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3009 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;::&lt;span class="n"&gt;scaling_factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view_box_width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view_box_height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3010 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3011 
         3012 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3013 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3014 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3015 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3016 
         3017 &lt;p&gt;Note that the incantation is
         3018 &lt;code&gt;&amp;lt;Self::Orientation&amp;gt;::scaling_factor(...)&lt;/code&gt; to call that method on the
         3019 associated type.&lt;/p&gt;
         3020 &lt;p&gt;Now the &lt;code&gt;define_length_type!&lt;/code&gt; macro is shrunk a lot, with the
         3021 interesting part being just this:&lt;/p&gt;
         3022 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;define_length_type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3023 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cp"&gt;$name&lt;/span&gt;:&lt;span class="nc"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$orient&lt;/span&gt;:&lt;span class="nc"&gt;ty&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3024 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="cp"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3025 
         3026 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LengthTrait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3027 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$orient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3028 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3029 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3030 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3031 
         3032 &lt;span class="n"&gt;define_length_type&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LengthHorizontal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Horizontal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3033 &lt;span class="n"&gt;define_length_type&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LengthVertical&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Vertical&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3034 &lt;span class="n"&gt;define_length_type&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LengthBoth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Both&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3035 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3036 
         3037 &lt;p&gt;We moved from having three newtypes of length-with-LengthDir to three
         3038 newtypes with dir-as-associated-type.&lt;/p&gt;
         3039 &lt;h3&gt;Removing the newtypes and the macro&lt;/h3&gt;
         3040 &lt;p&gt;After that temporary refactoring, we had the &lt;code&gt;Orientation&lt;/code&gt; trait and
         3041 the three zero-sized types &lt;code&gt;Horizontal&lt;/code&gt;, &lt;code&gt;Vertical&lt;/code&gt;, &lt;code&gt;Both&lt;/code&gt;.&lt;/p&gt;
         3042 &lt;p&gt;I figured out that one can use &lt;a href="https://doc.rust-lang.org/std/marker/struct.PhantomData.html"&gt;&lt;code&gt;PhantomData&lt;/code&gt;&lt;/a&gt; as a way to carry
         3043 around the type that &lt;code&gt;Length&lt;/code&gt; needs to normalize itself, instead of
         3044 using an associated type in an extra &lt;code&gt;LengthTrait&lt;/code&gt;.  Behold!&lt;/p&gt;
         3045 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Length&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;: &lt;span class="nc"&gt;Orientation&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3046 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3047 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;: &lt;span class="nc"&gt;LengthUnit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3048 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;: &lt;span class="nc"&gt;PhantomData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3049 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3050 
         3051 &lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;: &lt;span class="nc"&gt;Orientation&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3052 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;ComputedValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;ViewParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;f64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3053 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3054 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;LengthUnit&lt;/span&gt;::&lt;span class="n"&gt;Px&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3055 
         3056 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;LengthUnit&lt;/span&gt;::&lt;span class="n"&gt;Percent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3057 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
         3058 &lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;::&lt;span class="n"&gt;scaling_factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view_box_width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view_box_height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3059 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3060 
         3061 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3062 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3063 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3064 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3065 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3066 
         3067 &lt;p&gt;Now the incantation is &lt;code&gt;&amp;lt;O as Orientation&amp;gt;::scaling_factor()&lt;/code&gt; to call
         3068 the method on the generic type; it is no longer an associated type in
         3069 a trait.&lt;/p&gt;
         3070 &lt;p&gt;With that, users of lengths look like this; here, our &lt;code&gt;&amp;lt;circle&amp;gt;&lt;/code&gt;
         3071 element from before:&lt;/p&gt;
         3072 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Circle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3073 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt;: &lt;span class="nc"&gt;Length&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Horizontal&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3074 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cy&lt;/span&gt;: &lt;span class="nc"&gt;Length&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Vertical&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3075 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;: &lt;span class="nc"&gt;Length&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Both&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3076 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3077 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3078 
         3079 &lt;p&gt;I'm very happy with the readability of all the code now.  I used to
         3080 think of &lt;code&gt;PhantomData&lt;/code&gt; as a way to deal with &lt;a href="https://doc.rust-lang.org/nomicon/phantom-data.html"&gt;wrapping pointers from
         3081 C&lt;/a&gt;, but it turns out that it is also useful to keep a generic
         3082 type around should one need it.&lt;/p&gt;
         3083 &lt;p&gt;The final &lt;code&gt;Length&lt;/code&gt; struct is this:&lt;/p&gt;
         3084 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Length&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;: &lt;span class="nc"&gt;Orientation&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3085 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3086 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;: &lt;span class="nc"&gt;LengthUnit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3087 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;: &lt;span class="nc"&gt;PhantomData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3088 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3089 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3090 
         3091 &lt;p&gt;And it only takes up as much space as its &lt;code&gt;length&lt;/code&gt; and &lt;code&gt;unit&lt;/code&gt; fields;
         3092 &lt;code&gt;PhantomData&lt;/code&gt; is zero-sized after all.&lt;/p&gt;
         3093 &lt;p&gt;(Later, we renamed &lt;code&gt;Orientation&lt;/code&gt; to &lt;code&gt;Normalize&lt;/code&gt;, but the code's
         3094 structure remained the same.)&lt;/p&gt;
         3095 &lt;h2&gt;Summary&lt;/h2&gt;
         3096 &lt;p&gt;Over a couple of years, librsvg's type that represents CSS lengths
         3097 went from a C representation along the lines of "all data in the world
         3098 is an int", to a Rust representation that uses some interesting type
         3099 trickery:&lt;/p&gt;
         3100 &lt;ul&gt;
         3101 &lt;li&gt;
         3102 &lt;p&gt;C struct with &lt;code&gt;char&lt;/code&gt; for units.&lt;/p&gt;
         3103 &lt;/li&gt;
         3104 &lt;li&gt;
         3105 &lt;p&gt;C struct with a &lt;code&gt;LengthUnits&lt;/code&gt; enum.&lt;/p&gt;
         3106 &lt;/li&gt;
         3107 &lt;li&gt;
         3108 &lt;p&gt;C struct without an embodied direction; each place that needs to
         3109   normalize needs to get the orientation right.&lt;/p&gt;
         3110 &lt;/li&gt;
         3111 &lt;li&gt;
         3112 &lt;p&gt;C struct with a built-in direction as an extra field, done at
         3113   initialization time.&lt;/p&gt;
         3114 &lt;/li&gt;
         3115 &lt;li&gt;
         3116 &lt;p&gt;Same struct but in Rust.&lt;/p&gt;
         3117 &lt;/li&gt;
         3118 &lt;li&gt;
         3119 &lt;p&gt;An ugly but workable &lt;code&gt;Parse&lt;/code&gt; trait so that the direction can be set
         3120   at parse/initialization time.&lt;/p&gt;
         3121 &lt;/li&gt;
         3122 &lt;li&gt;
         3123 &lt;p&gt;Three newtypes &lt;code&gt;LengthHorizontal&lt;/code&gt;, &lt;code&gt;LengthVertical&lt;/code&gt;,
         3124   &lt;code&gt;LengthBoth&lt;/code&gt; with a common core.  A cleaned-up &lt;code&gt;Parse&lt;/code&gt; trait.  A
         3125   macro to generate those newtypes.&lt;/p&gt;
         3126 &lt;/li&gt;
         3127 &lt;li&gt;
         3128 &lt;p&gt;Replace the &lt;code&gt;LengthDir&lt;/code&gt; enum with an &lt;code&gt;Orientation&lt;/code&gt;
         3129   trait, and three zero-sized types &lt;code&gt;Horizontal/Vertical/Both&lt;/code&gt; that
         3130   implement the trait.&lt;/p&gt;
         3131 &lt;/li&gt;
         3132 &lt;li&gt;
         3133 &lt;p&gt;Replace most of the macro with a helper trait &lt;code&gt;LengthTrait&lt;/code&gt; that has
         3134   an &lt;code&gt;Orientation&lt;/code&gt; associated type.&lt;/p&gt;
         3135 &lt;/li&gt;
         3136 &lt;li&gt;
         3137 &lt;p&gt;Replace the helper trait with a single &lt;code&gt;Length&amp;lt;T: Orientation&amp;gt;&lt;/code&gt;
         3138   type, which puts the orientation as a generic parameter.  The macro
         3139   disappears and there is a single implementation for everything.&lt;/p&gt;
         3140 &lt;/li&gt;
         3141 &lt;/ul&gt;
         3142 &lt;p&gt;Refactoring never ends!&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category></entry><entry><title>CSS in librsvg is now in Rust, courtesy of Mozilla Servo</title><link href="https://people.gnome.org/~federico/blog/css-in-librsvg-is-now-in-rust.html" rel="alternate"></link><published>2019-11-11T19:36:04-06:00</published><updated>2019-11-11T19:36:04-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-11-11:/~federico/blog/css-in-librsvg-is-now-in-rust.html</id><summary type="html">&lt;p&gt;Summary: after an &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/237"&gt;epic amount of
         3143 refactoring&lt;/a&gt;,
         3144 librsvg now does all CSS parsing and matching in Rust, &lt;strong&gt;without using
         3145 libcroco&lt;/strong&gt;. In addition, the CSS engine comes from Mozilla Servo, so
         3146 it should be able to handle much more complex CSS than librsvg ever
         3147 could before.&lt;/p&gt;
         3148 &lt;p&gt;This is the story of …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Summary: after an &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/237"&gt;epic amount of
         3149 refactoring&lt;/a&gt;,
         3150 librsvg now does all CSS parsing and matching in Rust, &lt;strong&gt;without using
         3151 libcroco&lt;/strong&gt;. In addition, the CSS engine comes from Mozilla Servo, so
         3152 it should be able to handle much more complex CSS than librsvg ever
         3153 could before.&lt;/p&gt;
         3154 &lt;p&gt;This is the story of CSS support in librsvg.&lt;/p&gt;
         3155 &lt;h2&gt;Introduction&lt;/h2&gt;
         3156 &lt;p&gt;The &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/c5cbb842b25980321a09c427531279d56097b646"&gt;first commit to introduce CSS
         3157 parsing&lt;/a&gt;
         3158 in librsvg dates from 2002.  It was as minimal as possible, written to
         3159 support a small subset of what was then
         3160 &lt;a href="https://www.w3.org/TR/1998/REC-CSS2-19980512/"&gt;CSS2&lt;/a&gt;.&lt;/p&gt;
         3161 &lt;p&gt;Librsvg handled CSS stylesheets more "piecing them apart" than
         3162 "parsing them".  You know, when &lt;code&gt;g_strsplit()&lt;/code&gt; is your best friend.
         3163 The basic parsing algorithm was to turn a stylesheet like this:&lt;/p&gt;
         3164 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;rect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
         3165 
         3166 &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;classname&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         3167     &lt;span class="n"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         3168     &lt;span class="n"&gt;stroke-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         3169 &lt;span class="p"&gt;}&lt;/span&gt;
         3170 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3171 
         3172 &lt;p&gt;Into a hash table whose keys are strings like &lt;code&gt;rect&lt;/code&gt; and &lt;code&gt;.classname&lt;/code&gt;,
         3173 and whose values are everything inside curly braces.&lt;/p&gt;
         3174 &lt;p&gt;The selector matching phase was equally simple.  The code only handled
         3175 a few possible match types as follows.  If it wanted to match a
         3176 certain kind of CSS selector, it would say, "what would this selector
         3177 look like in CSS syntax", it would make up a string with that syntax,
         3178 and compare it to the key strings it had stored in the hash table from
         3179 above.&lt;/p&gt;
         3180 &lt;p&gt;So, to match an &lt;strong&gt;element name selector&lt;/strong&gt;, it would &lt;code&gt;sprintf("%s",
         3181 element-&amp;gt;name)&lt;/code&gt;, obtain something like &lt;code&gt;rect&lt;/code&gt; and see if the hash
         3182 table had such a key.&lt;/p&gt;
         3183 &lt;p&gt;To match a &lt;strong&gt;class selector&lt;/strong&gt;, it would &lt;code&gt;sprintf(".%s",
         3184 element-&amp;gt;class)&lt;/code&gt;, obtain something like &lt;code&gt;.classname&lt;/code&gt;, and look it up
         3185 in the hash table.&lt;/p&gt;
         3186 &lt;p&gt;This scheme supported only a few combinations.  It handled &lt;code&gt;tag&lt;/code&gt;,
         3187 &lt;code&gt;.class&lt;/code&gt;, &lt;code&gt;tag.class&lt;/code&gt;, and a few combinations with &lt;code&gt;#id&lt;/code&gt; in them.
         3188 This was enough to support very simple stylesheets.&lt;/p&gt;
         3189 &lt;p&gt;The value corresponding to each key in the hash table was the stuff
         3190 between curly braces in the stylesheet, so the second rule from the
         3191 example above would contain &lt;code&gt;fill: green; stroke-width: 4;&lt;/code&gt;.  Once
         3192 librsvg decided that an SVG element matched that CSS rule, it would
         3193 re-parse the string with the CSS properties and apply them to the
         3194 element's style.&lt;/p&gt;
         3195 &lt;p&gt;I'm amazed that so little code was enough to deal with a good number
         3196 of SVG files with stylesheets.  I suspect that this was due to a few
         3197 things:&lt;/p&gt;
         3198 &lt;ul&gt;
         3199 &lt;li&gt;
         3200 &lt;p&gt;While people were using complex CSS in HTML all the time, it was
         3201   less common for SVG...&lt;/p&gt;
         3202 &lt;/li&gt;
         3203 &lt;li&gt;
         3204 &lt;p&gt;... because CSS2 was somewhat new, and the SVG spec was still being
         3205   written...&lt;/p&gt;
         3206 &lt;/li&gt;
         3207 &lt;li&gt;
         3208 &lt;p&gt;... and SVGs created with illustration programs don't really use
         3209   stylesheets; they include the full style information inside each
         3210   element instead of symbolically referencing it from a stylesheet.&lt;/p&gt;
         3211 &lt;/li&gt;
         3212 &lt;/ul&gt;
         3213 &lt;p&gt;From the kinds of bugs that librsvg has gotten around "CSS support is
         3214 too limited", it feels like SVGs which use CSS features are either
         3215 hand-written, or machine-generated from custom programs like data
         3216 plotting software.  Illustration programs tend to list all style
         3217 properties explicitly in each SVG element, and don't use CSS.&lt;/p&gt;
         3218 &lt;h2&gt;Libcroco appears&lt;/h2&gt;
         3219 &lt;p&gt;The first commit to &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/99de937717129fdf8539904618b918f6119f43a1"&gt;introduce
         3220 libcroco&lt;/a&gt;
         3221 was to do CSS parsing, from March 2003.&lt;/p&gt;
         3222 &lt;p&gt;At the same time, libcroco was introducing code to do CSS matching.
         3223 However, this code never got used in librsvg; it still kept its simple
         3224 string-based matcher.  Maybe libcroco's API was not ready?&lt;/p&gt;
         3225 &lt;p&gt;Libcroco fell out of maintainership around the first half of 2005, and
         3226 volunteers have kept fixing it since then.&lt;/p&gt;
         3227 &lt;h2&gt;Problems with librsvg's string matcher for CSS&lt;/h2&gt;
         3228 &lt;p&gt;The C implementation of CSS matching in librsvg remained basically
         3229 untouched until 2018, when Paolo Borelli and I started porting the
         3230 surrounding code to Rust.&lt;/p&gt;
         3231 &lt;p&gt;I had a lot of trouble figuring out the concepts from the code.  I
         3232 didn't know all the &lt;a href="https://gnome.pages.gitlab.gnome.org/librsvg/doc/rsvg_internals/css/index.html#terminology"&gt;terminology of CSS
         3233 implementations&lt;/a&gt;,
         3234 and librsvg didn't use it, either.&lt;/p&gt;
         3235 &lt;p&gt;I think that librsvg's code suffered from what the refactoring
         3236 literature calls &lt;a href="https://refactoring.guru/smells/primitive-obsession"&gt;&lt;strong&gt;primitive
         3237 obsession&lt;/strong&gt;&lt;/a&gt;.
         3238 Instead of having a parsed representation of CSS selectors, librsvg
         3239 just stored a stringified version of them.  So, a selector like
         3240 &lt;code&gt;rect#classname&lt;/code&gt; really was stored with a string like that, instead of
         3241 an actual decomposition into structs.&lt;/p&gt;
         3242 &lt;p&gt;Moreover, things were misnamed.  This is the field that stored
         3243 stylesheet data inside an RsvgHandle:&lt;/p&gt;
         3244 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="n"&gt;GHashTable&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;css_props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         3245 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3246 
         3247 &lt;p&gt;From just looking at the field declaration, this doesn't tell me
         3248 anything about what kind of data is stored there.  One has to grep the
         3249 source code for where that field is used:&lt;/p&gt;
         3250 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
         3251 &lt;span class="nf"&gt;rsvg_css_define_style&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RsvgHandle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         3252                        &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;gchar&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         3253                        &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;gchar&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;style_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         3254                        &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;gchar&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;style_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         3255                        &lt;span class="n"&gt;gboolean&lt;/span&gt; &lt;span class="n"&gt;important&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         3256 &lt;span class="p"&gt;{&lt;/span&gt;
         3257     &lt;span class="n"&gt;GHashTable&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         3258 
         3259     &lt;span class="n"&gt;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g_hash_table_lookup&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;priv&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;css_props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         3260 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3261 
         3262 &lt;p&gt;Okay, it looks up a &lt;code&gt;selector&lt;/code&gt; by name in the &lt;code&gt;css_props&lt;/code&gt;, and it
         3263 gives back... another hash table &lt;code&gt;styles&lt;/code&gt;?  What's in there?&lt;/p&gt;
         3264 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;        &lt;span class="n"&gt;g_hash_table_insert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         3265                              &lt;span class="n"&gt;g_strdup&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;style_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
         3266                              &lt;span class="n"&gt;style_value_data_new&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;style_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;important&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
         3267 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3268 
         3269 &lt;p&gt;Another string key called &lt;code&gt;style_name&lt;/code&gt;, whose key is a
         3270 &lt;code&gt;StyleValueData&lt;/code&gt;; what's in it?&lt;/p&gt;
         3271 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;_StyleValueData&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         3272     &lt;span class="n"&gt;gchar&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         3273     &lt;span class="n"&gt;gboolean&lt;/span&gt; &lt;span class="n"&gt;important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         3274 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;StyleValueData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         3275 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3276 
         3277 &lt;p&gt;The &lt;code&gt;value&lt;/code&gt; is another string.  Strings all the way!&lt;/p&gt;
         3278 &lt;p&gt;At the time, I didn't really figure out what each level of nested hash
         3279 tables was supposed to mean.  I didn't understand why we handled style
         3280 properties in a completely different part of the code, and yet this
         3281 part had a &lt;code&gt;css_props&lt;/code&gt; field that didn't seem to store properties at all.&lt;/p&gt;
         3282 &lt;p&gt;It took a while to realize that &lt;code&gt;css_props&lt;/code&gt; was misnamed.  It wasn't
         3283 storing a mapping of selector names to properties; it was storing a
         3284 mapping of selector names to &lt;strong&gt;declaration lists&lt;/strong&gt;, which are lists of
         3285 property/value pairs.&lt;/p&gt;
         3286 &lt;p&gt;So, when I started &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/08f28816868878962647651118d5a1eb95d06d17"&gt;porting the CSS parsing code to
         3287 Rust&lt;/a&gt;,
         3288 I started to create real types with for each concept.&lt;/p&gt;
         3289 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Maps property_name -&amp;gt; Declaration&lt;/span&gt;
         3290 &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;DeclarationList&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Declaration&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3291 
         3292 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;CssStyles&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3293 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;selectors_to_declarations&lt;/span&gt;: &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DeclarationList&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3294 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3295 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3296 
         3297 &lt;p&gt;Even though the keys of those HashMaps are still strings, because
         3298 librsvg didn't have a better way to represent their corresponding
         3299 concepts, at least those declarations let one see what the hell is
         3300 being stored without grepping the rest of the code.  This is a part of
         3301 the code that I didn't really touch very much, so it was nice to have
         3302 that reminder.&lt;/p&gt;
         3303 &lt;p&gt;The &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/12dd9b1bb039484ce273228049f96f8e39d2f339"&gt;first port of the CSS matching code to
         3304 Rust&lt;/a&gt;
         3305 kept the same algorithm as the C code, the one that created strings
         3306 with &lt;code&gt;element.class&lt;/code&gt; and compared them to the stored selector names.
         3307 Ugly, but it still worked in the same limited fashion.&lt;/p&gt;
         3308 &lt;h2&gt;Rustifying the CSS parsers&lt;/h2&gt;
         3309 &lt;p&gt;It turns out that CSS parsing is divided in two parts.  One can have a
         3310 &lt;code&gt;style&lt;/code&gt; attribute inside an element, for example&lt;/p&gt;
         3311 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;100&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;100&amp;quot;&lt;/span&gt;
         3312       &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fill: green; stroke: magenta; stroke-width: 4;&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         3313 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3314 
         3315 &lt;p&gt;This is a plain declaration list which is not associated to any
         3316 selectors, and which is applied directly to just the element in which it
         3317 appears.&lt;/p&gt;
         3318 &lt;p&gt;Then, there is the &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; element itself, with a normal-looking CSS stylesheet&lt;/p&gt;
         3319 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         3320   rect {
         3321     fill: green;
         3322     stroke: magenta;
         3323     stroke-width: 4;
         3324   }
         3325 &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
         3326 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3327 
         3328 &lt;p&gt;This means that all &lt;code&gt;&amp;lt;rect&amp;gt;&lt;/code&gt; elements will get that style applied.&lt;/p&gt;
         3329 &lt;p&gt;I started to look for existing Rust crates to parse and handle CSS
         3330 data.  The &lt;a href="https://docs.rs/cssparser/"&gt;cssparser&lt;/a&gt; and
         3331 &lt;a href="https://docs.rs/selectors/"&gt;selectors&lt;/a&gt; crates come from Mozilla, so
         3332 I thought they should do a pretty good job of things.&lt;/p&gt;
         3333 &lt;p&gt;And they do!  Except that they are not a drop-in replacement for
         3334 anything.  They are what gets used in Mozilla's Servo browser engine,
         3335 so they are optimized to hell, and the code can be pretty intimidating.&lt;/p&gt;
         3336 &lt;p&gt;Out of the box, cssparser provides a CSS tokenizer, but it does
         3337 not know how to handle any properties/values in particular.  One must
         3338 use the tokenizer to implement a parser for each kind of CSS property
         3339 one wants to support — Servo has mountains of code for all of HTML's
         3340 style properties, and librsvg had to provide a smaller mountain of code
         3341 for SVG style properties.&lt;/p&gt;
         3342 &lt;p&gt;Thus started the big task of porting librsvg's string-based parsers
         3343 for CSS properties into ones based on cssparser tokens.  Cssparser
         3344 provides a &lt;code&gt;Parser&lt;/code&gt; struct, which extracts tokens out of a CSS
         3345 stream.  Out of this, librsvg defines a &lt;code&gt;Parse&lt;/code&gt; trait for parsable
         3346 things:&lt;/p&gt;
         3347 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cssparser&lt;/span&gt;::&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3348 
         3349 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;: &lt;span class="nb"&gt;Sized&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3350 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3351 
         3352 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="nb"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nb"&gt;_&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;::&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3353 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3354 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3355 
         3356 &lt;p&gt;What's with those two default lifetimes in &lt;code&gt;Parser&amp;lt;'_, '_&amp;gt;&lt;/code&gt;?
         3357 Cssparser tries very hard to be a zero-copy tokenizer.  One of the
         3358 lifetimes refers to the input string which is wrapped in a
         3359 &lt;code&gt;Tokenizer&lt;/code&gt;, which is wrapped in a &lt;code&gt;ParserInput&lt;/code&gt;.  The other lifetime
         3360 is for the &lt;code&gt;ParserInput&lt;/code&gt; itself.&lt;/p&gt;
         3361 &lt;p&gt;In the actual implementation of that trait, the &lt;code&gt;Err&lt;/code&gt; type also uses
         3362 the lifetime that refers to the input string.  For example, there is a
         3363 &lt;code&gt;BasicParseErrorKind::UnexpectedToken(Token&amp;lt;'i&amp;gt;)&lt;/code&gt;, which one returns
         3364 when there is an unexpected token.  And to avoid copying the substring
         3365 into the error, one returns a slice reference into the original
         3366 string, thus the lifetime.&lt;/p&gt;
         3367 &lt;p&gt;I was more of a Rust newbie back then, and it was very hard to make
         3368 sense of how cssparser was meant to be used.&lt;/p&gt;
         3369 &lt;p&gt;The process was more or less this:&lt;/p&gt;
         3370 &lt;ul&gt;
         3371 &lt;li&gt;
         3372 &lt;p&gt;Port the C parsers to Rust; implement types for each CSS property.&lt;/p&gt;
         3373 &lt;/li&gt;
         3374 &lt;li&gt;
         3375 &lt;p&gt;Port the &lt;code&gt;&amp;amp;str&lt;/code&gt;-based parsers into ones that use &lt;code&gt;cssparser&lt;/code&gt;.&lt;/p&gt;
         3376 &lt;/li&gt;
         3377 &lt;li&gt;
         3378 &lt;p&gt;Fix the error handling scheme to match what cssparser's high-level
         3379   traits expect.&lt;/p&gt;
         3380 &lt;/li&gt;
         3381 &lt;/ul&gt;
         3382 &lt;p&gt;This last point was... hard.  Again, I wasn't comfortable enough with
         3383 Rust lifetimes and nested generics; in the end it was all right.&lt;/p&gt;
         3384 &lt;h2&gt;Moving declaration lists to Rust&lt;/h2&gt;
         3385 &lt;p&gt;With the individual parsers for CSS properties done, and with them
         3386 already using a different type for each property, the next thing was
         3387 to implement cssparser's traits to parse declaration lists.&lt;/p&gt;
         3388 &lt;p&gt;Again, a declaration list looks like this:&lt;/p&gt;
         3389 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;blue&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
         3390 &lt;span class="nt"&gt;stroke-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;4&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
         3391 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3392 
         3393 &lt;p&gt;It's essentially a key/value list.&lt;/p&gt;
         3394 &lt;p&gt;The trait that cssparser wants us to implement is this:&lt;/p&gt;
         3395 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DeclarationParser&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3396 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Declaration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3397 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;: &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3398 
         3399 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse_value&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;t&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3400 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3401 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;: &lt;span class="nc"&gt;CowRcStr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3402 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;t&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3403 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;Declaration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3404 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3405 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3406 
         3407 &lt;p&gt;That is, define a type for a &lt;code&gt;Declaration&lt;/code&gt;, and implement a
         3408 &lt;code&gt;parse_value()&lt;/code&gt; method that takes a &lt;code&gt;name&lt;/code&gt; and a &lt;code&gt;Parser&lt;/code&gt;, and outputs
         3409 a &lt;code&gt;Declaration&lt;/code&gt; or an error.&lt;/p&gt;
         3410 &lt;p&gt;What this &lt;em&gt;really&lt;/em&gt; means is that the type you implement for
         3411 &lt;code&gt;Declaration&lt;/code&gt; needs to be able to represent all the CSS property types
         3412 that you care about.  Thus, a struct plus a big enum like this:&lt;/p&gt;
         3413 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Declaration&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3414 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prop_name&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3415 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;property&lt;/span&gt;: &lt;span class="nc"&gt;ParsedProperty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3416 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;important&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3417 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3418 
         3419 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;ParsedProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3420 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;BaselineShift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BaselineShift&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3421 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ClipPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ClipPath&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3422 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ClipRule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ClipRule&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3423 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3424 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ColorInterpolationFilters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ColorInterpolationFilters&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3425 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SpecifiedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3426 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3427 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3428 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3429 
         3430 &lt;p&gt;This gives us declaration lists (the stuff inside curly braces in a
         3431 CSS stylesheet), but it doesn't give us qualified rules, which are
         3432 composed of selector names plus a declaration list.&lt;/p&gt;
         3433 &lt;h2&gt;Refactoring towards real CSS concepts&lt;/h2&gt;
         3434 &lt;p&gt;Paolo Borelli has been steadily refactoring librsvg and fixing things
         3435 like the primitive obsession I mentioned above.  We now have real
         3436 concepts like a Document, Stylesheet, QualifiedRule, Rule, AtRule.&lt;/p&gt;
         3437 &lt;p&gt;This refactoring took a long time, because it involved redoing the XML
         3438 loading code and its interaction with the CSS parser a few times.&lt;/p&gt;
         3439 &lt;h2&gt;Implementing traits from the selectors crate&lt;/h2&gt;
         3440 &lt;p&gt;The &lt;a href="https://docs.rs/selectors"&gt;selectors&lt;/a&gt; crate
         3441 contains Servo's code for parsing CSS selectors and doing matching.
         3442 However, it is &lt;em&gt;extremely&lt;/em&gt; generic.  Using it involves implementing a
         3443 good number of concepts.&lt;/p&gt;
         3444 &lt;p&gt;For example, this &lt;code&gt;SelectorImpl&lt;/code&gt; trait has no methods, and is just a
         3445 collection of types that refer to your implementation of an element
         3446 tree.  How do you represent an attribute/value?  How do you represent
         3447 an identifier?  How do you represent a namespace and a local name?&lt;/p&gt;
         3448 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SelectorImpl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3449 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;ExtraMatchingData&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3450 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;AttrValue&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3451 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Identifier&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3452 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;ClassName&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3453 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;PartName&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3454 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;LocalName&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3455 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;NamespaceUrl&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3456 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;NamespacePrefix&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3457 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;BorrowedNamespaceUrl&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3458 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;BorrowedLocalName&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3459 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;NonTSPseudoClass&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3460 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;PseudoElement&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3461 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3462 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3463 
         3464 &lt;p&gt;A lot of those can be &lt;code&gt;String&lt;/code&gt;, but Servo has smarter things in store.
         3465 I ended up using the &lt;a href="https://docs.rs/markup5ever"&gt;&lt;code&gt;markup5ever&lt;/code&gt;&lt;/a&gt; crate, which provides a string
         3466 interning framework for markup and XML concepts like a &lt;code&gt;LocalName&lt;/code&gt;, a
         3467 &lt;code&gt;Namespace&lt;/code&gt;, etc.  This reduces memory consumption, because instead of
         3468 storing string copies of element names everywhere, one just stores
         3469 tokens for interned strings.&lt;/p&gt;
         3470 &lt;p&gt;(In the meantime I had to implement support for XML namespaces, which
         3471 the selectors code really wants, but which librsvg never supported.)&lt;/p&gt;
         3472 &lt;p&gt;Then, the selectors crate wants you to say how your code implements an
         3473 element tree.  It has a monster trait &lt;code&gt;Element&lt;/code&gt;:&lt;/p&gt;
         3474 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3475 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Impl&lt;/span&gt;: &lt;span class="nc"&gt;SelectorImpl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3476 
         3477 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;opaque&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;OpaqueElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3478 
         3479 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parent_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3480 
         3481 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parent_node_is_shadow_root&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3482 
         3483 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3484 
         3485 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;prev_sibling_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3486 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;next_sibling_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3487 
         3488 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;has_local_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3489 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
         3490 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;local_name&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;Impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SelectorImpl&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;::&lt;span class="n"&gt;BorrowedLocalName&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3491 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3492 
         3493 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;has_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3494 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3495 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;Impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SelectorImpl&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;::&lt;span class="n"&gt;Identifier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3496 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;case_sensitivity&lt;/span&gt;: &lt;span class="nc"&gt;CaseSensitivity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3497 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3498 
         3499 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3500 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         3501 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3502 
         3503 &lt;p&gt;That is, when you provide an implementation of &lt;code&gt;Element&lt;/code&gt; and
         3504 &lt;code&gt;SelectorImpl&lt;/code&gt;, the selectors crate will know how to navigate your
         3505 element tree and ask it questions like, "does this element have the id
         3506 &lt;code&gt;#foo&lt;/code&gt;?"; "does this element have the name &lt;code&gt;rect&lt;/code&gt;?".  It makes perfect
         3507 sense in the end, but it is quite intimidating when you are not 100%
         3508 comfortable with webs of traits and associated types and generics with
         3509 a bunch of trait bounds!&lt;/p&gt;
         3510 &lt;p&gt;I tried implementing that trait twice in the last year, and failed.
         3511 It turns out that its API &lt;a href="https://github.com/servo/servo/issues/22972"&gt;needed a key
         3512 fix&lt;/a&gt; that landed last
         3513 June, but I didn't notice until a couple of weeks ago.&lt;/p&gt;
         3514 &lt;h2&gt;So?&lt;/h2&gt;
         3515 &lt;p&gt;Two days ago, Paolo and I committed the &lt;a href="https://gitlab.gnome.org/federico/librsvg/merge_requests/6"&gt;last code to be able to
         3516 completely replace
         3517 libcroco&lt;/a&gt;.&lt;/p&gt;
         3518 &lt;p&gt;And, after implementing CSS &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/525"&gt;specificity&lt;/a&gt; (which was easy now that we
         3519 have real CSS concepts and a good pipeline for the CSS cascade), a
         3520 bunch of very old bugs started falling down
         3521 (&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/336"&gt;1&lt;/a&gt;
         3522 &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/466"&gt;2&lt;/a&gt;
         3523 &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/428"&gt;3&lt;/a&gt;
         3524 &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/167"&gt;4&lt;/a&gt;
         3525 &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/79"&gt;5&lt;/a&gt;
         3526 &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/441"&gt;6&lt;/a&gt;).&lt;/p&gt;
         3527 &lt;p&gt;Now it is going to be easy to implement things like &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/379"&gt;letting the
         3528 application specify a user
         3529 stylesheet&lt;/a&gt;.  In
         3530 particular, this should let GTK remove the &lt;a href="https://gitlab.gnome.org/GNOME/gtk/blob/ad48bbb8/gtk/gtkicontheme.c#L3728-3750"&gt;rather egregious
         3531 hack&lt;/a&gt;
         3532 it has to recolor SVG icons while using librsvg indirectly.&lt;/p&gt;
         3533 &lt;h2&gt;Conclusion&lt;/h2&gt;
         3534 &lt;p&gt;This will appear in librsvg 2.47.1 — that version will no longer
         3535 require libcroco.&lt;/p&gt;
         3536 &lt;p&gt;As far as I know, the only module that still depends on libcroco (in
         3537 GNOME or otherwise) is &lt;strong&gt;gnome-shell&lt;/strong&gt;.  It uses libcroco to parse CSS
         3538 and get the basic structure of selectors so it can implement matching
         3539 by hand.&lt;/p&gt;
         3540 &lt;p&gt;Gnome-shell has some code which looks awfully similar to what librsvg
         3541 had when it was written in C:&lt;/p&gt;
         3542 &lt;ul&gt;
         3543 &lt;li&gt;
         3544 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/gnome-shell/blob/66fc5c07/src/st/st-theme.c"&gt;StTheme&lt;/a&gt;
         3545   has the high-level CSS stylesheet parser and the selector matching code.&lt;/p&gt;
         3546 &lt;/li&gt;
         3547 &lt;li&gt;
         3548 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/gnome-shell/blob/66fc5c07/src/st/st-theme-node.c"&gt;StThemeNode&lt;/a&gt;
         3549   has the low-level CSS property parsers.&lt;/p&gt;
         3550 &lt;/li&gt;
         3551 &lt;/ul&gt;
         3552 &lt;p&gt;... and it turns out that those files come all the way from
         3553 &lt;a href="https://blog.ometer.com/2006/10/14/text-layout-that-works-properly/"&gt;HippoCanvas&lt;/a&gt;,
         3554 the CSS-aware canvas that Mugshot used!  Mugshot was a circa-2006
         3555 pre-Facebook aggregator for social media data like blogs, Flickr
         3556 pictures, etc.  HippoCanvas also got used in Sugar, the GUI for
         3557 One Laptop Per Child.  Yes, our code is &lt;em&gt;that&lt;/em&gt; old.&lt;/p&gt;
         3558 &lt;p&gt;Libcroco is unmaintained, and has outstanding CVEs.  I would be very
         3559 happy to assist someone in porting gnome-shell's CSS code to Rust :)&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category><category term="rust"></category></entry><entry><title>Gdk-pixbuf modules - call for help</title><link href="https://people.gnome.org/~federico/blog/gdk-pixbuf-modules.html" rel="alternate"></link><published>2019-09-11T17:54:03-05:00</published><updated>2019-09-12T13:15:17-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-09-11:/~federico/blog/gdk-pixbuf-modules.html</id><summary type="html">&lt;p&gt;I've been doing a little refactoring of gdk-pixbuf's crufty code, to
         3560 see if the gripes from my &lt;a href="https://people.gnome.org/~federico/blog/my-gdk-pixbuf-braindump.html"&gt;braindump&lt;/a&gt; can be solved.  For
         3561 things where it is not obvious how to proceed, I've started taking
         3562 more detailed notes in a &lt;a href="https://gitlab.gnome.org/federico/gdk-pixbuf-survey"&gt;gdk-pixbuf survey&lt;/a&gt;.&lt;/p&gt;
         3563 &lt;p&gt;Today I was looking at which &lt;a href="https://gitlab.gnome.org/federico/gdk-pixbuf-survey/blob/master/src/modules.md"&gt;gdk-pixbuf modules&lt;/a&gt; are …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I've been doing a little refactoring of gdk-pixbuf's crufty code, to
         3564 see if the gripes from my &lt;a href="https://people.gnome.org/~federico/blog/my-gdk-pixbuf-braindump.html"&gt;braindump&lt;/a&gt; can be solved.  For
         3565 things where it is not obvious how to proceed, I've started taking
         3566 more detailed notes in a &lt;a href="https://gitlab.gnome.org/federico/gdk-pixbuf-survey"&gt;gdk-pixbuf survey&lt;/a&gt;.&lt;/p&gt;
         3567 &lt;p&gt;Today I was looking at which &lt;a href="https://gitlab.gnome.org/federico/gdk-pixbuf-survey/blob/master/src/modules.md"&gt;gdk-pixbuf modules&lt;/a&gt; are
         3568 implemented by third parties, that is, which external projects provide
         3569 their own image codecs pluggable into gdk-pixbuf.&lt;/p&gt;
         3570 &lt;p&gt;And there are not that many!&lt;/p&gt;
         3571 &lt;p&gt;The only four that I found are &lt;strong&gt;libheif, libopenraw, libwmf,
         3572 librsvg&lt;/strong&gt; (this last one, of course).&lt;/p&gt;
         3573 &lt;p&gt;&lt;em&gt;Update 2019/Sep/12&lt;/em&gt; - Added &lt;strong&gt;apng, exif-raw, psd, pvr, vtf, webp, xcf&lt;/strong&gt;.&lt;/p&gt;
         3574 &lt;p&gt;All of those use the gdk-pixbuf module API in a remarkably similar
         3575 fashion.  Did they cut&amp;amp;paste each other's code?  Did they do the
         3576 simplest thing that didn't crash in gdk-pixbuf's checks for buggy
         3577 loaders, which happens to be exactly what they do?  Who knows!  Either
         3578 way, this makes future API changes in the modules a lot easier, since
         3579 they all do the same right now.&lt;/p&gt;
         3580 &lt;p&gt;I'm trying to decide between these:&lt;/p&gt;
         3581 &lt;ul&gt;
         3582 &lt;li&gt;
         3583 &lt;p&gt;Keep modules as they are; find a way to sandbox them from gdk-pixbuf
         3584   itself.  This is hard because the API is "chatty"; modules and
         3585   calling code go back and forth peeking at each other's structures.&lt;/p&gt;
         3586 &lt;/li&gt;
         3587 &lt;li&gt;
         3588 &lt;p&gt;Decide that third-party modules are only useful for thumbnailers;
         3589   modify them to &lt;em&gt;be&lt;/em&gt; thumbnailers instead of generic gdk-pixbuf
         3590   modules.  This would mean that those formats would stop working
         3591   automatically in gdk-pixbuf based viewers like EOG.&lt;/p&gt;
         3592 &lt;/li&gt;
         3593 &lt;li&gt;
         3594 &lt;p&gt;Have "blessed" codecs inside gdk-pixbuf which are not modules so
         3595   their no longer have API/ABI stability constraints.  Keep
         3596   third-party modules separate.  Sandbox the internal ones with a
         3597   non-chatty API.&lt;/p&gt;
         3598 &lt;/li&gt;
         3599 &lt;li&gt;
         3600 &lt;p&gt;If all third-party modules work indeed as &lt;a href="https://gitlab.gnome.org/federico/gdk-pixbuf-survey/blob/master/src/modules.md"&gt;I found&lt;/a&gt;, the
         3601   module API can be simplified quite a lot since no third-party
         3602   modules implement animations or saving.  If so, simplify the module
         3603   API and the gdk-pixbuf internals rather drastically.&lt;/p&gt;
         3604 &lt;/li&gt;
         3605 &lt;/ul&gt;
         3606 &lt;p&gt;Do you know any other image formats which provide &lt;a href="https://gitlab.gnome.org/federico/gdk-pixbuf-survey/blob/master/src/modules.md"&gt;gdk-pixbuf
         3607 modules&lt;/a&gt;?  &lt;a href="mailto:federico@gnome.org"&gt;Mail me, please!&lt;/a&gt;&lt;/p&gt;</content><category term="misc"></category><category term="gdk-pixbuf"></category></entry><entry><title>On responsible vulnerability disclosure</title><link href="https://people.gnome.org/~federico/blog/on-responsible-vulnerability-disclosure.html" rel="alternate"></link><published>2019-08-10T21:05:34-05:00</published><updated>2019-08-10T21:05:34-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-08-10:/~federico/blog/on-responsible-vulnerability-disclosure.html</id><summary type="html">&lt;p&gt;Recently KDE had an unfortunate event.  Someone &lt;a href="https://gist.github.com/zeropwn/630832df151029cb8f22d5b6b9efaefb"&gt;found a
         3608 vulnerability&lt;/a&gt; in the code that processes &lt;code&gt;.desktop&lt;/code&gt; and
         3609 &lt;code&gt;.directory&lt;/code&gt; files, through which an attacker could create a malicious
         3610 file that causes shell command execution (&lt;a href="https://paper.seebug.org/1008/"&gt;analysis&lt;/a&gt;).  They went for immediate,
         3611 full disclosure, where KDE didn't even get a chance of fixing the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Recently KDE had an unfortunate event.  Someone &lt;a href="https://gist.github.com/zeropwn/630832df151029cb8f22d5b6b9efaefb"&gt;found a
         3612 vulnerability&lt;/a&gt; in the code that processes &lt;code&gt;.desktop&lt;/code&gt; and
         3613 &lt;code&gt;.directory&lt;/code&gt; files, through which an attacker could create a malicious
         3614 file that causes shell command execution (&lt;a href="https://paper.seebug.org/1008/"&gt;analysis&lt;/a&gt;).  They went for immediate,
         3615 full disclosure, where KDE didn't even get a chance of fixing the bug
         3616 before it was published.&lt;/p&gt;
         3617 &lt;p&gt;There are many protocols for &lt;a href="https://en.wikipedia.org/wiki/Responsible_disclosure"&gt;disclosing vulnerabilities in a
         3618 coordinated, responsible fashion&lt;/a&gt;, but the gist of them is this:&lt;/p&gt;
         3619 &lt;ol&gt;
         3620 &lt;li&gt;
         3621 &lt;p&gt;Someone finds a vulnerability in some software through studying
         3622    some code, or some other mechanism.&lt;/p&gt;
         3623 &lt;/li&gt;
         3624 &lt;li&gt;
         3625 &lt;p&gt;They report the vulnerability to the software's author through some
         3626    private channel.  For free softare in particular, researchers can
         3627    use &lt;a href="https://oss-security.openwall.org/wiki/disclosure/researcher"&gt;Openwall's recommended process for
         3628    researchers&lt;/a&gt;, which includes &lt;strong&gt;notifying the
         3629    author/maintainer and distros and security groups.&lt;/strong&gt;  Free
         3630    software projects can &lt;a href="https://alexgaynor.net/2013/oct/19/security-process-open-source-projects/"&gt;follow a well-established process&lt;/a&gt;.&lt;/p&gt;
         3631 &lt;/li&gt;
         3632 &lt;li&gt;
         3633 &lt;p&gt;The author and reporter agree on a deadline for releasing a public
         3634    report of the vulnerability, or in semi-automated systems like
         3635    Google Zero, a deadline is automatically established.&lt;/p&gt;
         3636 &lt;/li&gt;
         3637 &lt;li&gt;
         3638 &lt;p&gt;The author works on fixing the vulnerability.&lt;/p&gt;
         3639 &lt;/li&gt;
         3640 &lt;li&gt;
         3641 &lt;p&gt;The deadline is reached; the patch has been publically released,
         3642    the appropriate people have been notified, systems have been
         3643    patched.  If there is no patch, the author and reporter can agree
         3644    on postponing the date, or the reporter can publish the
         3645    vulnerability report, thus creating public pressure for a fix.&lt;/p&gt;
         3646 &lt;/li&gt;
         3647 &lt;/ol&gt;
         3648 &lt;p&gt;The steps above gloss over many practicalities and issues from the
         3649 real world, but the idea is basically this:  the author or maintainer
         3650 of the software is given a chance to fix a security bug before
         3651 information on the vulnerability is released to the hostile world.
         3652 The idea is to &lt;strong&gt;keep harm from being done&lt;/strong&gt; by not publishing
         3653 unpatched vulnerabilities until there is a fix for them (... or until
         3654 the deadline expires).&lt;/p&gt;
         3655 &lt;h2&gt;What happened instead&lt;/h2&gt;
         3656 &lt;p&gt;Around the beginning of July, the reporter &lt;a href="https://twitter.com/zer0pwn/status/1146554083056193536"&gt;posts about looking for
         3657 bugs in KDE&lt;/a&gt;.&lt;/p&gt;
         3658 &lt;p&gt;On &lt;a href="https://twitter.com/zer0pwn/status/1156312405472923648"&gt;July 30&lt;/a&gt;, he posts a video with the proof of concept.&lt;/p&gt;
         3659 &lt;p&gt;On August 3, he &lt;a href="https://twitter.com/zer0pwn/status/1157760759289528321"&gt;makes a Twitter poll&lt;/a&gt; about what to do with the
         3660 vulnerability.&lt;/p&gt;
         3661 &lt;p&gt;On August 4, he &lt;a href="https://twitter.com/zer0pwn/status/1158167374799020039"&gt;publishes the vulnerability&lt;/a&gt;.&lt;/p&gt;
         3662 &lt;p&gt;KDE is left with having to patch this in emergency mode.  On August 7,
         3663 KDE releases a &lt;a href="https://kde.org/info/security/advisory-20190807-1.txt"&gt;security advisory&lt;/a&gt; in perfect form:&lt;/p&gt;
         3664 &lt;ul&gt;
         3665 &lt;li&gt;
         3666 &lt;p&gt;Description of exactly what causes the vulnerability.&lt;/p&gt;
         3667 &lt;/li&gt;
         3668 &lt;li&gt;
         3669 &lt;p&gt;Description of how it was solved.&lt;/p&gt;
         3670 &lt;/li&gt;
         3671 &lt;li&gt;
         3672 &lt;p&gt;Instructions on what to do for users of various versions of KDE
         3673   libraries.&lt;/p&gt;
         3674 &lt;/li&gt;
         3675 &lt;li&gt;
         3676 &lt;p&gt;Links to easy-to-cherry-pick patches for distro vendors.&lt;/p&gt;
         3677 &lt;/li&gt;
         3678 &lt;/ul&gt;
         3679 &lt;p&gt;Now, distro vendors are, in turn, in emergency mode, as they must
         3680 apply the patch, run it through QA, release their own advisories,
         3681 etc.&lt;/p&gt;
         3682 &lt;h2&gt;What if this had been done with coordinated disclosure?&lt;/h2&gt;
         3683 &lt;p&gt;The bug would have been fixed, probably in the same way, &lt;em&gt;but it would
         3684 not be in emergency mode&lt;/em&gt;.  &lt;a href="https://kde.org/info/security/advisory-20190807-1.txt"&gt;KDE's advisory&lt;/a&gt; contains this:&lt;/p&gt;
         3685 &lt;blockquote&gt;
         3686 &lt;p&gt;Thanks to Dominik Penner for finding and documenting this issue (we wish however that he would
         3687 have contacted us before making the issue public) and to David Faure for the fix.&lt;/p&gt;
         3688 &lt;/blockquote&gt;
         3689 &lt;p&gt;This is an extremely gracious way of thanking the reporter.&lt;/p&gt;
         3690 &lt;h2&gt;I am not an infosec person...&lt;/h2&gt;
         3691 &lt;p&gt;... but some behaviors in the infosec sphere are deeply uncomfortable
         3692 to me.  I don't like it when security "research" is hard to tell from
         3693 vandalism.  "Excuse me, you left your car door unlocked" vs. "Hey
         3694 everyone, this car is unlocked, have at it".&lt;/p&gt;
         3695 &lt;p&gt;I don't know the details of the discourse in the infosec sphere around
         3696 full disclosure against irresponsible vendors of proprietary software or
         3697 services.  However, &lt;strong&gt;KDE is free software&lt;/strong&gt;!  There is no need to be
         3698 an asshole to them.&lt;/p&gt;</content><category term="misc"></category><category term="security"></category><category term="kde"></category></entry><entry><title>Constructors</title><link href="https://people.gnome.org/~federico/blog/constructors.html" rel="alternate"></link><published>2019-07-24T13:59:01-05:00</published><updated>2019-07-24T13:59:01-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-07-24:/~federico/blog/constructors.html</id><summary type="html">&lt;p&gt;Have you ever had these annoyances with GObject-style constructors?&lt;/p&gt;
         3699 &lt;ul&gt;
         3700 &lt;li&gt;
         3701 &lt;p&gt;From a constructor, calling a method on a partially-constructed
         3702   object is dangerous.&lt;/p&gt;
         3703 &lt;/li&gt;
         3704 &lt;li&gt;
         3705 &lt;p&gt;A constructor needs to set up "not quite initialized" values in the
         3706   instance struct until a construct-time property is set.&lt;/p&gt;
         3707 &lt;/li&gt;
         3708 &lt;li&gt;
         3709 &lt;p&gt;You actually need to override &lt;code&gt;GObjectClass::constructed&lt;/code&gt; (or was …&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Have you ever had these annoyances with GObject-style constructors?&lt;/p&gt;
         3710 &lt;ul&gt;
         3711 &lt;li&gt;
         3712 &lt;p&gt;From a constructor, calling a method on a partially-constructed
         3713   object is dangerous.&lt;/p&gt;
         3714 &lt;/li&gt;
         3715 &lt;li&gt;
         3716 &lt;p&gt;A constructor needs to set up "not quite initialized" values in the
         3717   instance struct until a construct-time property is set.&lt;/p&gt;
         3718 &lt;/li&gt;
         3719 &lt;li&gt;
         3720 &lt;p&gt;You actually need to override &lt;code&gt;GObjectClass::constructed&lt;/code&gt; (or was it
         3721   &lt;code&gt;::constructor&lt;/code&gt;?) to take care of construct-only properties which
         3722   need to be considered together, not individually.&lt;/p&gt;
         3723 &lt;/li&gt;
         3724 &lt;li&gt;
         3725 &lt;p&gt;Constructors can't report an error, unless you derive from
         3726   &lt;code&gt;GInitable&lt;/code&gt;, which is not in gobject, but in gio instead.  (Also,
         3727   why does &lt;em&gt;that&lt;/em&gt; force the constructor to take a &lt;code&gt;GCancellable&lt;/code&gt;...?)&lt;/p&gt;
         3728 &lt;/li&gt;
         3729 &lt;li&gt;
         3730 &lt;p&gt;You need more than one constructor, but that needs to be done with
         3731   helper functions.&lt;/p&gt;
         3732 &lt;/li&gt;
         3733 &lt;/ul&gt;
         3734 &lt;p&gt;This article, &lt;a href="https://matklad.github.io/2019/07/16/perils-of-constructors.html"&gt;Perils of
         3735 Constructors&lt;/a&gt;,
         3736 explains all of these problems very well.  It is not centered on
         3737 GObject, but rather on constructors in object-oriented languages in
         3738 general.&lt;/p&gt;
         3739 &lt;p&gt;(Spoiler: Rust does not have constructors or partially-initialized structs, so
         3740 these problems don't really exist there.)&lt;/p&gt;
         3741 &lt;p&gt;(Addendum: &lt;em&gt;that&lt;/em&gt; makes it somewhat awkward to convert GObject code in
         3742 C to Rust, but librsvg was able to solve it nicely with
         3743 &lt;code&gt;&amp;lt;buzzword&amp;gt;&lt;/code&gt;&lt;a href="http://cliffle.com/blog/rust-typestate/"&gt;the typestate pattern&lt;/a&gt;&lt;code&gt;&amp;lt;/buzzword&amp;gt;&lt;/code&gt;.)&lt;/p&gt;</content><category term="misc"></category><category term="GObject"></category><category term="rust"></category></entry><entry><title>Gtk-rs tutorial</title><link href="https://people.gnome.org/~federico/blog/gtk-rs-tutorial.html" rel="alternate"></link><published>2019-07-08T18:36:11-05:00</published><updated>2019-07-08T18:36:11-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-07-08:/~federico/blog/gtk-rs-tutorial.html</id><content type="html">&lt;p&gt;&lt;a href="https://cybre.space/@tindall"&gt;Leonora Tindall&lt;/a&gt; has written a
         3744 very nice tutorial on &lt;a href="https://nora.codes/tutorial/speedy-desktop-apps-with-gtk-and-rust/"&gt;Speedy Desktop Apps With GTK and
         3745 Rust&lt;/a&gt;.
         3746 It covers prototyping a dice roller app with Glade, writing the code with
         3747 Rust and the gtk-rs bindings, and integrating the app into the desktop with
         3748 a &lt;code&gt;.desktop&lt;/code&gt; file.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="gnome"></category></entry><entry><title>Removing rsvg-view</title><link href="https://people.gnome.org/~federico/blog/removing-rsvg-view.html" rel="alternate"></link><published>2019-07-02T11:36:59-05:00</published><updated>2019-07-02T11:36:59-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-07-02:/~federico/blog/removing-rsvg-view.html</id><summary type="html">&lt;p&gt;I am preparing the 2.46.0 librsvg release.  &lt;strong&gt;This will no longer have
         3749 the rsvg-view-3 program.&lt;/strong&gt;&lt;/p&gt;
         3750 &lt;h2&gt;History of rsvg-view&lt;/h2&gt;
         3751 &lt;p&gt;Rsvg-view &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/c56e236c5b5fa89c365b87ac59bd476d67c5ee27/test-display.c"&gt;started
         3752 out&lt;/a&gt;
         3753 as a 71-line C program to aid development of librsvg.  It would just
         3754 render an SVG file to a pixbuf, stick that pixbuf in a &lt;code&gt;GtkImage&lt;/code&gt;
         3755 widget …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I am preparing the 2.46.0 librsvg release.  &lt;strong&gt;This will no longer have
         3756 the rsvg-view-3 program.&lt;/strong&gt;&lt;/p&gt;
         3757 &lt;h2&gt;History of rsvg-view&lt;/h2&gt;
         3758 &lt;p&gt;Rsvg-view &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/c56e236c5b5fa89c365b87ac59bd476d67c5ee27/test-display.c"&gt;started
         3759 out&lt;/a&gt;
         3760 as a 71-line C program to aid development of librsvg.  It would just
         3761 render an SVG file to a pixbuf, stick that pixbuf in a &lt;code&gt;GtkImage&lt;/code&gt;
         3762 widget, and show a window with that.&lt;/p&gt;
         3763 &lt;p&gt;Over time, it slowly acquired most of the command-line options that
         3764 &lt;code&gt;rsvg-convert&lt;/code&gt; supports.  And I suppose, as a way of testing the
         3765 Cairo-ification of librsvg, it also got the ability to print SVG files
         3766 to a &lt;code&gt;GtkPrintContext&lt;/code&gt;.  At last count, it was a 784-line C program
         3767 that is not really the best code in the world.&lt;/p&gt;
         3768 &lt;h2&gt;What makes rsvg-view awkward?&lt;/h2&gt;
         3769 &lt;p&gt;Rsvg-view requires GTK.  But GTK requires librsvg, indirectly, through
         3770 gdk-pixbuf!  There is not a hard circular dependency because GTK goes,
         3771 "gdk-pixbuf, load me this SVG file" without knowing how it will be
         3772 loaded.  In turn, gdk-pixbuf initializes the SVG loader provided by
         3773 librsvg, and that loader reads/renders the SVG file.&lt;/p&gt;
         3774 &lt;p&gt;Ideally librsvg would only depend on gdk-pixbuf, so it would be able
         3775 to provide the SVG loader.&lt;/p&gt;
         3776 &lt;p&gt;The rsvg-view source code still has a few calls to GTK functions which
         3777 are now deprecated.  The program emits GTK warnings during normal use.&lt;/p&gt;
         3778 &lt;p&gt;Rsvg-view is... not a very good SVG viewer.  It doesn't even start up
         3779 with the window scaled properly to the SVG's dimensions!  If used for
         3780 quick testing during development, it cannot even aid in viewing the
         3781 transparent background regions which the SVG does not cover.  It just
         3782 sticks a lousy custom widget inside a &lt;code&gt;GtkScrolledWindow&lt;/code&gt;, and does
         3783 not have the conventional niceties to view images like zooming with
         3784 the scroll wheel.&lt;/p&gt;
         3785 &lt;p&gt;&lt;a href="https://wiki.gnome.org/Apps/EyeOfGnome/"&gt;EOG&lt;/a&gt; is a much better SVG viewer than rsvg-view, and people actually
         3786 invest effort in making it pleasant to use.&lt;/p&gt;
         3787 &lt;h2&gt;Removal of rsvg-view&lt;/h2&gt;
         3788 &lt;p&gt;So, the next version of librsvg will not provide the &lt;code&gt;rsvg-view-3&lt;/code&gt;
         3789 binary.  Please update your packages accordingly.  Distros may be able to
         3790 move the compilation of librsvg to a more sensible place in the
         3791 platform stack, now that it doesn't depend on GTK being available.&lt;/p&gt;
         3792 &lt;p&gt;What can you use instead?  Any other image viewer.  &lt;a href="https://wiki.gnome.org/Apps/EyeOfGnome/"&gt;EOG&lt;/a&gt; works fine;
         3793 there are dozens of other good viewers, too.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category></entry><entry><title>Bzip2 1.0.7 is released</title><link href="https://people.gnome.org/~federico/blog/bzip2-107-is-released.html" rel="alternate"></link><published>2019-06-27T13:55:38-05:00</published><updated>2019-06-27T13:55:38-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-06-27:/~federico/blog/bzip2-107-is-released.html</id><summary type="html">&lt;p&gt;&lt;a href="https://sourceware.org/ml/bzip2-devel/2019-q2/msg00022.html"&gt;Bzip2 1.0.7 has been released&lt;/a&gt; by Mark Wielaard.  We have a
         3794 slight change of plans since &lt;a href="https://people.gnome.org/~federico/blog/preparing-the-bzip2-107-release.html"&gt;my last post&lt;/a&gt;:&lt;/p&gt;
         3795 &lt;ul&gt;
         3796 &lt;li&gt;
         3797 &lt;p&gt;The 1.0.x series is in strict maintenance mode and will not change
         3798   build systems.  &lt;strong&gt;This is targeted towards embedded use&lt;/strong&gt;, as in
         3799   projects which already embed the …&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://sourceware.org/ml/bzip2-devel/2019-q2/msg00022.html"&gt;Bzip2 1.0.7 has been released&lt;/a&gt; by Mark Wielaard.  We have a
         3800 slight change of plans since &lt;a href="https://people.gnome.org/~federico/blog/preparing-the-bzip2-107-release.html"&gt;my last post&lt;/a&gt;:&lt;/p&gt;
         3801 &lt;ul&gt;
         3802 &lt;li&gt;
         3803 &lt;p&gt;The 1.0.x series is in strict maintenance mode and will not change
         3804   build systems.  &lt;strong&gt;This is targeted towards embedded use&lt;/strong&gt;, as in
         3805   projects which already embed the bzip2-1.0.6 sources and undoubtedly
         3806   patch the build system.  Right now this series, and the tagged 1.0.7
         3807   release, live in the &lt;a href="https://sourceware.org/git/?p=bzip2.git"&gt;sourceware repository for bzip2&lt;/a&gt;.&lt;/p&gt;
         3808 &lt;/li&gt;
         3809 &lt;li&gt;
         3810 &lt;p&gt;The 1.1.x series has Meson and CMake build systems, and a couple of
         3811   extra changes to modernize the C code but which were not fit for the
         3812   1.0.7 release.  &lt;strong&gt;This is targeted towards operating system
         3813   distributions&lt;/strong&gt;.  This lives in the master branch of the &lt;a href="https://gitlab.com/federicomenaquintero/bzip2"&gt;gitlab
         3814   repository for bzip2&lt;/a&gt;.&lt;/p&gt;
         3815 &lt;/li&gt;
         3816 &lt;/ul&gt;
         3817 &lt;p&gt;&lt;strong&gt;Distros and embedded users&lt;/strong&gt; should start using bzip2-1.0.7
         3818 immediately.  The patches they already have for the bzip2's
         3819 traditional build system should still apply.  The release includes bug
         3820 fixes and security fixes that have accumulated over the years,
         3821 including the new &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/74de1e2e6ffc9d51ef9824db71a8ffee5962cdbc"&gt;CVE-2019-12900&lt;/a&gt;.&lt;/p&gt;
         3822 &lt;p&gt;Once 1.1.0 is released, distributions should be able to remove their
         3823 patches to the build system and just start using Meson or CMake.  You
         3824 may want to monitor the &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/-/milestones/1"&gt;1.1.0 milestone&lt;/a&gt; — help is
         3825 appreciated fixing the issues there so we can make the first release
         3826 with the new build systems!&lt;/p&gt;</content><category term="misc"></category><category term="bzip2"></category></entry><entry><title>Preparing the bzip2-1.0.7 release</title><link href="https://people.gnome.org/~federico/blog/preparing-the-bzip2-107-release.html" rel="alternate"></link><published>2019-06-20T11:47:26-05:00</published><updated>2019-06-20T11:47:26-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-06-20:/~federico/blog/preparing-the-bzip2-107-release.html</id><summary type="html">&lt;p&gt;&lt;strong&gt;ATTENTION ALL DISTRIBUTIONS&lt;/strong&gt;: this is for you.  &lt;strong&gt;THE SONAME MAY CHANGE!&lt;/strong&gt;&lt;/p&gt;
         3827 &lt;p&gt;I am preparing a bzip2-1.0.7 release.  You can see the &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/master/NEWS"&gt;release
         3828 notes&lt;/a&gt;, which should be of interest:&lt;/p&gt;
         3829 &lt;ul&gt;
         3830 &lt;li&gt;
         3831 &lt;p&gt;Many historical patches from various distributions are integrated
         3832   now.&lt;/p&gt;
         3833 &lt;/li&gt;
         3834 &lt;li&gt;
         3835 &lt;p&gt;We have a new fix for the just-published &lt;a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-12900"&gt;CVE-2019-12900&lt;/a&gt;, courtesy of …&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;ATTENTION ALL DISTRIBUTIONS&lt;/strong&gt;: this is for you.  &lt;strong&gt;THE SONAME MAY CHANGE!&lt;/strong&gt;&lt;/p&gt;
         3836 &lt;p&gt;I am preparing a bzip2-1.0.7 release.  You can see the &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/master/NEWS"&gt;release
         3837 notes&lt;/a&gt;, which should be of interest:&lt;/p&gt;
         3838 &lt;ul&gt;
         3839 &lt;li&gt;
         3840 &lt;p&gt;Many historical patches from various distributions are integrated
         3841   now.&lt;/p&gt;
         3842 &lt;/li&gt;
         3843 &lt;li&gt;
         3844 &lt;p&gt;We have a new fix for the just-published &lt;a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-12900"&gt;CVE-2019-12900&lt;/a&gt;, courtesy of
         3845   Albert Astals Cid.&lt;/p&gt;
         3846 &lt;/li&gt;
         3847 &lt;li&gt;
         3848 &lt;p&gt;&lt;strong&gt;Bzip2 has moved to Meson&lt;/strong&gt; for its preferred build system,
         3849   courtesy of Dylan Baker.  For special situations, a CMake build
         3850   system is also provided, courtesy of Micah Snyder.&lt;/p&gt;
         3851 &lt;/li&gt;
         3852 &lt;/ul&gt;
         3853 &lt;h2&gt;What's with the soname?&lt;/h2&gt;
         3854 &lt;p&gt;From bzip2-1.0.1 (from the year 2000), until bzip2-1.0.6 (from 2010),
         3855 release tarballs came with a special
         3856 &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/962d60610cb31e0f294a834e55ebb355be55d05a/Makefile-libbz2_so#L38"&gt;&lt;code&gt;Makefile-libbz2_so&lt;/code&gt;&lt;/a&gt; to generate a shared library
         3857 instead of a static one.&lt;/p&gt;
         3858 &lt;p&gt;This never used libtool or anything; it specified linker flags by
         3859 hand.  Various distributions either patched this special makefile, or
         3860 replaced it by another one, or outright replaced the complete build
         3861 system for a different one.&lt;/p&gt;
         3862 &lt;p&gt;Some things to note:&lt;/p&gt;
         3863 &lt;ul&gt;
         3864 &lt;li&gt;
         3865 &lt;p&gt;This hand-written &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/962d60610cb31e0f294a834e55ebb355be55d05a/Makefile-libbz2_so#L38"&gt;&lt;code&gt;Makefile-libbz2_so&lt;/code&gt;&lt;/a&gt; used a link
         3866   line like &lt;code&gt;$(CC) -shared -Wl,-soname -Wl,libbz2.so.1.0 -o
         3867   libbz2.so.1.0.6&lt;/code&gt;.  This means, make the DT_SONAME field inside the
         3868   ELF file be &lt;code&gt;libbz2.so.1.0&lt;/code&gt; (note the two digits in &lt;code&gt;1.0&lt;/code&gt;), and make
         3869   the filename of the shared library be &lt;code&gt;libbz2.so.1.0.6&lt;/code&gt;.&lt;/p&gt;
         3870 &lt;/li&gt;
         3871 &lt;li&gt;
         3872 &lt;p&gt;Fedora patched the soname in a patch called "saneso" to just be
         3873   &lt;code&gt;libbz2.so.1&lt;/code&gt;.&lt;/p&gt;
         3874 &lt;/li&gt;
         3875 &lt;li&gt;
         3876 &lt;p&gt;Stanislav Brabec, from openSUSE, &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/70ec984159c8263fdd4aac7c4670977aff0fe5b3#a4d1bfa62791f4ba7465f19c7f7da6b3b78714a5_0_30"&gt;replaced the hand-written
         3877   makefiles with autotools&lt;/a&gt;, which meant using libtool.  It
         3878   has this interesting note:&lt;/p&gt;
         3879 &lt;/li&gt;
         3880 &lt;/ul&gt;
         3881 &lt;blockquote&gt;
         3882 &lt;p&gt;Incompatible changes:&lt;/p&gt;
         3883 &lt;p&gt;soname change. Libtool has no support for two parts soname suffix (e. g.
         3884 libbz2.so.1.0). It must be a single number (e. g. libbz2.so.1). That is
         3885 why soname must change. But I see not a big problem with it. Several
         3886 distributions already use the new number instead of the non-standard
         3887 number from Makefile-libbz2_so.&lt;/p&gt;
         3888 &lt;/blockquote&gt;
         3889 &lt;p&gt;(In fact, if I do &lt;code&gt;objdump -x /usr/lib64/*.so | grep SONAME&lt;/code&gt;, I see
         3890 that most libraries have single-digit sonames.)&lt;/p&gt;
         3891 &lt;p&gt;In my experience, both Fedora and openSUSE are very strict, and
         3892 correct, about obscure things like library sonames.&lt;/p&gt;
         3893 &lt;p&gt;With the switch to Meson, bzip2 no longer uses libtool.  It will have
         3894 a single-digit soname — this is not in the &lt;code&gt;meson.build&lt;/code&gt; yet, but
         3895 expect it to be there within the next couple of days.&lt;/p&gt;
         3896 &lt;p&gt;I don't know what distros which decided to preserve the &lt;code&gt;1.0&lt;/code&gt; soname
         3897 will need to do; maybe they will need to patch &lt;code&gt;meson.build&lt;/code&gt; on their
         3898 own.&lt;/p&gt;
         3899 &lt;p&gt;Fortunately, &lt;strong&gt;the API/ABI are still exactly the same&lt;/strong&gt;.  You can
         3900 preserve the old soname which your distro was using and linking libbz2
         3901 will probably keep working as usual.&lt;/p&gt;
         3902 &lt;p&gt;(This is a C-only release as usual.  The Rust branch is still
         3903 experimental.)&lt;/p&gt;</content><category term="misc"></category><category term="bzip2"></category></entry><entry><title>Bzip2 in Rust: porting the randomization table</title><link href="https://people.gnome.org/~federico/blog/bzip2-in-rust-randomization-table.html" rel="alternate"></link><published>2019-06-11T14:30:17-05:00</published><updated>2019-06-11T14:30:17-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-06-11:/~federico/blog/bzip2-in-rust-randomization-table.html</id><summary type="html">&lt;p&gt;Here is a straightforward port of some easy code.&lt;/p&gt;
         3904 &lt;p&gt;&lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/7bd2dc3c13d01a963ef80ae96727ce247acb77fa/randtable.c#L26"&gt;&lt;code&gt;randtable.c&lt;/code&gt;&lt;/a&gt; has a lookup table with seemingly-random
         3905 numbers.  This table is used by &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/5f8f075a554fc593be827cff5f8bc6ce880b08f7/bzlib_private.h#L131-149"&gt;the following macros in
         3906 bzlib_private.h&lt;/a&gt;:&lt;/p&gt;
         3907 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;BZ2_rNums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
         3908 
         3909 &lt;span class="cp"&gt;#define BZ_RAND_DECLS                          \&lt;/span&gt;
         3910 &lt;span class="cp"&gt;   Int32 rNToGo;                               \&lt;/span&gt;
         3911 &lt;span class="cp"&gt;   Int32 rTPos                                 \&lt;/span&gt;
         3912 
         3913 &lt;span class="cp"&gt;#define BZ_RAND_INIT_MASK                      \&lt;/span&gt;
         3914 &lt;span class="cp"&gt;   s-&amp;gt;rNToGo = 0;                              \&lt;/span&gt;
         3915 &lt;span class="cp"&gt;   s-&amp;gt;rTPos  = 0                               \&lt;/span&gt;
         3916 
         3917 &lt;span class="cp"&gt;#define BZ_RAND_MASK ((s- …&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;Here is a straightforward port of some easy code.&lt;/p&gt;
         3918 &lt;p&gt;&lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/7bd2dc3c13d01a963ef80ae96727ce247acb77fa/randtable.c#L26"&gt;&lt;code&gt;randtable.c&lt;/code&gt;&lt;/a&gt; has a lookup table with seemingly-random
         3919 numbers.  This table is used by &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/5f8f075a554fc593be827cff5f8bc6ce880b08f7/bzlib_private.h#L131-149"&gt;the following macros in
         3920 bzlib_private.h&lt;/a&gt;:&lt;/p&gt;
         3921 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;BZ2_rNums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
         3922 
         3923 &lt;span class="cp"&gt;#define BZ_RAND_DECLS                          \&lt;/span&gt;
         3924 &lt;span class="cp"&gt;   Int32 rNToGo;                               \&lt;/span&gt;
         3925 &lt;span class="cp"&gt;   Int32 rTPos                                 \&lt;/span&gt;
         3926 
         3927 &lt;span class="cp"&gt;#define BZ_RAND_INIT_MASK                      \&lt;/span&gt;
         3928 &lt;span class="cp"&gt;   s-&amp;gt;rNToGo = 0;                              \&lt;/span&gt;
         3929 &lt;span class="cp"&gt;   s-&amp;gt;rTPos  = 0                               \&lt;/span&gt;
         3930 
         3931 &lt;span class="cp"&gt;#define BZ_RAND_MASK ((s-&amp;gt;rNToGo == 1) ? 1 : 0)&lt;/span&gt;
         3932 
         3933 &lt;span class="cp"&gt;#define BZ_RAND_UPD_MASK                       \&lt;/span&gt;
         3934 &lt;span class="cp"&gt;   if (s-&amp;gt;rNToGo == 0) {                       \&lt;/span&gt;
         3935 &lt;span class="cp"&gt;      s-&amp;gt;rNToGo = BZ2_rNums[s-&amp;gt;rTPos];         \&lt;/span&gt;
         3936 &lt;span class="cp"&gt;      s-&amp;gt;rTPos++;                              \&lt;/span&gt;
         3937 &lt;span class="cp"&gt;      if (s-&amp;gt;rTPos == 512) s-&amp;gt;rTPos = 0;       \&lt;/span&gt;
         3938 &lt;span class="cp"&gt;   }                                           \&lt;/span&gt;
         3939 &lt;span class="cp"&gt;   s-&amp;gt;rNToGo--;&lt;/span&gt;
         3940 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3941 
         3942 &lt;p&gt;Here, &lt;code&gt;BZ_RAND_DECLS&lt;/code&gt; is used to declare two fields, &lt;code&gt;rNToGo&lt;/code&gt; and
         3943 &lt;code&gt;rTPos&lt;/code&gt;, into two structs (&lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/5f8f075a554fc593be827cff5f8bc6ce880b08f7/bzlib_private.h#L213"&gt;1&lt;/a&gt;, &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/5f8f075a554fc593be827cff5f8bc6ce880b08f7/bzlib_private.h#L345"&gt;2&lt;/a&gt;).  Both are similar to this:&lt;/p&gt;
         3944 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         3945    &lt;span class="p"&gt;...&lt;/span&gt;
         3946    &lt;span class="n"&gt;Bool&lt;/span&gt;     &lt;span class="n"&gt;blockRandomised&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         3947    &lt;span class="n"&gt;BZ_RAND_DECLS&lt;/span&gt;
         3948    &lt;span class="p"&gt;...&lt;/span&gt;
         3949 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;DState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         3950 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3951 
         3952 &lt;p&gt;Then, the code that needs to initialize those fields calls
         3953 &lt;code&gt;BZ_RAND_INIT_MASK&lt;/code&gt;, which expands into code to set the two fields to
         3954 zero.&lt;/p&gt;
         3955 &lt;p&gt;At several points in the code, &lt;code&gt;BZ_RAND_UPD_MASK&lt;/code&gt; gets called, which
         3956 expands into code that updates the randomization state, or something
         3957 like that, and uses &lt;code&gt;BZ_RAND_MASK&lt;/code&gt; to get a useful value out of the
         3958 randomization state.&lt;/p&gt;
         3959 &lt;p&gt;I have no idea yet what the state is about, but let's port it
         3960 directly.&lt;/p&gt;
         3961 &lt;h2&gt;Give things a name&lt;/h2&gt;
         3962 &lt;p&gt;It's interesting to see that &lt;strong&gt;no code except for those macros&lt;/strong&gt; uses
         3963 the fields &lt;code&gt;rNToGo&lt;/code&gt; and &lt;code&gt;rTPos&lt;/code&gt;, which are declared via
         3964 &lt;code&gt;BZ_RAND_DECLS&lt;/code&gt;.  So, let's make up a &lt;strong&gt;type with a name&lt;/strong&gt; for that.
         3965 Since I have no better name for it, I shall call it just
         3966 &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/7bd2dc3c13d01a963ef80ae96727ce247acb77fa"&gt;&lt;code&gt;RandState&lt;/code&gt;&lt;/a&gt;.  I added that type definition in the C code,
         3967 and replaced the macro-which-creates-struct-fields with a
         3968 &lt;code&gt;RandState&lt;/code&gt;-typed field:&lt;/p&gt;
         3969 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;-#define BZ_RAND_DECLS                          \
         3970 -   Int32 rNToGo;                               \
         3971 -   Int32 rTPos                                 \
         3972 +typedef struct {
         3973 +   Int32 rNToGo;
         3974 +   Int32 rTPos;
         3975 +} RandState;
         3976 
         3977 ...
         3978 
         3979 -      BZ_RAND_DECLS;
         3980 +      RandState rand;
         3981 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         3982 
         3983 &lt;p&gt;Since the fields now live inside a sub-struct, I changed the other
         3984 macros to use &lt;code&gt;s-&amp;gt;rand.rNToGo&lt;/code&gt; instead of &lt;code&gt;s-&amp;gt;rNToGo&lt;/code&gt;, and similarly
         3985 for the other field.&lt;/p&gt;
         3986 &lt;h2&gt;Turn macros into functions&lt;/h2&gt;
         3987 &lt;p&gt;Now, three commits (&lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/95d3e979a4ac69d382b67d0d4c97e956002797b4"&gt;1&lt;/a&gt;, &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/35242daa8f760c68e0b358f4ee38488374f440db"&gt;2&lt;/a&gt;, &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/5d376c13abb891d311a00dc1ce0533390fc20b51"&gt;3&lt;/a&gt;) to turn the
         3988 macros &lt;code&gt;BZ_RAND_INIT_MASK&lt;/code&gt;, &lt;code&gt;BZ_RAND_MASK&lt;/code&gt;, and &lt;code&gt;BZ_RAND_UPD_MASK&lt;/code&gt;
         3989 into functions.&lt;/p&gt;
         3990 &lt;p&gt;And now that the functions live in the same C source file as the
         3991 lookup table they reference, &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/5d5f98ab88526498a20969d565bf2f3831b4467a"&gt;the table can be made &lt;code&gt;static const&lt;/code&gt;&lt;/a&gt; to
         3992 avoid having it as read/write unshared data in the linked binary.&lt;/p&gt;
         3993 &lt;p&gt;Premature optimization concern:  doesn't de-inlining those macros
         3994 cause performance problems?  At first, we will get the added overhead
         3995 from a function call.  When the whole code is ported to Rust, the Rust
         3996 compiler will probably be able to figure out that those tiny functions
         3997 can be inlined (or we can &lt;code&gt;#[inline]&lt;/code&gt; them by hand if we have proof,
         3998 or if we have more hubris than faith in LLVM).&lt;/p&gt;
         3999 &lt;h2&gt;Port functions and table to Rust&lt;/h2&gt;
         4000 &lt;p&gt;The functions are so tiny, and the table so cut-and-pasteable, that
         4001 it's easy to &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/dc01d95a704d02a810072a0aab5fb11e58150f78"&gt;port them to Rust&lt;/a&gt; in a single shot:&lt;/p&gt;
         4002 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4003 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;BZ2_rand_init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;RandState&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4004 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;RandState&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4005 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;rNToGo&lt;/span&gt;: &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4006 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;rTPos&lt;/span&gt;: &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4007 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4008 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4009 
         4010 &lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4011 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;BZ2_rand_mask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;RandState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4012 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rNToGo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4013 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4014 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4015 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4016 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4017 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4018 
         4019 &lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4020 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;BZ2_rand_update_mask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RandState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4021 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rNToGo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4022 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rNToGo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RAND_TABLE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rTPos&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4023 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rTPos&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4024 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rTPos&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4025 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rTPos&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4026 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4027 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4028 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rNToGo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4029 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4030 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4031 
         4032 &lt;p&gt;Also, we define the &lt;code&gt;RandState&lt;/code&gt; type as a Rust struct with a
         4033 &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/dc01d95a704d02a810072a0aab5fb11e58150f78/bzlib_rust/src/rand_table.rs#L56-61"&gt;C-compatible representation&lt;/a&gt;, so it will have the same layout in memory
         4034 as the C struct.  &lt;strong&gt;This is what allows us to have a &lt;code&gt;RandState&lt;/code&gt; in
         4035 the C struct&lt;/strong&gt;, while in reality the C code doesn't access it
         4036 directly; it is just used as a struct field.&lt;/p&gt;
         4037 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Keep this in sync with bzlib_private.h:&lt;/span&gt;
         4038 &lt;span class="cp"&gt;#[repr(C)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4039 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;RandState&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4040 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;rNToGo&lt;/span&gt;: &lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4041 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;rTPos&lt;/span&gt;: &lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4042 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4043 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4044 
         4045 &lt;p&gt;&lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/dc01d95a704d02a810072a0aab5fb11e58150f78"&gt;See the commit&lt;/a&gt; for the corresponding &lt;code&gt;extern&lt;/code&gt;
         4046 declarations in &lt;code&gt;bzlib_private.h&lt;/code&gt;.  With those functions and the table
         4047 ported to Rust, we can remove &lt;code&gt;randtable.c&lt;/code&gt;.  Yay!&lt;/p&gt;
         4048 &lt;h2&gt;A few cleanups&lt;/h2&gt;
         4049 &lt;p&gt;After moving to another house one throws away useless boxes; we have
         4050 to do some cleanup in the Rust code after the initial port, too.&lt;/p&gt;
         4051 &lt;p&gt;Rust prefers snake_case fields rather than camelCase ones, and I
         4052 agree.  I &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/d13a9fbc51f5c49b859485d6097ee0dd2b3410f0"&gt;renamed the fields&lt;/a&gt; to &lt;code&gt;n_to_go&lt;/code&gt; and &lt;code&gt;table_pos&lt;/code&gt;.&lt;/p&gt;
         4053 &lt;p&gt;Then, I discovered that the &lt;code&gt;EState&lt;/code&gt; struct doesn't actually use the
         4054 fields for the randomization state.  I just &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/b73c6a507de373dbb0cc8deab0767b41967e678b"&gt;removed them&lt;/a&gt;.&lt;/p&gt;
         4055 &lt;h2&gt;Exegesis&lt;/h2&gt;
         4056 &lt;p&gt;What is that randomization state all about?&lt;/p&gt;
         4057 &lt;p&gt;And why does &lt;code&gt;DState&lt;/code&gt; (the struct used during decompression) need the
         4058 randomization state, but &lt;code&gt;EState&lt;/code&gt; (used during compression) doesn't
         4059 need it?&lt;/p&gt;
         4060 &lt;p&gt;I found &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/rustify/compress.c#L639-648"&gt;this interesting comment&lt;/a&gt;:&lt;/p&gt;
         4061 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;      &lt;span class="cm"&gt;/*-- &lt;/span&gt;
         4062 &lt;span class="cm"&gt;         Now a single bit indicating (non-)randomisation. &lt;/span&gt;
         4063 &lt;span class="cm"&gt;         As of version 0.9.5, we use a better sorting algorithm&lt;/span&gt;
         4064 &lt;span class="cm"&gt;         which makes randomisation unnecessary.  So always set&lt;/span&gt;
         4065 &lt;span class="cm"&gt;         the randomised bit to &amp;#39;no&amp;#39;.  Of course, the decoder&lt;/span&gt;
         4066 &lt;span class="cm"&gt;         still needs to be able to handle randomised blocks&lt;/span&gt;
         4067 &lt;span class="cm"&gt;         so as to maintain backwards compatibility with&lt;/span&gt;
         4068 &lt;span class="cm"&gt;         older versions of bzip2.&lt;/span&gt;
         4069 &lt;span class="cm"&gt;      --*/&lt;/span&gt;
         4070       &lt;span class="n"&gt;bsW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4071 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4072 
         4073 &lt;p&gt;Okay!  So &lt;em&gt;compression&lt;/em&gt; no longer uses randomization, but
         4074 &lt;em&gt;decompression&lt;/em&gt; has to support files which were compressed with
         4075 randomization.  Here, &lt;code&gt;bsW(s,1,0)&lt;/code&gt; always writes a 0 bit to the file.&lt;/p&gt;
         4076 &lt;p&gt;However, the decompression code &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/b73c6a507de373dbb0cc8deab0767b41967e678b/decompress.c#L251"&gt;actually reads the &lt;code&gt;blockRandomised&lt;/code&gt;
         4077 bit&lt;/a&gt; from the file so that it can see whether it is
         4078 dealing with an old-format file:&lt;/p&gt;
         4079 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;GET_BITS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BZ_X_RANDBIT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;blockRandomised&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4080 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4081 
         4082 &lt;p&gt;Later in the code, this &lt;code&gt;s-&amp;gt;blockRandomised&lt;/code&gt; field gets consulted; if
         4083 the bit is on, the code calls &lt;code&gt;BZ2_rand_update_mask()&lt;/code&gt; and friends as
         4084 appropriate.  If one is using files compressed with Bzip2 0.9.5 or
         4085 later, those randomization functions are not even called.&lt;/p&gt;
         4086 &lt;p&gt;Talk about preserving compatibility with the past.&lt;/p&gt;
         4087 &lt;h2&gt;Explanation, or building my headcanon&lt;/h2&gt;
         4088 &lt;p&gt;Bzip2's compression starts by running a &lt;a href="https://en.wikipedia.org/wiki/Burrows%E2%80%93Wheeler_transform"&gt;Burrows-Wheeler
         4089 Transform&lt;/a&gt; on a block of data to compress, which is a wonderful
         4090 algorithm that I'm trying to fully understand.  Part of the BWT
         4091 involves sorting all the string rotations of the block in question.&lt;/p&gt;
         4092 &lt;p&gt;Per &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/rustify/compress.c#L639-648"&gt;the comment I cited&lt;/a&gt;, really old versions of bzip2 used a
         4093 randomization helper to make sorting perform well in extreme cases,
         4094 but not-so-old versions fixed this.&lt;/p&gt;
         4095 &lt;p&gt;This explains why the decompression struct &lt;code&gt;DState&lt;/code&gt; has a
         4096 &lt;code&gt;blockRandomised&lt;/code&gt; bit, but the compression struct &lt;code&gt;EState&lt;/code&gt; doesn't
         4097 need one.  The fields that the original macro was pasting into
         4098 &lt;code&gt;EState&lt;/code&gt; were just a vestige from 1999, which is when Bzip2 0.9.5 was
         4099 released.&lt;/p&gt;</content><category term="misc"></category><category term="bzip2"></category><category term="rust"></category></entry><entry><title>Bzip2 uses Meson and Autotools now — and a plea for help</title><link href="https://people.gnome.org/~federico/blog/bzip2-uses-meson-and-autotools.html" rel="alternate"></link><published>2019-06-07T11:01:44-05:00</published><updated>2019-06-07T11:01:44-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-06-07:/~federico/blog/bzip2-uses-meson-and-autotools.html</id><summary type="html">&lt;p&gt;There is a lot of activity in the &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/activity"&gt;bzip2 repository&lt;/a&gt;!&lt;/p&gt;
         4100 &lt;p&gt;Perhaps the most exciting thing is that Dylan Baker made a merge
         4101 request to add &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/merge_requests/6"&gt;Meson as a build system for bzip2&lt;/a&gt;; this is
         4102 merged now into the master branch.&lt;/p&gt;
         4103 &lt;p&gt;The current status is this:&lt;/p&gt;
         4104 &lt;ul&gt;
         4105 &lt;li&gt;Both Meson and Autotools are …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;There is a lot of activity in the &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/activity"&gt;bzip2 repository&lt;/a&gt;!&lt;/p&gt;
         4106 &lt;p&gt;Perhaps the most exciting thing is that Dylan Baker made a merge
         4107 request to add &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/merge_requests/6"&gt;Meson as a build system for bzip2&lt;/a&gt;; this is
         4108 merged now into the master branch.&lt;/p&gt;
         4109 &lt;p&gt;The current status is this:&lt;/p&gt;
         4110 &lt;ul&gt;
         4111 &lt;li&gt;Both Meson and Autotools are supported.&lt;/li&gt;
         4112 &lt;li&gt;We have CI runs for both build systems.&lt;/li&gt;
         4113 &lt;/ul&gt;
         4114 &lt;h2&gt;A plea for help: add CI runners for other platforms!&lt;/h2&gt;
         4115 &lt;p&gt;Do you use *BSD / Windows / Solaris / etc. and know how to make
         4116 Gitlab's CI work for them?&lt;/p&gt;
         4117 &lt;p&gt;The only runners we have now for bzip2 are for well-known Linux
         4118 distros.  I would really like to keep bzip2 working on non-Linux
         4119 platforms.  If you know how to make Gitlab CI runners for other
         4120 systems, &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/merge_requests"&gt;please send a merge request&lt;/a&gt;!&lt;/p&gt;
         4121 &lt;h2&gt;Why two build systems?&lt;/h2&gt;
         4122 &lt;p&gt;Mainly uncertainty on my part.  I haven't used Meson extensively;
         4123 people tell me that it works better than Autotools out of the box for
         4124 Windows.&lt;/p&gt;
         4125 &lt;p&gt;Bzip2 runs on all sorts of ancient systems, and I don't know whether
         4126 Meson or Autotools will be a better fit for them.  Time will tell.
         4127 Hopefully in the future we can have only a single supported build
         4128 system for bzip2.&lt;/p&gt;</content><category term="misc"></category><category term="bzip2"></category><category term="meson"></category></entry><entry><title>Bzip2 repository reconstructed</title><link href="https://people.gnome.org/~federico/blog/bzip2-repository-reconstructed.html" rel="alternate"></link><published>2019-06-05T19:13:05-05:00</published><updated>2019-06-05T19:13:05-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-06-05:/~federico/blog/bzip2-repository-reconstructed.html</id><summary type="html">&lt;p&gt;I have just done a &lt;code&gt;git push --force-with-lease&lt;/code&gt; to &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commits/master"&gt;bzip2's master
         4129 branch&lt;/a&gt;, which means that if you had a previous clone of this
         4130 repository, you'll have to re-fetch it and rebase any changes you may
         4131 have on top.&lt;/p&gt;
         4132 &lt;p&gt;I apologize for the inconvenience!&lt;/p&gt;
         4133 &lt;p&gt;But I have a good excuse:  Julian …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I have just done a &lt;code&gt;git push --force-with-lease&lt;/code&gt; to &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commits/master"&gt;bzip2's master
         4134 branch&lt;/a&gt;, which means that if you had a previous clone of this
         4135 repository, you'll have to re-fetch it and rebase any changes you may
         4136 have on top.&lt;/p&gt;
         4137 &lt;p&gt;I apologize for the inconvenience!&lt;/p&gt;
         4138 &lt;p&gt;But I have a good excuse:  Julian Seward pointed me to a &lt;a href="https://sourceware.org/git/?p=bzip2.git;a=summary"&gt;repository
         4139 at sourceware&lt;/a&gt; where Mark Wielaard reconstructed a commit
         4140 history for bzip2, based on the historical tarballs starting from
         4141 bzip2-0.1.  Bzip2 was never maintained under revision control, so the
         4142 reconstructed repository should be used mostly for historical
         4143 reference (go look for &lt;code&gt;bzip2.exe&lt;/code&gt; in the initial commit!).&lt;/p&gt;
         4144 &lt;p&gt;I have rebased all the post-1.0.6 commits on top of Mark's repository;
         4145 this is what is in the &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commits/master"&gt;master&lt;/a&gt; branch now.&lt;/p&gt;
         4146 &lt;p&gt;There is a new &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commits/rustify"&gt;rustify&lt;/a&gt; branch as well, based on master, which is
         4147 where I will do the gradual port to Rust.&lt;/p&gt;
         4148 &lt;p&gt;I foresee no other force-pushes to the master branch in the future.
         4149 Apologies again if this disrupts your workflow.&lt;/p&gt;
         4150 &lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/issues/7"&gt;Someone did another reconstruction&lt;/a&gt;.  If they
         4151 weave the histories together, I'll do another force-push, the very
         4152 last one, I promise.  If you send merge requests, I'll rebase them
         4153 myself if that happens.&lt;/p&gt;</content><category term="misc"></category><category term="bzip2"></category></entry><entry><title>Maintaining bzip2</title><link href="https://people.gnome.org/~federico/blog/maintaining-bzip2.html" rel="alternate"></link><published>2019-06-04T19:41:57-05:00</published><updated>2019-06-04T19:41:57-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-06-04:/~federico/blog/maintaining-bzip2.html</id><summary type="html">&lt;p&gt;Today I had a very pleasant conversation with Julian Seward, of bzip2
         4154 and &lt;a href="http://valgrind.org/"&gt;Valgrind&lt;/a&gt; fame.  Julian has kindly agreed
         4155 to cede the maintainership of &lt;a href="https://sourceware.org/bzip2/"&gt;bzip2&lt;/a&gt;
         4156 to me.&lt;/p&gt;
         4157 &lt;p&gt;Bzip2 has not had a release since 2010.  In the meantime, Linux
         4158 distros have accumulated a number of bug/security fixes for it …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today I had a very pleasant conversation with Julian Seward, of bzip2
         4159 and &lt;a href="http://valgrind.org/"&gt;Valgrind&lt;/a&gt; fame.  Julian has kindly agreed
         4160 to cede the maintainership of &lt;a href="https://sourceware.org/bzip2/"&gt;bzip2&lt;/a&gt;
         4161 to me.&lt;/p&gt;
         4162 &lt;p&gt;Bzip2 has not had a release since 2010.  In the meantime, Linux
         4163 distros have accumulated a number of bug/security fixes for it.
         4164 Seemingly every distributor of bzip2 patches its build system.  The
         4165 documentation generation step is a bit creaky.  There is no source
         4166 control repository, nor bug tracker.  I hope to fix these things
         4167 gradually.&lt;/p&gt;
         4168 &lt;p&gt;This is the new &lt;a href="https://gitlab.com/federicomenaquintero/bzip2"&gt;repository for bzip2&lt;/a&gt;.&lt;/p&gt;
         4169 &lt;p&gt;Ways in which you can immediately help by submitting merge requests:&lt;/p&gt;
         4170 &lt;ul&gt;
         4171 &lt;li&gt;
         4172 &lt;p&gt;Look at the &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/issues"&gt;issues&lt;/a&gt;; currently they are around auto-generating the
         4173   version number.&lt;/p&gt;
         4174 &lt;/li&gt;
         4175 &lt;li&gt;
         4176 &lt;p&gt;Create a basic &lt;a href="https://gitlab.com/help/ci/README.md"&gt;continuous integration&lt;/a&gt; pipeline that at least
         4177   builds the code and runs the tests.&lt;/p&gt;
         4178 &lt;/li&gt;
         4179 &lt;li&gt;
         4180 &lt;p&gt;Test the autotools setup, courtesy of Stanislav Brabec, and improve
         4181   it as you see fit.&lt;/p&gt;
         4182 &lt;/li&gt;
         4183 &lt;/ul&gt;
         4184 &lt;p&gt;The &lt;a href="https://people.gnome.org/~federico/blog/bzip2-in-rust-basic-infra.html"&gt;rustification&lt;/a&gt; will happen in a separate branch for now, at least
         4185 until the Autotools setup settles down.&lt;/p&gt;
         4186 &lt;p&gt;I hope to have a 1.0.7 release soon, but this really needs &lt;em&gt;your&lt;/em&gt;
         4187 help.  Let's revive this awesome little project.&lt;/p&gt;</content><category term="misc"></category><category term="bzip2"></category></entry><entry><title>Bzip2 in Rust - Basic infrastructure and CRC32 computation</title><link href="https://people.gnome.org/~federico/blog/bzip2-in-rust-basic-infra.html" rel="alternate"></link><published>2019-05-30T10:36:19-05:00</published><updated>2019-05-30T10:36:19-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-05-30:/~federico/blog/bzip2-in-rust-basic-infra.html</id><summary type="html">&lt;p&gt;I have started a little experiment in porting bits of the widely-used
         4188 &lt;a href="https://sourceware.org/bzip2/"&gt;bzip2/bzlib&lt;/a&gt; to Rust.  I hope this can
         4189 serve to refresh bzip2, which had its last release in 2010 and has
         4190 been nominally unmaintained for years.&lt;/p&gt;
         4191 &lt;p&gt;I hope to make several posts detailing how this port is done …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I have started a little experiment in porting bits of the widely-used
         4192 &lt;a href="https://sourceware.org/bzip2/"&gt;bzip2/bzlib&lt;/a&gt; to Rust.  I hope this can
         4193 serve to refresh bzip2, which had its last release in 2010 and has
         4194 been nominally unmaintained for years.&lt;/p&gt;
         4195 &lt;p&gt;I hope to make several posts detailing how this port is done.  In this
         4196 post, I'll talk about setting up a Rust infrastructure for bzip2 and
         4197 my experiments in replacing the C code that does CRC32 computations.&lt;/p&gt;
         4198 &lt;h2&gt;Super-quick summary of how librsvg was ported to Rust&lt;/h2&gt;
         4199 &lt;ul&gt;
         4200 &lt;li&gt;
         4201 &lt;p&gt;Add the necessary autotools infrastructure to build a Rust
         4202   sub-library that gets linked into the main public library.&lt;/p&gt;
         4203 &lt;/li&gt;
         4204 &lt;li&gt;
         4205 &lt;p&gt;Port bit by bit to Rust.  Add unit tests as appropriate.  Refactor
         4206   endlessly.&lt;/p&gt;
         4207 &lt;/li&gt;
         4208 &lt;li&gt;
         4209 &lt;p&gt;&lt;strong&gt;MAINTAIN THE PUBLIC API/ABI AT ALL COSTS&lt;/strong&gt; so callers don't
         4210   notice that the library is being rewritten under their feet.&lt;/p&gt;
         4211 &lt;/li&gt;
         4212 &lt;/ul&gt;
         4213 &lt;p&gt;I have no idea of how bzip2 works internally, but I do know how to
         4214 maintain ABIs, so let's get started.&lt;/p&gt;
         4215 &lt;h2&gt;Bzip2's source tree&lt;/h2&gt;
         4216 &lt;p&gt;As a very small project that just builds a library and couple of
         4217 executables, bzip2 was structured with all the source files directly
         4218 under a toplevel directory.&lt;/p&gt;
         4219 &lt;p&gt;The only tests in there are three reference files that get compressed,
         4220 then uncompressed, and then compared to the original ones.&lt;/p&gt;
         4221 &lt;p&gt;As the rustification proceeds, I'll move the files around to better
         4222 places.  The scheme from librsvg worked well in this respect, so I'll
         4223 probably be copying many of the techniques and organization from
         4224 there.&lt;/p&gt;
         4225 &lt;h2&gt;Deciding what to port first&lt;/h2&gt;
         4226 &lt;p&gt;I looked a bit at the bzip2 sources, and the code to do CRC32
         4227 computations seemed isolated enough from the rest of the code to port
         4228 easily.&lt;/p&gt;
         4229 &lt;p&gt;The CRC32 code was arranged like this.  First, a lookup table in
         4230 &lt;code&gt;crc32table.c&lt;/code&gt;:&lt;/p&gt;
         4231 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;UInt32&lt;/span&gt; &lt;span class="n"&gt;BZ2_crc32Table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         4232    &lt;span class="mh"&gt;0x00000000L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x04c11db7L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x09823b6eL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x0d4326d9L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         4233    &lt;span class="mh"&gt;0x130476dcL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x17c56b6bL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x1a864db2L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x1e475005L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         4234    &lt;span class="p"&gt;...&lt;/span&gt;
         4235 &lt;span class="p"&gt;}&lt;/span&gt;
         4236 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4237 
         4238 &lt;p&gt;And then, three macros in &lt;code&gt;bzlib_private.h&lt;/code&gt; which make up all the
         4239 CRC32 code in the library:&lt;/p&gt;
         4240 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;UInt32&lt;/span&gt; &lt;span class="n"&gt;BZ2_crc32Table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
         4241 
         4242 &lt;span class="cp"&gt;#define BZ_INITIALISE_CRC(crcVar)              \&lt;/span&gt;
         4243 &lt;span class="cp"&gt;{                                              \&lt;/span&gt;
         4244 &lt;span class="cp"&gt;   crcVar = 0xffffffffL;                       \&lt;/span&gt;
         4245 &lt;span class="cp"&gt;}&lt;/span&gt;
         4246 
         4247 &lt;span class="cp"&gt;#define BZ_FINALISE_CRC(crcVar)                \&lt;/span&gt;
         4248 &lt;span class="cp"&gt;{                                              \&lt;/span&gt;
         4249 &lt;span class="cp"&gt;   crcVar = ~(crcVar);                         \&lt;/span&gt;
         4250 &lt;span class="cp"&gt;}&lt;/span&gt;
         4251 
         4252 &lt;span class="cp"&gt;#define BZ_UPDATE_CRC(crcVar,cha)              \&lt;/span&gt;
         4253 &lt;span class="cp"&gt;{                                              \&lt;/span&gt;
         4254 &lt;span class="cp"&gt;   crcVar = (crcVar &amp;lt;&amp;lt; 8) ^                    \&lt;/span&gt;
         4255 &lt;span class="cp"&gt;            BZ2_crc32Table[(crcVar &amp;gt;&amp;gt; 24) ^    \&lt;/span&gt;
         4256 &lt;span class="cp"&gt;                           ((UChar)cha)];      \&lt;/span&gt;
         4257 &lt;span class="cp"&gt;}&lt;/span&gt;
         4258 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4259 
         4260 &lt;p&gt;Initially I wanted to just remove this code and replace it with one of
         4261 the existing Rust crates to do CRC32 computations, but first I needed
         4262 to know which variant of CRC32 this is.&lt;/p&gt;
         4263 &lt;h2&gt;Preparing the CRC32 port so it will not break&lt;/h2&gt;
         4264 &lt;p&gt;I needed to set up tests for the CRC32 code so the replacement code
         4265 would compute exactly the same values as the original:&lt;/p&gt;
         4266 &lt;ul&gt;
         4267 &lt;li&gt;&lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/bd79e7adf4274eef376111404a40ef3bd6836f06"&gt;Rename crc32table.c to
         4268   crc32.c&lt;/a&gt; -
         4269   that file is going to hold all the CRC32 code, not only the lookup table.&lt;/li&gt;
         4270 &lt;li&gt;&lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/fb284d38c6f45382c5f6acde69631caed6589f27"&gt;Turn the CRC32 macros into
         4271   functions&lt;/a&gt; -
         4272   so I can move them to Rust and have the C code call them.&lt;/li&gt;
         4273 &lt;/ul&gt;
         4274 &lt;p&gt;Then I needed a test that computed the CRC32 values of several
         4275 strings, so I could capture the results and make them part of the
         4276 test.&lt;/p&gt;
         4277 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;UChar&lt;/span&gt; &lt;span class="n"&gt;buf1&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4278 &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;UChar&lt;/span&gt; &lt;span class="n"&gt;buf2&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4279 &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;UChar&lt;/span&gt; &lt;span class="n"&gt;buf3&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;hello world&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4280 &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;UChar&lt;/span&gt; &lt;span class="n"&gt;buf4&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Lorem ipsum dolor sit amet, consectetur adipiscing elit, &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4281 
         4282 &lt;span class="kt"&gt;int&lt;/span&gt;
         4283 &lt;span class="nf"&gt;main&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         4284 &lt;span class="p"&gt;{&lt;/span&gt;
         4285     &lt;span class="n"&gt;printf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;buf1: %x&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crc32_buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf1&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
         4286     &lt;span class="n"&gt;printf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;buf2: %x&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crc32_buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf2&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
         4287     &lt;span class="n"&gt;printf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;buf3: %x&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crc32_buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf3&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
         4288     &lt;span class="n"&gt;printf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;buf4: %x&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crc32_buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf4&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
         4289     &lt;span class="c1"&gt;// ...&lt;/span&gt;
         4290 &lt;span class="p"&gt;}&lt;/span&gt;
         4291 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4292 
         4293 &lt;p&gt;This computes the CRC32 values of some strings using the original
         4294 algorithm, and prints their results.  Then I could cut&amp;amp;paste those
         4295 results, and turn the &lt;code&gt;printf&lt;/code&gt; into &lt;code&gt;assert&lt;/code&gt; — and that gives me a
         4296 test.&lt;/p&gt;
         4297 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;
         4298 &lt;span class="nf"&gt;main&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         4299 &lt;span class="p"&gt;{&lt;/span&gt;
         4300     &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crc32_buffer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mh"&gt;0x00000000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4301     &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crc32_buffer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mh"&gt;0x29d4f6ab&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4302     &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crc32_buffer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mh"&gt;0x44f71378&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4303     &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crc32_buffer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mh"&gt;0xd31de6c9&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4304     &lt;span class="c1"&gt;// ...&lt;/span&gt;
         4305 &lt;span class="p"&gt;}&lt;/span&gt;
         4306 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4307 
         4308 &lt;h2&gt;Setting up a Rust infrastructure for bzip2&lt;/h2&gt;
         4309 &lt;p&gt;Two things made this reasonably easy:&lt;/p&gt;
         4310 &lt;ul&gt;
         4311 &lt;li&gt;A patch from Stanislav Brabec, from Suse, to &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/72ece1146d6de1d2e6d2bb2cc96a1c3c0f307d7b"&gt;add an autotools
         4312   framework to bzip2&lt;/a&gt;&lt;/li&gt;
         4313 &lt;li&gt;The existing &lt;a href="https://people.gnome.org/~federico/blog/librsvg-build-infrastructure.html"&gt;Autotools + Rust machinery in librsvg&lt;/a&gt;.&lt;/li&gt;
         4314 &lt;/ul&gt;
         4315 &lt;p&gt;I.e. "copy and paste from somewhere that I know works well".
         4316 Wonderful!&lt;/p&gt;
         4317 &lt;p&gt;This is the &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/dfa0b88df8b518c4b76d0f3660b6487c67e93d52"&gt;commit that adds a Rust infrastructure for
         4318 bzip2&lt;/a&gt;.  It does the following:&lt;/p&gt;
         4319 &lt;ol&gt;
         4320 &lt;li&gt;Create a Cargo workspace (a &lt;code&gt;Cargo.toml&lt;/code&gt; in the toplevel) with a
         4321    single member, a &lt;code&gt;bzlib_rust&lt;/code&gt; directory where the Rustified parts
         4322    of the code will live.&lt;/li&gt;
         4323 &lt;li&gt;Create &lt;code&gt;bzlib_rust/Cargo.toml&lt;/code&gt; and &lt;code&gt;bzlib_rust/src&lt;/code&gt; for the Rust
         4324    sources.  This will generate a &lt;code&gt;staticlib&lt;/code&gt; for &lt;code&gt;libbzlib_rust.a&lt;/code&gt;, that
         4325    can be linked into the main &lt;code&gt;libbz2.la&lt;/code&gt;.&lt;/li&gt;
         4326 &lt;li&gt;Puts in automake hooks so that &lt;code&gt;make clean&lt;/code&gt;, &lt;code&gt;make check&lt;/code&gt;, etc. all
         4327    do what you expect for the Rust part.&lt;/li&gt;
         4328 &lt;/ol&gt;
         4329 &lt;p&gt;As a side benefit, librsvg's Autotools+Rust infrastructure already
         4330 handled things like cross-compilation correctly, so I have high hopes
         4331 that this will be good enough for bzip2.&lt;/p&gt;
         4332 &lt;h2&gt;Can I use a Rust crate for CRC32?&lt;/h2&gt;
         4333 &lt;p&gt;There are &lt;a href="https://crates.io/search?q=crc&amp;amp;sort=downloads"&gt;many Rust crates to do CRC computations&lt;/a&gt;.  I was
         4334 hoping especially to be able to use &lt;a href="https://github.com/srijs/rust-crc32fast"&gt;crc32fast&lt;/a&gt;, which is
         4335 SIMD-accelerated.&lt;/p&gt;
         4336 &lt;p&gt;I wrote a Rust version of the "CRC me a buffer" test from above to see
         4337 if crc32fast produced the same values as the C code, and of course it
         4338 didn't.  Eventually, after &lt;a href="https://mstdn.mx/@federicomena/102170914494787056"&gt;asking on Mastodon&lt;/a&gt;, Kepstin &lt;a href="https://glitch.social/@kepstin/102171203800281388"&gt;figured
         4339 out&lt;/a&gt; what variant of CRC32 is being used in the original
         4340 code.&lt;/p&gt;
         4341 &lt;p&gt;It turns out that this is directly doable in Rust with the &lt;a href="https://github.com/mrhooray/crc-rs"&gt;git version
         4342 of the &lt;code&gt;crc&lt;/code&gt; crate&lt;/a&gt;.  This crate lets one configure the CRC32
         4343 polynomial and the mode of computation; there are &lt;a href="https://github.com/Michaelangel007/crc32"&gt;many variants of
         4344 CRC32&lt;/a&gt; and I wasn't fully aware of them.&lt;/p&gt;
         4345 &lt;p&gt;The magic incantation is this:&lt;/p&gt;
         4346 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;digest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;crc32&lt;/span&gt;::&lt;span class="n"&gt;Digest&lt;/span&gt;::&lt;span class="n"&gt;new_custom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crc32&lt;/span&gt;::&lt;span class="n"&gt;IEEE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="k"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="k"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;crc&lt;/span&gt;::&lt;span class="n"&gt;CalcType&lt;/span&gt;::&lt;span class="n"&gt;Normal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4347 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4348 
         4349 &lt;p&gt;With that, &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/6ef10026a74af85437a4deca6957889d9e8bdbf8"&gt;the Rust
         4350 test&lt;/a&gt;
         4351 produces the same values as the C code.  Yay!&lt;/p&gt;
         4352 &lt;h2&gt;But it can't be that easy&lt;/h2&gt;
         4353 &lt;p&gt;Bzlib stores its internal state in the &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/60be65f9/bzlib_private.h#L182-252"&gt;EState
         4354 struct&lt;/a&gt;,
         4355 defined in
         4356 &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/60be65f9/bzlib_private.h"&gt;bzlib_private.h&lt;/a&gt;.&lt;/p&gt;
         4357 &lt;p&gt;That struct stores several running CRC32 computations, and the state
         4358 for each one of those is a single &lt;code&gt;UInt32&lt;/code&gt; value.  However, I cannot
         4359 just replace those struct fields with something that comes from Rust,
         4360 since the C code does not know the size of a &lt;code&gt;crc32::Digest&lt;/code&gt; from
         4361 Rust.&lt;/p&gt;
         4362 &lt;p&gt;The normal way to do this (say, like in librsvg) would be to turn
         4363 &lt;code&gt;UInt32 some_crc&lt;/code&gt; into &lt;code&gt;void *some_crc&lt;/code&gt; and heap-allocate that on the
         4364 Rust side, with whatever size it needs.&lt;/p&gt;
         4365 &lt;p&gt;&lt;strong&gt;However!&lt;/strong&gt;&lt;/p&gt;
         4366 &lt;p&gt;It turns out that bzlib lets the caller &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/blob/60be65f9/bzlib.h#L62-64"&gt;define a custom
         4367 allocator&lt;/a&gt;
         4368 so that bzlib doesn't use plain &lt;code&gt;malloc()&lt;/code&gt; by default.&lt;/p&gt;
         4369 &lt;p&gt;Rust lets one define a &lt;a href="https://doc.rust-lang.org/alloc/alloc/trait.GlobalAlloc.html"&gt;global, custom allocator&lt;/a&gt;.
         4370 However, bzlib's concept of a custom allocator includes a bit of
         4371 context:&lt;/p&gt;
         4372 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         4373     &lt;span class="c1"&gt;// ...&lt;/span&gt;
         4374 
         4375     &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;bzalloc&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;opaque&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4376     &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;bzfree&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;opaque&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4377     &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;opaque&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4378 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;bz_stream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4379 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4380 
         4381 &lt;p&gt;The caller sets up &lt;code&gt;bzalloc/bzfree&lt;/code&gt; callbacks and an optional &lt;code&gt;opaque&lt;/code&gt;
         4382 context for the allocator.  However, Rust's &lt;code&gt;GlobalAlloc&lt;/code&gt; is set up at
         4383 compilation time, and we can't pass that context in a good,
         4384 thread-safe fashion to it.&lt;/p&gt;
         4385 &lt;h2&gt;Who uses the bzlib custom allocator, anyway?&lt;/h2&gt;
         4386 &lt;p&gt;If one sets &lt;code&gt;bzalloc/bzfree&lt;/code&gt; to &lt;code&gt;NULL&lt;/code&gt;, bzlib will use the system's
         4387 plain &lt;code&gt;malloc()/free()&lt;/code&gt; by default.  Most software does this.&lt;/p&gt;
         4388 &lt;p&gt;I am looking in &lt;a href="https://codesearch.debian.net/search?q=bzalloc"&gt;Debian's codesearch&lt;/a&gt; for where &lt;code&gt;bzalloc&lt;/code&gt;
         4389 gets set, hoping that I can figure out if that software really needs a
         4390 custom allocator, or if they are just dressing up &lt;code&gt;malloc()&lt;/code&gt; with
         4391 logging code or similar (ImageMagick seems to do this; Python seems to
         4392 have a genuine concern about the Global Interpreter Lock).  Debian's
         4393 codesearch is a fantastic tool!&lt;/p&gt;
         4394 &lt;h2&gt;The first rustified code&lt;/h2&gt;
         4395 &lt;p&gt;I &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/2fb746e887d0fff705f5c82c961407b8539d96a2"&gt;cut&amp;amp;pasted the CRC32 lookup
         4396 table&lt;/a&gt;
         4397 and fixed it up for Rust's syntax, and also ported the CRC32
         4398 computation functions.  I gave them the same names as the original C
         4399 ones, and exported them, e.g.&lt;/p&gt;
         4400 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TABLE&lt;/span&gt;: &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4401 &lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mh"&gt;0x00000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x04c11db7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x09823b6e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x0d4326d9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4402 &lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4403 &lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4404 
         4405 &lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4406 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;BZ2_update_crc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crc_var&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cha&lt;/span&gt;: &lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4407 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;crc_var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;crc_var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TABLE&lt;/span&gt;&lt;span class="p"&gt;[((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;crc_var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;::&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cha&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4408 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4409 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4410 
         4411 &lt;p&gt;This is a straight port of the C code.  Rust is very strict about
         4412 integer sizes, and arrays can only be indexed with a &lt;code&gt;usize&lt;/code&gt;, not any
         4413 random integer — hence the explicit conversions.&lt;/p&gt;
         4414 &lt;p&gt;And with this, &lt;a href="https://gitlab.com/federicomenaquintero/bzip2/commit/c4c071059f98cfc2e4bb528bde499ba2d41a8b24"&gt;and after fixing the
         4415 linkage&lt;/a&gt;,
         4416 the tests pass!&lt;/p&gt;
         4417 &lt;p&gt;First pass at rustifying CRC32: &lt;strong&gt;done&lt;/strong&gt;.&lt;/p&gt;
         4418 &lt;h2&gt;But that does one byte at a time&lt;/h2&gt;
         4419 &lt;p&gt;Indeed; the original C code to do CRC32 only handled one byte at a
         4420 time.  If I replace this with a SIMD-enabled Rust crate, it will want
         4421 to process whole buffers at once.  I hope the code in bzlib can be
         4422 refactored to do that.  We'll see!&lt;/p&gt;
         4423 &lt;h2&gt;How to use an existing Rust crate for this&lt;/h2&gt;
         4424 &lt;p&gt;I just found out that one does not in fact need to use a complete
         4425 &lt;code&gt;crc32::Digest&lt;/code&gt; to do equivalent computations; one can call
         4426 &lt;a href="https://docs.rs/crc/1.8.1/crc/crc32/fn.update.html"&gt;crc32::update()&lt;/a&gt;
         4427 by hand and maintain a single &lt;code&gt;u32&lt;/code&gt; state, just like the original
         4428 &lt;code&gt;UInt32&lt;/code&gt; from the C code.&lt;/p&gt;
         4429 &lt;p&gt;So, I may not need to mess around with a custom allocator just yet.
         4430 Stay tuned.&lt;/p&gt;
         4431 &lt;p&gt;In the meantime, I've &lt;a href="https://github.com/srijs/rust-crc32fast/issues/9"&gt;filed a bug against
         4432 crc32fast&lt;/a&gt; to make
         4433 it possible to use a custom polynomial and order and still get the
         4434 benefits of SIMD.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="bzip2"></category></entry><entry><title>Containing mutability in GObjects</title><link href="https://people.gnome.org/~federico/blog/containing-mutability-in-gobjects.html" rel="alternate"></link><published>2019-04-16T17:04:33-05:00</published><updated>2019-04-16T17:04:40-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-04-16:/~federico/blog/containing-mutability-in-gobjects.html</id><summary type="html">&lt;p&gt;Traditionally, GObject implementations in C are mutable:  you
         4435 instantiate a GObject and then change its state via method calls.
         4436 Sometimes this is expected and desired; a &lt;code&gt;GtkCheckButton&lt;/code&gt; widget
         4437 certainly can change its internal state from pressed to not pressed,
         4438 for example.&lt;/p&gt;
         4439 &lt;p&gt;Other times, objects are mutable while they are being …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Traditionally, GObject implementations in C are mutable:  you
         4440 instantiate a GObject and then change its state via method calls.
         4441 Sometimes this is expected and desired; a &lt;code&gt;GtkCheckButton&lt;/code&gt; widget
         4442 certainly can change its internal state from pressed to not pressed,
         4443 for example.&lt;/p&gt;
         4444 &lt;p&gt;Other times, objects are mutable while they are being "assembled" or
         4445 "configured", and only yield a final immutable result until later.
         4446 This is the case for &lt;code&gt;RsvgHandle&lt;/code&gt; from librsvg.&lt;/p&gt;
         4447 &lt;p&gt;Please bear with me while I write about the history of the
         4448 &lt;code&gt;RsvgHandle&lt;/code&gt; API and why it ended up with different ways of doing the
         4449 same thing.&lt;/p&gt;
         4450 &lt;h2&gt;The traditional RsvgHandle API&lt;/h2&gt;
         4451 &lt;p&gt;The final purpose of an &lt;code&gt;RsvgHandle&lt;/code&gt; is to represent an SVG document
         4452 loaded in memory.  Once it is loaded, the SVG document does not
         4453 change, as librsvg does not support animation or creating/removing SVG
         4454 elements; it is a static renderer.&lt;/p&gt;
         4455 &lt;p&gt;However, before an &lt;code&gt;RsvgHandle&lt;/code&gt; achieves its immutable state, it has
         4456 to be loaded first.  Loading can be done in two ways:&lt;/p&gt;
         4457 &lt;ul&gt;
         4458 &lt;li&gt;The historical/deprecated way, using the &lt;a href="https://developer.gnome.org/rsvg/unstable/rsvg-RsvgHandle.html#rsvg-handle-write"&gt;&lt;code&gt;rsvg_handle_write()&lt;/code&gt;&lt;/a&gt; and
         4459   &lt;code&gt;rsvg_handle_close()&lt;/code&gt; APIs.  Plenty of code in GNOME used this
         4460   &lt;code&gt;write/close&lt;/code&gt; idiom before GLib got a good abstraction for
         4461   streams; you can see another example in &lt;a href="https://developer.gnome.org/gdk-pixbuf/unstable/GdkPixbufLoader.html"&gt;&lt;code&gt;GdkPixbufLoader&lt;/code&gt;&lt;/a&gt;.
         4462   The idea is that applications do this:&lt;/li&gt;
         4463 &lt;/ul&gt;
         4464 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;open&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4465 &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rsvg_handle_new&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
         4466 
         4467 &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         4468    &lt;span class="n"&gt;rsvg_handle_write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;bit&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4469 &lt;span class="p"&gt;}&lt;/span&gt;
         4470 
         4471 &lt;span class="n"&gt;rsvg_handle_close&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4472 
         4473 &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;fully&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;immutable&lt;/span&gt;
         4474 
         4475 &lt;span class="n"&gt;rsvg_handle_render&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4476 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4477 
         4478 &lt;ul&gt;
         4479 &lt;li&gt;The streaming way, with &lt;a href="https://developer.gnome.org/rsvg/unstable/rsvg-Using-RSVG-with-GIO.html#rsvg-handle-read-stream-sync"&gt;&lt;code&gt;rsvg_handle_read_stream_sync()&lt;/code&gt;&lt;/a&gt;,
         4480   which takes a &lt;a href="https://developer.gnome.org/gio/unstable/GInputStream.html"&gt;&lt;code&gt;GInputStream&lt;/code&gt;&lt;/a&gt;, or one of the convenience functions
         4481   which take a &lt;a href="https://developer.gnome.org/gio/unstable/GFile.html#GFile-struct"&gt;&lt;code&gt;GFile&lt;/code&gt;&lt;/a&gt; and produce a stream from it.&lt;/li&gt;
         4482 &lt;/ul&gt;
         4483 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g_file_new_for_path&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/foo/bar.svg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4484 &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g_file_read&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4485 &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rsvg_handle_new&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
         4486 
         4487 &lt;span class="n"&gt;rsvg_handle_read_stream_sync&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4488 
         4489 &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;fully&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;immutable&lt;/span&gt;
         4490 
         4491 &lt;span class="n"&gt;rsvg_handle_render&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         4492 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4493 
         4494 &lt;h2&gt;A bit of history&lt;/h2&gt;
         4495 &lt;p&gt;Let's consider a few of &lt;code&gt;RsvgHandle&lt;/code&gt;'s functions.&lt;/p&gt;
         4496 &lt;p&gt;&lt;strong&gt;Constructors:&lt;/strong&gt;&lt;/p&gt;
         4497 &lt;ul&gt;
         4498 &lt;li&gt;&lt;code&gt;rsvg_handle_new()&lt;/code&gt;&lt;/li&gt;
         4499 &lt;li&gt;&lt;code&gt;rsvg_handle_new_with_flags()&lt;/code&gt;&lt;/li&gt;
         4500 &lt;/ul&gt;
         4501 &lt;p&gt;&lt;strong&gt;Configure the handle for loading:&lt;/strong&gt;&lt;/p&gt;
         4502 &lt;ul&gt;
         4503 &lt;li&gt;&lt;code&gt;rsvg_handle_set_base_uri()&lt;/code&gt;&lt;/li&gt;
         4504 &lt;li&gt;&lt;code&gt;rsvg_handle_set_base_gfile()&lt;/code&gt;&lt;/li&gt;
         4505 &lt;/ul&gt;
         4506 &lt;p&gt;&lt;strong&gt;Deprecated loading API:&lt;/strong&gt;&lt;/p&gt;
         4507 &lt;ul&gt;
         4508 &lt;li&gt;&lt;code&gt;rsvg_handle_write()&lt;/code&gt;&lt;/li&gt;
         4509 &lt;li&gt;&lt;code&gt;rsvg_handle_close()&lt;/code&gt;&lt;/li&gt;
         4510 &lt;/ul&gt;
         4511 &lt;p&gt;&lt;strong&gt;Streaming API:&lt;/strong&gt;&lt;/p&gt;
         4512 &lt;ul&gt;
         4513 &lt;li&gt;&lt;code&gt;rsvg_handle_read_stream_sync()&lt;/code&gt;&lt;/li&gt;
         4514 &lt;/ul&gt;
         4515 &lt;p&gt;When librsvg first acquired the concept of an &lt;code&gt;RsvgHandle&lt;/code&gt;, it just
         4516 had &lt;code&gt;rsvg_handle_new()&lt;/code&gt; with no arguments.  About 9 years later, it
         4517 got &lt;code&gt;rsvg_handle_new_with_flags()&lt;/code&gt; to allow more options, but it took
         4518 another 2 years to actually add some usable flags — the first one was
         4519 to configure the parsing limits in the underlying calls to libxml2.&lt;/p&gt;
         4520 &lt;p&gt;About 3 years after &lt;code&gt;RsvgHandle&lt;/code&gt; appeared, it got
         4521 &lt;code&gt;rsvg_handle_set_base_uri()&lt;/code&gt; to configure the "base URI" against which
         4522 relative references in the SVG document get resolved.  For example, if
         4523 you are reading &lt;code&gt;/foo/bar.svg&lt;/code&gt; and it contains an element like &lt;code&gt;&amp;lt;image
         4524 xlink:ref="smiley.png"/&amp;gt;&lt;/code&gt;, then librsvg needs to be able to produce
         4525 the path &lt;code&gt;/foo/smiley.png&lt;/code&gt; and that is done relative to the base URI.
         4526 (The base URI is implicit when reading from a specific SVG file, but
         4527 it needs to be provided when reading from an arbitrary stream that may
         4528 not even come from a file.)&lt;/p&gt;
         4529 &lt;p&gt;Initially &lt;code&gt;RsvgHandle&lt;/code&gt; had the &lt;code&gt;write/close&lt;/code&gt; APIs, and 8 years later
         4530 it got the streaming functions once GIO appeared.  Eventually the
         4531 streaming API would be the preferred one, instead of just being a
         4532 convenience for those brave new apps that started using GIO.&lt;/p&gt;
         4533 &lt;p&gt;A summary of librsvg's API may be something like:&lt;/p&gt;
         4534 &lt;ul&gt;
         4535 &lt;li&gt;
         4536 &lt;p&gt;librsvg gets written initially; it doesn't even have an
         4537   &lt;code&gt;RsvgHandle&lt;/code&gt;, and just provides a single function which takes a
         4538   &lt;code&gt;FILE *&lt;/code&gt; and renders it to a &lt;code&gt;GdkPixbuf&lt;/code&gt;.&lt;/p&gt;
         4539 &lt;/li&gt;
         4540 &lt;li&gt;
         4541 &lt;p&gt;That gets replaced with &lt;code&gt;RsvgHandle&lt;/code&gt;, its single &lt;code&gt;rsvg_handle_new()&lt;/code&gt;
         4542   constructor, and the &lt;code&gt;write/close&lt;/code&gt; API to feed it data
         4543   progressively.&lt;/p&gt;
         4544 &lt;/li&gt;
         4545 &lt;li&gt;
         4546 &lt;p&gt;GIO appears, we get the first widespread streaming APIs in GNOME,
         4547   and &lt;code&gt;RsvgHandle&lt;/code&gt; gets the ability to read from streams.&lt;/p&gt;
         4548 &lt;/li&gt;
         4549 &lt;li&gt;
         4550 &lt;p&gt;&lt;code&gt;RsvgHandle&lt;/code&gt; gets &lt;code&gt;rsvg_handle_new_with_flags()&lt;/code&gt; because now apps
         4551   may want to configure extra stuff for libxml2.&lt;/p&gt;
         4552 &lt;/li&gt;
         4553 &lt;li&gt;
         4554 &lt;p&gt;When Cairo appears and librsvg is ported to it, &lt;code&gt;RsvgHandle&lt;/code&gt; gets an
         4555   extra flag so that SVGs rendered to PDF can embed image data
         4556   efficiently.&lt;/p&gt;
         4557 &lt;/li&gt;
         4558 &lt;/ul&gt;
         4559 &lt;p&gt;It's a convoluted history, but &lt;code&gt;git log -- rsvg.h&lt;/code&gt; makes it accessible.&lt;/p&gt;
         4560 &lt;h2&gt;Where is the mutability?&lt;/h2&gt;
         4561 &lt;p&gt;An &lt;code&gt;RsvgHandle&lt;/code&gt; gets created, with flags or without.  It's empty, and
         4562 doesn't know if it will be given data with the &lt;code&gt;write/close&lt;/code&gt; API or
         4563 with the streaming API.  Also, someone may call &lt;code&gt;set_base_uri()&lt;/code&gt; on
         4564 it.  So, the handle must remain mutable while it is being populated
         4565 with data.  After that, it can say, "no more changes, I'm done".&lt;/p&gt;
         4566 &lt;p&gt;In C, this doesn't even have a name.  Everything is mutable by default
         4567 all the time.  This monster was the private data of &lt;code&gt;RsvgHandle&lt;/code&gt;
         4568 before it got ported to Rust:&lt;/p&gt;
         4569 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;RsvgHandlePrivate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         4570     &lt;span class="c1"&gt;// set during construction&lt;/span&gt;
         4571     &lt;span class="n"&gt;RsvgHandleFlags&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4572 
         4573     &lt;span class="c1"&gt;// GObject-ism&lt;/span&gt;
         4574     &lt;span class="n"&gt;gboolean&lt;/span&gt; &lt;span class="n"&gt;is_disposed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4575 
         4576     &lt;span class="c1"&gt;// Extra crap for a deprecated API&lt;/span&gt;
         4577     &lt;span class="n"&gt;RsvgSizeFunc&lt;/span&gt; &lt;span class="n"&gt;size_func&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4578     &lt;span class="n"&gt;gpointer&lt;/span&gt; &lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4579     &lt;span class="n"&gt;GDestroyNotify&lt;/span&gt; &lt;span class="n"&gt;user_data_destroy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4580 
         4581     &lt;span class="c1"&gt;// Data only used while parsing an SVG&lt;/span&gt;
         4582     &lt;span class="n"&gt;RsvgHandleState&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4583     &lt;span class="n"&gt;RsvgDefs&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;defs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4584     &lt;span class="n"&gt;guint&lt;/span&gt; &lt;span class="n"&gt;nest_level&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4585     &lt;span class="n"&gt;RsvgNode&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;currentnode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4586     &lt;span class="n"&gt;RsvgNode&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;treebase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4587     &lt;span class="n"&gt;GHashTable&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;css_props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4588     &lt;span class="n"&gt;RsvgSaxHandler&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4589     &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;handler_nest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4590     &lt;span class="n"&gt;GHashTable&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4591     &lt;span class="n"&gt;xmlParserCtxtPtr&lt;/span&gt; &lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4592     &lt;span class="n"&gt;GError&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4593     &lt;span class="n"&gt;GCancellable&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cancellable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4594     &lt;span class="n"&gt;GInputStream&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;compressed_input_stream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4595 
         4596     &lt;span class="c1"&gt;// Data only used while rendering&lt;/span&gt;
         4597     &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;dpi_x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4598     &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;dpi_y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4599 
         4600     &lt;span class="c1"&gt;// The famous base URI, set before loading&lt;/span&gt;
         4601     &lt;span class="n"&gt;gchar&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;base_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4602     &lt;span class="n"&gt;GFile&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;base_gfile&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4603 
         4604     &lt;span class="c1"&gt;// Some internal stuff&lt;/span&gt;
         4605     &lt;span class="n"&gt;gboolean&lt;/span&gt; &lt;span class="n"&gt;in_loop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4606     &lt;span class="n"&gt;gboolean&lt;/span&gt; &lt;span class="n"&gt;is_testing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         4607 &lt;span class="p"&gt;};&lt;/span&gt;
         4608 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4609 
         4610 &lt;p&gt;"Single responsibility principle"?  This is a horror show.  That
         4611 &lt;code&gt;RsvgHandlePrivate&lt;/code&gt; struct has all of these:&lt;/p&gt;
         4612 &lt;ul&gt;
         4613 &lt;li&gt;Data only settable during construction (flags)&lt;/li&gt;
         4614 &lt;li&gt;Data set after construction, but which may only be set before
         4615   loading (base URI)&lt;/li&gt;
         4616 &lt;li&gt;Highly mutable data used only during the loading stage: state
         4617   machines, XML parsers, a stack of XML elements, CSS properties...&lt;/li&gt;
         4618 &lt;li&gt;The DPI (dots per inch) values only used during rendering.&lt;/li&gt;
         4619 &lt;li&gt;Assorted fields used at various stages of the handle's life.&lt;/li&gt;
         4620 &lt;/ul&gt;
         4621 &lt;p&gt;It took a lot of refactoring to get the code to a point where it was
         4622 clear that an &lt;code&gt;RsvgHandle&lt;/code&gt; in fact has distinct stages during its
         4623 lifetime, and that some of that data should only live during a
         4624 particular stage.  Before, everything seemed a jumble of fields, used
         4625 at various unclear points in the code (for the struct listing above,
         4626 I've grouped related fields together — they were somewhat shuffled in
         4627 the original code!).&lt;/p&gt;
         4628 &lt;h2&gt;What would a better separation look like?&lt;/h2&gt;
         4629 &lt;p&gt;In the &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/"&gt;master branch&lt;/a&gt;, now librsvg has this:&lt;/p&gt;
         4630 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="sd"&gt;/// Contains all the interior mutability for a RsvgHandle to be called&lt;/span&gt;
         4631 &lt;span class="sd"&gt;/// from the C API.&lt;/span&gt;
         4632 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;CHandle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4633 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;dpi&lt;/span&gt;: &lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Dpi&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4634 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;load_flags&lt;/span&gt;: &lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LoadFlags&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4635 
         4636 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt;: &lt;span class="nc"&gt;RefCell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Url&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4637 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// needed because the C api returns *const char&lt;/span&gt;
         4638 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;base_url_cstring&lt;/span&gt;: &lt;span class="nc"&gt;RefCell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CString&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4639 
         4640 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;size_callback&lt;/span&gt;: &lt;span class="nc"&gt;RefCell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SizeCallback&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4641 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;is_testing&lt;/span&gt;: &lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4642 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;load_state&lt;/span&gt;: &lt;span class="nc"&gt;RefCell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LoadState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4643 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4644 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4645 
         4646 &lt;p&gt;Internally, that &lt;code&gt;CHandle&lt;/code&gt; struct is now the private data of the
         4647 public &lt;code&gt;RsvgHandle&lt;/code&gt; object.  Note that all of &lt;code&gt;CHandle&lt;/code&gt;'s fields are a
         4648 &lt;code&gt;Cell&amp;lt;&amp;gt;&lt;/code&gt; or &lt;code&gt;RefCell&amp;lt;&amp;gt;&lt;/code&gt;:  in Rust terms, this means that those fields
         4649 allow for "interior mutability" in the &lt;code&gt;CHandle&lt;/code&gt; struct: they can be
         4650 modified after intialization.&lt;/p&gt;
         4651 &lt;p&gt;The last field's cell, &lt;code&gt;load_state&lt;/code&gt;, contains this type:&lt;/p&gt;
         4652 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;LoadState&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4653 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4654 
         4655 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Being loaded using the legacy write()/close() API&lt;/span&gt;
         4656 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Loading&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;: &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4657 
         4658 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Fully loaded, with a Handle to an SVG document&lt;/span&gt;
         4659 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ClosedOk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;: &lt;span class="nc"&gt;Handle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4660 
         4661 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ClosedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4662 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4663 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4664 
         4665 &lt;p&gt;A &lt;code&gt;CHandle&lt;/code&gt; starts in the &lt;code&gt;Start&lt;/code&gt; state, where it doesn't know if it
         4666 will be loaded with a stream, or with the legacy write/close API.&lt;/p&gt;
         4667 &lt;p&gt;If the caller uses the write/close API, the handle moves to the
         4668 &lt;code&gt;Loading&lt;/code&gt; state, which has a &lt;code&gt;buffer&lt;/code&gt; where it accumulates the data
         4669 being fed to it.&lt;/p&gt;
         4670 &lt;p&gt;But if the caller uses the stream API, the handle tries to parse an
         4671 SVG document from the stream, and it moves either to the &lt;code&gt;ClosedOk&lt;/code&gt;
         4672 state, or to the &lt;code&gt;ClosedError&lt;/code&gt; state if there is a parse error.&lt;/p&gt;
         4673 &lt;p&gt;Correspondingly, when using the write/close API, when the caller
         4674 finally calls &lt;code&gt;rsvg_handle_close()&lt;/code&gt;, the handle creates a stream for
         4675 the &lt;code&gt;buffer&lt;/code&gt;, parses it, and also gets either into the &lt;code&gt;ClosedOk&lt;/code&gt; or
         4676 &lt;code&gt;ClosedError&lt;/code&gt; state.&lt;/p&gt;
         4677 &lt;p&gt;If you look at the variant &lt;code&gt;ClosedOk { handle: Handle }&lt;/code&gt;, it contains
         4678 a fully loaded &lt;code&gt;Handle&lt;/code&gt; inside, which right now is just a wrapper
         4679 around a reference-counted &lt;code&gt;Svg&lt;/code&gt; object:&lt;/p&gt;
         4680 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Handle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4681 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;svg&lt;/span&gt;: &lt;span class="nc"&gt;Rc&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Svg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4682 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4683 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4684 
         4685 &lt;p&gt;The reason why &lt;code&gt;LoadState::ClosedOk&lt;/code&gt; does not contain an &lt;code&gt;Rc&amp;lt;Svg&amp;gt;&lt;/code&gt;
         4686 directly, and instead wraps it with a &lt;code&gt;Handle&lt;/code&gt;, is that this is just
         4687 the first pass at refactoring.  Also, &lt;code&gt;Handle&lt;/code&gt; contains some
         4688 API-level logic which I'm not completely sure makes sense as a
         4689 lower-level &lt;code&gt;Svg&lt;/code&gt; object.  We'll see.&lt;/p&gt;
         4690 &lt;h2&gt;Couldn't you move more of &lt;code&gt;CHandle&lt;/code&gt;'s fields into &lt;code&gt;LoadState&lt;/code&gt;?&lt;/h2&gt;
         4691 &lt;p&gt;Sort of, kind of, but the public API still lets one do things like
         4692 call &lt;code&gt;rsvg_handle_get_base_uri()&lt;/code&gt; after the handle is fully loaded,
         4693 even though its result will be of little value.  So, the fields that
         4694 hold the &lt;code&gt;base_uri&lt;/code&gt; information are kept in the longer-lived
         4695 &lt;code&gt;CHandle&lt;/code&gt;, not in the individual variants of &lt;code&gt;LoadState&lt;/code&gt;.&lt;/p&gt;
         4696 &lt;h2&gt;How does this look from the Rust API?&lt;/h2&gt;
         4697 &lt;p&gt;&lt;code&gt;CHandle&lt;/code&gt; implements the public C API of librsvg.  Internally,
         4698 &lt;code&gt;Handle&lt;/code&gt; implements the basic "load from stream", "get the geometry of
         4699 an SVG element", and "render to a Cairo context" functionality.&lt;/p&gt;
         4700 &lt;p&gt;This basic functionality gets exported in a cleaner way through the
         4701 &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/master/librsvg_crate/src/lib.rs"&gt;Rust API&lt;/a&gt;, discussed &lt;a href="https://people.gnome.org/~federico/blog/a-rust-api-for-librsvg.html"&gt;previously&lt;/a&gt;.  There is no
         4702 interior mutability in there at all; that API uses a builder pattern
         4703 to gradually configure an SVG loader, which returns a fully loaded
         4704 &lt;code&gt;SvgHandle&lt;/code&gt;, out of which you can create a &lt;code&gt;CairoRenderer&lt;/code&gt;.&lt;/p&gt;
         4705 &lt;p&gt;In fact, it may be possible to refactor all of this a bit and
         4706 implement &lt;code&gt;CHandle&lt;/code&gt; directly in terms of the new Rust API:  in effect,
         4707 use &lt;code&gt;CHandle&lt;/code&gt; as the "holding space" while the SVG loader gets
         4708 configured, and later turned into a fully loaded &lt;code&gt;SvgHandle&lt;/code&gt;
         4709 internally.&lt;/p&gt;
         4710 &lt;h2&gt;Conclusion&lt;/h2&gt;
         4711 &lt;p&gt;The C version of &lt;code&gt;RsvgHandle&lt;/code&gt;'s private structure used to have a bunch
         4712 of fields.  Without knowing the code, it was hard to know that they
         4713 belonged in groups, and each group corresponded roughtly to a stage in
         4714 the handle's lifetime.&lt;/p&gt;
         4715 &lt;p&gt;It took plenty of refactoring to get the fields split up cleanly in
         4716 librsvg's internals.  The process of refactoring &lt;code&gt;RsvgHandle&lt;/code&gt;'s fields,
         4717 and ensuring that the various states of a handle are consistent, in
         4718 fact exposed a few bugs where the state was not being checked
         4719 appropriately.  The public C API remains the same as always, but has
         4720 better internal checks now.&lt;/p&gt;
         4721 &lt;p&gt;GObject APIs tend to allow for a lot of mutability via methods that
         4722 change the internal state of objects.  For &lt;code&gt;RsvgHandle&lt;/code&gt;, it was possible
         4723 to change this into a single &lt;code&gt;CHandle&lt;/code&gt; that maintains the mutable data
         4724 in a contained fashion, and later translates it internally into an
         4725 immutable &lt;code&gt;Handle&lt;/code&gt; that represents a fully-loaded SVG document.  This
         4726 scheme ties in well with the new Rust API for librsvg, which keeps
         4727 everything immutable after creation.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category><category term="gnome"></category><category term="refactoring"></category></entry><entry><title>A Rust API for librsvg</title><link href="https://people.gnome.org/~federico/blog/a-rust-api-for-librsvg.html" rel="alternate"></link><published>2019-03-15T13:36:47-06:00</published><updated>2019-03-15T13:36:47-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-03-15:/~federico/blog/a-rust-api-for-librsvg.html</id><summary type="html">&lt;p&gt;After the librsvg team &lt;a href="https://people.gnome.org/~federico/blog/librsvg-gobject-in-rust.html"&gt;finished the rustification&lt;/a&gt; of
         4728 librsvg's main library, I wanted to start porting the high-level test
         4729 suite to Rust.  This is mainly to be able to run tests in parallel,
         4730 which &lt;code&gt;cargo test&lt;/code&gt; does automatically in order to reduce test times.
         4731 However, this meant that librsvg needed …&lt;/p&gt;</summary><content type="html">&lt;p&gt;After the librsvg team &lt;a href="https://people.gnome.org/~federico/blog/librsvg-gobject-in-rust.html"&gt;finished the rustification&lt;/a&gt; of
         4732 librsvg's main library, I wanted to start porting the high-level test
         4733 suite to Rust.  This is mainly to be able to run tests in parallel,
         4734 which &lt;code&gt;cargo test&lt;/code&gt; does automatically in order to reduce test times.
         4735 However, this meant that librsvg needed a Rust API that would exercise
         4736 the same code paths as the C entry points.&lt;/p&gt;
         4737 &lt;p&gt;At the same time, I wanted the Rust API to make it impossible to
         4738 misuse the library.  From the viewpoint of the C API, an &lt;code&gt;RsvgHandle&lt;/code&gt;
         4739 has different stages:&lt;/p&gt;
         4740 &lt;ul&gt;
         4741 &lt;li&gt;Just initialized&lt;/li&gt;
         4742 &lt;li&gt;Loading&lt;/li&gt;
         4743 &lt;li&gt;Loaded, or in an error state after a failed load&lt;/li&gt;
         4744 &lt;li&gt;Ready to render&lt;/li&gt;
         4745 &lt;/ul&gt;
         4746 &lt;p&gt;To ensure consistency, the public API checks that you cannot render an
         4747 &lt;code&gt;RsvgHandle&lt;/code&gt; that is not completely loaded yet, or one that resulted
         4748 in a loading error.  But wouldn't it be nice if it were impossible to
         4749 call the API functions in the wrong order?&lt;/p&gt;
         4750 &lt;p&gt;This is exactly what &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/master/librsvg_crate/src/lib.rs"&gt;the Rust API&lt;/a&gt; does.  There is a &lt;code&gt;Loader&lt;/code&gt;,
         4751 to which you give a filename or a stream, and it will return a
         4752 fully-loaded &lt;code&gt;SvgHandle&lt;/code&gt; or an error.  Then, you can only create a
         4753 &lt;code&gt;CairoRenderer&lt;/code&gt; if you have an &lt;code&gt;SvgHandle&lt;/code&gt;.&lt;/p&gt;
         4754 &lt;p&gt;For historical reasons, the C API in librsvg is not perfectly
         4755 consistent.  For example, some functions which return an error will
         4756 actually return a proper &lt;a href="https://developer.gnome.org/glib/stable/glib-Error-Reporting.html"&gt;&lt;code&gt;GError&lt;/code&gt;&lt;/a&gt;, but some others will just
         4757 return a &lt;code&gt;gboolean&lt;/code&gt; with no further explanation of what went wrong.
         4758 In contrast, all the Rust API functions that can fail will actually
         4759 return a &lt;a href="https://doc.rust-lang.org/std/result/index.html"&gt;&lt;code&gt;Result&lt;/code&gt;&lt;/a&gt;, and the error case will have a meaningful
         4760 error value.  In the Rust API, there is no "wrong order" in which the
         4761 various API functions and methods can be called; it tries to do the
         4762 whole "make invalid states unrepresentable".&lt;/p&gt;
         4763 &lt;p&gt;To implement &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/master/librsvg_crate/src/lib.rs"&gt;the Rust API&lt;/a&gt;, I had to do some refactoring of the
         4764 &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/master/rsvg_internals/src/handle.rs"&gt;internals&lt;/a&gt; that hook to the public entry points.  This made me
         4765 realize that librsvg could be a lot easier to use.  The C API has
         4766 always forced you to call it in this fashion:&lt;/p&gt;
         4767 &lt;ol&gt;
         4768 &lt;li&gt;Ask the SVG for its dimensions, or how big it is.&lt;/li&gt;
         4769 &lt;li&gt;Based on that, scale your Cairo context to the size you actually
         4770    want.&lt;/li&gt;
         4771 &lt;li&gt;Render the SVG to that context's current transformation matrix.&lt;/li&gt;
         4772 &lt;/ol&gt;
         4773 &lt;p&gt;But first, (1) gives you inadequate information because
         4774 &lt;code&gt;rsvg_handle_get_dimensions()&lt;/code&gt; returns &lt;a href="https://developer.gnome.org/rsvg/unstable/rsvg-RsvgHandle.html#RsvgDimensionData"&gt;a
         4775 structure&lt;/a&gt; with &lt;code&gt;int&lt;/code&gt; fields for the width and
         4776 height.  The API is similar to gdk-pixbuf's in that it always wants to
         4777 think in whole pixels.  However, an SVG is not necessarily
         4778 integer-sized.&lt;/p&gt;
         4779 &lt;p&gt;Then, (2) forces you to calculate some geometry in almost all cases,
         4780 as most apps want to render SVG content scaled proportionally to a
         4781 certain size.  This is not hard to do, but it's an inconvenience.&lt;/p&gt;
         4782 &lt;h2&gt;SVG dimensions&lt;/h2&gt;
         4783 &lt;p&gt;Let's look at (1) again.  The question, "how big is the SVG" is a bit
         4784 meaningless when we consider that SVGs &lt;strong&gt;can be scaled to any size&lt;/strong&gt;;
         4785 that's the whole point of them!&lt;/p&gt;
         4786 &lt;p&gt;When you ask &lt;code&gt;RsvgHandle&lt;/code&gt; how big it is, in reality it should look at
         4787 you and whisper in your ear, "how big do you want it to be?".&lt;/p&gt;
         4788 &lt;p&gt;And that's the thing.  The HTML/CSS/SVG model is that one embeds
         4789 content into &lt;strong&gt;viewports&lt;/strong&gt; of a given size.  The software is
         4790 responsible for scaling the content to fit into that viewport.&lt;/p&gt;
         4791 &lt;p&gt;In the end, what we want is a rendering function that takes a Cairo
         4792 context and a Rectangle for a viewport, and that's it.  The function
         4793 should take care of fitting the SVG's contents within that viewport.&lt;/p&gt;
         4794 &lt;p&gt;There is now &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/448"&gt;an open bug&lt;/a&gt; about exactly this sort of API.  In
         4795 the end, programs should just have to load their SVG handle, and
         4796 directly ask it to render at whatever size they need, instead of doing
         4797 the size computations by hand.&lt;/p&gt;
         4798 &lt;h2&gt;When will this be available?&lt;/h2&gt;
         4799 &lt;p&gt;I'm in the middle of a &lt;a href="https://gitlab.gnome.org/federico/librsvg/commits/viewport-with-offsets"&gt;rather large refactor&lt;/a&gt;
         4800 to make this &lt;em&gt;viewport&lt;/em&gt; concept really work.  So far this involves:&lt;/p&gt;
         4801 &lt;ul&gt;
         4802 &lt;li&gt;
         4803 &lt;p&gt;Defining APIs that take a viewport.&lt;/p&gt;
         4804 &lt;/li&gt;
         4805 &lt;li&gt;
         4806 &lt;p&gt;Refactoring all the geometry computation to support the semantics of the
         4807   C API, plus the new &lt;code&gt;with_viewport&lt;/code&gt; semantics.&lt;/p&gt;
         4808 &lt;/li&gt;
         4809 &lt;li&gt;
         4810 &lt;p&gt;Fixing the code that kept track of an internal offset for all
         4811   temporary images.&lt;/p&gt;
         4812 &lt;/li&gt;
         4813 &lt;li&gt;
         4814 &lt;p&gt;Refactoring all the code that mucks around with the Cairo context's
         4815   affine transformation matrix, which is a big mutable mess.&lt;/p&gt;
         4816 &lt;/li&gt;
         4817 &lt;li&gt;
         4818 &lt;p&gt;Tests, examples, documentation.&lt;/p&gt;
         4819 &lt;/li&gt;
         4820 &lt;/ul&gt;
         4821 &lt;p&gt;I want to make the Rust API available for the 2.46 release, which is
         4822 hopefully not too far off.  It should be ready for the next GNOME
         4823 release.  In the meantime, you can check out the open bugs for the
         4824 &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/milestones/20"&gt;2.46.0 milestone&lt;/a&gt;.  &lt;strong&gt;Help is appreciated; the deadline
         4825 for the first 3.33 tarballs is approximately one month from now!&lt;/strong&gt;&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category><category term="gnome"></category></entry><entry><title>Rust build scripts vs. Meson</title><link href="https://people.gnome.org/~federico/blog/rust-build-scripts.html" rel="alternate"></link><published>2019-02-27T12:14:12-06:00</published><updated>2019-02-27T12:14:12-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-02-27:/~federico/blog/rust-build-scripts.html</id><summary type="html">&lt;p&gt;One of the pain points in trying to make the &lt;a href="https://mesonbuild.com/"&gt;Meson&lt;/a&gt; build system work
         4826 with Rust and Cargo is Cargo's use of build scripts, i.e. the
         4827 &lt;code&gt;build.rs&lt;/code&gt; that many Rust programs use for doing things before the
         4828 main build.  This post is about my exploration of what &lt;code&gt;build …&lt;/code&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;One of the pain points in trying to make the &lt;a href="https://mesonbuild.com/"&gt;Meson&lt;/a&gt; build system work
         4829 with Rust and Cargo is Cargo's use of build scripts, i.e. the
         4830 &lt;code&gt;build.rs&lt;/code&gt; that many Rust programs use for doing things before the
         4831 main build.  This post is about my exploration of what &lt;code&gt;build.rs&lt;/code&gt;
         4832 does.&lt;/p&gt;
         4833 &lt;p&gt;Thanks to &lt;a href="https://nirbheek.in/"&gt;Nirbheek Chauhan&lt;/a&gt; for his comments
         4834 and additions to a draft of this article!&lt;/p&gt;
         4835 &lt;p&gt;TL;DR: &lt;code&gt;build.rs&lt;/code&gt; is pretty ad-hoc and somewhat primitive, when
         4836 compared to Meson's very nice, high-level patterns for build-time
         4837 things.&lt;/p&gt;
         4838 &lt;p&gt;I have the intuition that giving names to the things that are
         4839 usually done in &lt;code&gt;build.rs&lt;/code&gt; scripts, and creating abstractions for
         4840 them, can make it easier later to implement those abstractions in
         4841 terms of Meson.  Maybe we can eliminate &lt;code&gt;build.rs&lt;/code&gt; in most cases?
         4842 Maybe Cargo can acquire higher-level concepts that plug well to Meson?&lt;/p&gt;
         4843 &lt;p&gt;(That is... I think we can refactor our way out of this mess.)&lt;/p&gt;
         4844 &lt;h2&gt;What does &lt;code&gt;build.rs&lt;/code&gt; do?&lt;/h2&gt;
         4845 &lt;p&gt;The first paragraph in the &lt;a href="https://doc.rust-lang.org/cargo/reference/build-scripts.html"&gt;documentation for Cargo build
         4846 scripts&lt;/a&gt; tells us this:&lt;/p&gt;
         4847 &lt;blockquote&gt;
         4848 &lt;p&gt;Some packages need to compile third-party non-Rust code, for example
         4849 C libraries. Other packages need to link to C libraries which can
         4850 either be located on the system or possibly need to be built from
         4851 source. Others still need facilities for functionality such as code
         4852 generation before building (think parser generators).&lt;/p&gt;
         4853 &lt;/blockquote&gt;
         4854 &lt;p&gt;That is,&lt;/p&gt;
         4855 &lt;ul&gt;
         4856 &lt;li&gt;
         4857 &lt;p&gt;Compiling third-party non-Rust code.  For example, maybe there is a
         4858   C sub-library that the Rust crate needs.&lt;/p&gt;
         4859 &lt;/li&gt;
         4860 &lt;li&gt;
         4861 &lt;p&gt;Link to C libraries... located on the system... or built from
         4862   source.  For example, in &lt;a href="https://gtk-rs.org"&gt;gtk-rs&lt;/a&gt;, the &lt;a href="https://github.com/gtk-rs/sys"&gt;sys&lt;/a&gt; crates link to
         4863   &lt;code&gt;libgtk-3.so&lt;/code&gt;, &lt;code&gt;libcairo.so&lt;/code&gt;, etc. and need to find a way to locate
         4864   those libraries with &lt;code&gt;pkg-config&lt;/code&gt;.&lt;/p&gt;
         4865 &lt;/li&gt;
         4866 &lt;li&gt;
         4867 &lt;p&gt;Code generation.  In the C world this could be generating a parser
         4868   with &lt;code&gt;yacc&lt;/code&gt;; in the Rust world there are many utilities to generate
         4869   code that is later used in your actual program.&lt;/p&gt;
         4870 &lt;/li&gt;
         4871 &lt;/ul&gt;
         4872 &lt;p&gt;In the next sections I'll look briefly at each of these cases, but in
         4873 a different order.&lt;/p&gt;
         4874 &lt;h2&gt;Code generation&lt;/h2&gt;
         4875 &lt;p&gt;Here is an example, in &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/a5c8a9ca/rsvg_internals/build.rs"&gt;how librsvg generates code&lt;/a&gt;
         4876 for a couple of things that get autogenerated before compiling the
         4877 main library:&lt;/p&gt;
         4878 &lt;ul&gt;
         4879 &lt;li&gt;A perfect hash function (PHF) of attributes and CSS property names.&lt;/li&gt;
         4880 &lt;li&gt;A pair of lookup tables for SRGB linearization and un-linearization.&lt;/li&gt;
         4881 &lt;/ul&gt;
         4882 &lt;p&gt;For example, this is &lt;code&gt;main()&lt;/code&gt; in &lt;code&gt;build.rs&lt;/code&gt;:&lt;/p&gt;
         4883 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4884 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;generate_phf_of_svg_attributes&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4885 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;generate_srgb_tables&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4886 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4887 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4888 
         4889 &lt;p&gt;And this is the first few lines of of the first function:&lt;/p&gt;
         4890 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;generate_phf_of_svg_attributes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4891 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;::&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;OUT_DIR&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;attributes-codegen.rs&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4892 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BufWriter&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;::&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4893 
         4894 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;writeln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#[repr(C)]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4895 
         4896 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ... etc&lt;/span&gt;
         4897 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4898 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4899 
         4900 &lt;p&gt;Generate a path like &lt;code&gt;$OUT_DIR/attributes-codegen.rs&lt;/code&gt;, create a file
         4901 with that name, a &lt;code&gt;BufWriter&lt;/code&gt; for the file, and start outputting code
         4902 to it.&lt;/p&gt;
         4903 &lt;p&gt;Similarly, the second function:&lt;/p&gt;
         4904 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;generate_srgb_tables&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4905 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;linearize_table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;compute_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;linearize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4906 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unlinearize_table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;compute_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unlinearize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4907 
         4908 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;::&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;OUT_DIR&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;srgb-codegen.rs&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4909 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BufWriter&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;::&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4910 
         4911 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
         4912 
         4913 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;print_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;LINEARIZE&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;linearize_table&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4914 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;print_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UNLINEARIZE&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;unlinearize_table&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4915 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4916 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4917 
         4918 &lt;p&gt;Compute two lookup tables, create a file named
         4919 &lt;code&gt;$OUT_DIR/srgb-codegen.rs&lt;/code&gt;, and write the lookup tables to the file.&lt;/p&gt;
         4920 &lt;p&gt;Later in the actual librsvg code, the generated files get included
         4921 into the source code using the &lt;code&gt;include!&lt;/code&gt; macro.  For example, here is
         4922 where &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/a5c8a9ca/rsvg_internals/src/attributes.rs#L6"&gt;&lt;code&gt;attributes-codegen.rs&lt;/code&gt; gets included&lt;/a&gt;:&lt;/p&gt;
         4923 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// attributes.rs&lt;/span&gt;
         4924 
         4925 &lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;phf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// crate for perfect hash function&lt;/span&gt;
         4926 
         4927 &lt;span class="c1"&gt;// the generated file has the declaration for enum Attribute&lt;/span&gt;
         4928 &lt;span class="fm"&gt;include!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="fm"&gt;concat!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="fm"&gt;env!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;OUT_DIR&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/attributes-codegen.rs&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4929 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4930 
         4931 &lt;p&gt;One thing to note here is that the generated source files
         4932 (&lt;code&gt;attributes-codegen.rs&lt;/code&gt;, &lt;code&gt;srgb-codegen.rs&lt;/code&gt;) get put in &lt;code&gt;$OUT_DIR&lt;/code&gt;, a
         4933 directory that Cargo creates for the compilation artifacts.  The files &lt;strong&gt;do
         4934 not&lt;/strong&gt; get put into the original source directories with the rest of
         4935 the library's code; the idea is to keep the source directories
         4936 pristine.&lt;/p&gt;
         4937 &lt;p&gt;At least in those terms, Meson and Cargo agree that source directories
         4938 should be kept clean of autogenerated files.&lt;/p&gt;
         4939 &lt;p&gt;The &lt;a href="https://doc.rust-lang.org/cargo/reference/build-scripts.html#case-study-code-generation"&gt;Code Generation&lt;/a&gt; section of Cargo's documentation agrees:&lt;/p&gt;
         4940 &lt;blockquote&gt;
         4941 &lt;p&gt;In general, build scripts should not modify any files outside of
         4942 OUT_DIR. It may seem fine on the first blush, but it does cause
         4943 problems when you use such crate as a dependency, because there's an
         4944 implicit invariant that sources in .cargo/registry should be
         4945 immutable. cargo won't allow such scripts when packaging.&lt;/p&gt;
         4946 &lt;/blockquote&gt;
         4947 &lt;p&gt;Now, some things to note here:&lt;/p&gt;
         4948 &lt;ul&gt;
         4949 &lt;li&gt;
         4950 &lt;p&gt;Both the &lt;code&gt;build.rs&lt;/code&gt; program and the actual library sources look at
         4951   the &lt;code&gt;$OUT_DIR&lt;/code&gt; environment variable for the location of the
         4952   generated sources.&lt;/p&gt;
         4953 &lt;/li&gt;
         4954 &lt;li&gt;
         4955 &lt;p&gt;The Cargo docs say that if the code generator needs input files, it
         4956   can look for them based on its current directory, which will be the
         4957   toplevel of your source package (i.e. your toplevel &lt;code&gt;Cargo.toml&lt;/code&gt;).&lt;/p&gt;
         4958 &lt;/li&gt;
         4959 &lt;/ul&gt;
         4960 &lt;p&gt;&lt;strong&gt;Meson hates this scheme of things&lt;/strong&gt;.  In particular, Meson is very
         4961 systematic about where it finds input files and sources, and where
         4962 things like code generators are allowed to place their output.&lt;/p&gt;
         4963 &lt;p&gt;The way Meson communicates these paths to code generators is via
         4964 command-line arguments to &lt;a href="https://mesonbuild.com/Reference-manual.html#custom_target"&gt;"custom targets"&lt;/a&gt;.  Here is
         4965 &lt;a href="https://github.com/mesonbuild/meson/blob/master/test%20cases/common/145%20custom%20target%20multiple%20outputs/meson.build"&gt;an example&lt;/a&gt; that is easier to read than the
         4966 documentation:&lt;/p&gt;
         4967 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;gen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;find_program&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;generator.py&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4968 
         4969 &lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;custom_target&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;generated&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4970 &lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;&amp;#39;foo.h&amp;#39;, &amp;#39;foo.c&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4971 &lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;gen, &amp;#39;@OUTDIR@&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4972 &lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4973 &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         4974 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         4975 
         4976 &lt;p&gt;This defines a target named &lt;code&gt;'generated'&lt;/code&gt;, which will use the
         4977 &lt;code&gt;generator.py&lt;/code&gt; program to output two files, &lt;code&gt;foo.h&lt;/code&gt; and &lt;code&gt;foo.c&lt;/code&gt;.  That
         4978 Python program will get called with &lt;code&gt;@OUTDIR@&lt;/code&gt; as a command-line
         4979 argument; in effect, meson will call
         4980 &lt;code&gt;/full/path/to/generator.py @OUTDIR@&lt;/code&gt; explicitly, without any magic
         4981 passed through environment variables.&lt;/p&gt;
         4982 &lt;p&gt;If this looks similar to what Cargo does above with &lt;code&gt;build.rs&lt;/code&gt;, it's
         4983 because it &lt;strong&gt;is&lt;/strong&gt; similar.  It's just that &lt;strong&gt;Meson gives a name&lt;/strong&gt; to
         4984 the concept of generating code at build time (Meson's name for this is
         4985 a &lt;strong&gt;custom target&lt;/strong&gt;), and provides a mechanism to say which program is
         4986 the generator, which files it is expected to generate, and how to call
         4987 the program with appropriate arguments to put files in the right
         4988 place.&lt;/p&gt;
         4989 &lt;p&gt;In contrast, Cargo assumes that all of that information can be
         4990 inferred from an environment variable.&lt;/p&gt;
         4991 &lt;p&gt;In addition, if the custom target takes other files as input (say, so
         4992 it can call &lt;code&gt;yacc my-grammar.y&lt;/code&gt;), the &lt;code&gt;custom_target()&lt;/code&gt; command can
         4993 take an &lt;code&gt;input:&lt;/code&gt; argument.  This way, Meson can add a dependency on
         4994 those input files, so that the appropriate things will be rebuilt if
         4995 the input files change.&lt;/p&gt;
         4996 &lt;p&gt;Now, Cargo could very well provide a small utility crate that build
         4997 scripts could use to figure out all that information.  Meson would
         4998 tell Cargo to use its scheme of things, and pass it down to build
         4999 scripts via that utility crate.  I.e. to have&lt;/p&gt;
         5000 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// build.rs&lt;/span&gt;
         5001 
         5002 &lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cargo_high_level&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5003 
         5004 &lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cargo_high_level&lt;/span&gt;::&lt;span class="n"&gt;get_output_path&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;codegen.rs&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5005 &lt;span class="c1"&gt;//                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this, instead of:&lt;/span&gt;
         5006 
         5007 &lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;::&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;OUT_DIR&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;codegen.rs&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5008 
         5009 &lt;span class="c1"&gt;// let the build system know about generated dependencies&lt;/span&gt;
         5010 &lt;span class="n"&gt;cargo_high_level&lt;/span&gt;::&lt;span class="n"&gt;add_output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5011 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5012 
         5013 &lt;p&gt;A similar mechanism could be used for the way Meson likes to pass
         5014 command-line arguments to the programs that deal with custom targets.&lt;/p&gt;
         5015 &lt;h2&gt;Linking to C libraries on the system&lt;/h2&gt;
         5016 &lt;p&gt;Some Rust crates need to link to lower-level C libraries that actually
         5017 do the work.  For example, in &lt;a href="https://gtk-rs.org"&gt;gtk-rs&lt;/a&gt;, there are high-level binding
         5018 crates called &lt;code&gt;gtk&lt;/code&gt;, &lt;code&gt;gdk&lt;/code&gt;, &lt;code&gt;cairo&lt;/code&gt;, etc.  These use low-level crates
         5019 called &lt;code&gt;gtk-sys&lt;/code&gt;, &lt;code&gt;gdk-sys&lt;/code&gt;, &lt;code&gt;cairo-sys&lt;/code&gt;.  Those &lt;code&gt;-sys&lt;/code&gt; crates are
         5020 just direct wrappers on top of the C functions of the respective
         5021 system libraries:  &lt;code&gt;gtk-sys&lt;/code&gt; makes almost every function in 
         5022 &lt;code&gt;libgtk-3.so&lt;/code&gt; available as a Rust-callable function.&lt;/p&gt;
         5023 &lt;p&gt;System libraries sometimes live in a well-known part of the filesystem
         5024 (&lt;code&gt;/usr/lib64&lt;/code&gt;, for example); other times, like in Windows and MacOS,
         5025 they could be anywhere.  To find that location plus other related
         5026 metadata (include paths for C header files, library version), many
         5027 system libraries use &lt;a href="https://www.freedesktop.org/wiki/Software/pkg-config/"&gt;&lt;code&gt;pkg-config&lt;/code&gt;&lt;/a&gt;.  At the highest
         5028 level, one can run &lt;code&gt;pkg-config&lt;/code&gt; on the command line, or from build
         5029 scripts, to query some things about libraries.  For example:&lt;/p&gt;
         5030 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# &lt;span class="nv"&gt;what&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="s"&gt;s the system&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nv"&gt;s&lt;/span&gt; &lt;span class="nv"&gt;installed&lt;/span&gt; &lt;span class="nv"&gt;version&lt;/span&gt; &lt;span class="nv"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;GTK&lt;/span&gt;?
         5031 $ &lt;span class="nv"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nv"&gt;modversion&lt;/span&gt; &lt;span class="nv"&gt;gtk&lt;/span&gt;&lt;span class="o"&gt;+-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;
         5032 &lt;span class="mi"&gt;3&lt;/span&gt;.&lt;span class="mi"&gt;24&lt;/span&gt;.&lt;span class="mi"&gt;4&lt;/span&gt;
         5033 
         5034 # &lt;span class="nv"&gt;what&lt;/span&gt; &lt;span class="nv"&gt;compiler&lt;/span&gt; &lt;span class="nv"&gt;flags&lt;/span&gt; &lt;span class="nv"&gt;would&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="nv"&gt;compiler&lt;/span&gt; &lt;span class="nv"&gt;need&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;GTK&lt;/span&gt;?
         5035 $ &lt;span class="nv"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nv"&gt;cflags&lt;/span&gt; &lt;span class="nv"&gt;gtk&lt;/span&gt;&lt;span class="o"&gt;+-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;
         5036 &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;pthread&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;gtk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;at&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;spi2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;atk&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;at&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;spi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;dbus&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;lib64&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;dbus&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;gtk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;gio&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;unix&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;libxkbcommon&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;wayland&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;cairo&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;pango&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;harfbuzz&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;pango&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;fribidi&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;atk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;cairo&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;pixman&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;freetype2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;libdrm&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;libpng16&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;gdk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;pixbuf&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;libmount&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;blkid&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;uuid&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;glib&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;lib64&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;glib&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;
         5037 
         5038 # &lt;span class="nv"&gt;and&lt;/span&gt; &lt;span class="nv"&gt;which&lt;/span&gt; &lt;span class="nv"&gt;libraries&lt;/span&gt;?
         5039 $ &lt;span class="nv"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nv"&gt;libs&lt;/span&gt; &lt;span class="nv"&gt;gtk&lt;/span&gt;&lt;span class="o"&gt;+-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;
         5040 &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lgtk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lgdk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lpangocairo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lpango&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;latk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lcairo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;gobject&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lcairo&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lgdk_pixbuf&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lgio&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lgobject&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lglib&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;
         5041 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5042 
         5043 &lt;p&gt;There is a &lt;a href="https://docs.rs/pkg-config/0.3.14/pkg_config/"&gt;&lt;code&gt;pkg-config&lt;/code&gt; crate&lt;/a&gt; which &lt;code&gt;build.rs&lt;/code&gt; can
         5044 use to call this, and communicate that information to Cargo.  The
         5045 example in the crate's documentation is for asking pkg-config for the
         5046 &lt;code&gt;foo&lt;/code&gt; package, with version at least &lt;code&gt;1.2.3&lt;/code&gt;:&lt;/p&gt;
         5047 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pkg_config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5048 
         5049 &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5050 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;pkg_config&lt;/span&gt;::&lt;span class="n"&gt;Config&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;atleast_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1.2.3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;probe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5051 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5052 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5053 
         5054 &lt;p&gt;And the documentation says,&lt;/p&gt;
         5055 &lt;blockquote&gt;
         5056 &lt;p&gt;After running pkg-config all appropriate Cargo metadata will be
         5057 printed on stdout if the search was successful.&lt;/p&gt;
         5058 &lt;/blockquote&gt;
         5059 &lt;p&gt;Wait, what?&lt;/p&gt;
         5060 &lt;p&gt;Indeed, printing specially-formated stuff on stdout is how &lt;code&gt;build.rs&lt;/code&gt;
         5061 scripts communicate back to Cargo about their findings.  To quote &lt;a href="https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script"&gt;Cargo's docs
         5062 on build scripts&lt;/a&gt;; the following is talking
         5063 about the stdout of &lt;code&gt;build.rs&lt;/code&gt;:&lt;/p&gt;
         5064 &lt;blockquote&gt;
         5065 &lt;p&gt;Any line that starts with cargo: is interpreted directly by
         5066 Cargo. This line must be of the form cargo:key=value, like the
         5067 examples below:&lt;/p&gt;
         5068 &lt;/blockquote&gt;
         5069 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# &lt;span class="nv"&gt;specially&lt;/span&gt; &lt;span class="nv"&gt;recognized&lt;/span&gt; &lt;span class="nv"&gt;by&lt;/span&gt; &lt;span class="nv"&gt;Cargo&lt;/span&gt;
         5070 &lt;span class="nv"&gt;cargo&lt;/span&gt;:&lt;span class="nv"&gt;rustc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;link&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;static&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;foo&lt;/span&gt;
         5071 &lt;span class="nv"&gt;cargo&lt;/span&gt;:&lt;span class="nv"&gt;rustc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;link&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;native&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;foo&lt;/span&gt;
         5072 &lt;span class="nv"&gt;cargo&lt;/span&gt;:&lt;span class="nv"&gt;rustc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;foo&lt;/span&gt;
         5073 &lt;span class="nv"&gt;cargo&lt;/span&gt;:&lt;span class="nv"&gt;rustc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;FOO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;bar&lt;/span&gt;
         5074 # &lt;span class="nv"&gt;arbitrary&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;defined&lt;/span&gt; &lt;span class="nv"&gt;metadata&lt;/span&gt;
         5075 &lt;span class="nv"&gt;cargo&lt;/span&gt;:&lt;span class="nv"&gt;root&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;foo&lt;/span&gt;
         5076 &lt;span class="nv"&gt;cargo&lt;/span&gt;:&lt;span class="nv"&gt;libdir&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;lib&lt;/span&gt;
         5077 &lt;span class="nv"&gt;cargo&lt;/span&gt;:&lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;include&lt;/span&gt;
         5078 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5079 
         5080 &lt;p&gt;One can use the stdout of a &lt;code&gt;build.rs&lt;/code&gt; program to add additional
         5081 command-line options for &lt;code&gt;rustc&lt;/code&gt;, or set environment variables for it,
         5082 or add library paths, or specific libraries.&lt;/p&gt;
         5083 &lt;p&gt;&lt;strong&gt;Meson hates this scheme of things&lt;/strong&gt;.  I suppose it would prefer to
         5084 do the pkg-config calls itself, and then pass that information down to
         5085 Cargo, you guessed it, via command-line options or something
         5086 well-defined like that.  Again, the example &lt;code&gt;cargo_high_level&lt;/code&gt; crate I
         5087 proposed above could be used to communicate this information from
         5088 Meson to Cargo scripts.  Meson also doesn't like this because it would
         5089 prefer to know about &lt;code&gt;pkg-config&lt;/code&gt;-based libraries in a declarative
         5090 fashion, without having to run a random script like &lt;code&gt;build.rs&lt;/code&gt;.&lt;/p&gt;
         5091 &lt;h2&gt;Building C code from Rust&lt;/h2&gt;
         5092 &lt;p&gt;Finally, some Rust crates build a bit of C code and then link that
         5093 into the compiled Rust code.  I have no experience with that, but
         5094 the respective build scripts generally use the &lt;a href="https://docs.rs/cc/1.0.29/cc/"&gt;&lt;code&gt;cc&lt;/code&gt; crate&lt;/a&gt; to
         5095 call a C compiler and pass options to it conveniently.  I suppose
         5096 Meson would prefer to do this instead, or at least to have a
         5097 high-level way of passing down information to Cargo.&lt;/p&gt;
         5098 &lt;p&gt;In effect, Meson has to be in charge of picking the C compiler.
         5099 Having the thing-to-be-built pick on its own has caused big problems
         5100 in the past:  GObject-Introspection made the same mistake years ago
         5101 when it decided to use distutils to detect the C compiler; gtk-doc did
         5102 as well.  When those tools are used, we still deal with problems with
         5103 cross-compilation and when the system has more than one C compiler in
         5104 it.&lt;/p&gt;
         5105 &lt;h2&gt;Snarky comments about the Unix philosophy&lt;/h2&gt;
         5106 &lt;p&gt;If part of the Unix philosophy is that shit can be glued together with
         5107 environment variables and stringly-typed stdout... it's a pretty bad
         5108 philosophy.  All the cases above boil down to having a well-defined,
         5109 more or less strongly-typed way to pass information between programs
         5110 instead of shaking proverbial tree of the filesystem and the
         5111 environment and seeing if something usable falls down.&lt;/p&gt;
         5112 &lt;h2&gt;Would we really have to modify all &lt;code&gt;build.rs&lt;/code&gt; scripts for this?&lt;/h2&gt;
         5113 &lt;p&gt;Probably.  Why not?  Meson already has a lot of very well-structured
         5114 knowledge of how to deal with multi-platform compilation and
         5115 installation.  Re-creating this knowledge in ad-hoc ways in &lt;code&gt;build.rs&lt;/code&gt;
         5116 is not very pleasant or maintainable.&lt;/p&gt;
         5117 &lt;h3&gt;Related work&lt;/h3&gt;
         5118 &lt;ul&gt;
         5119 &lt;li&gt;
         5120 &lt;p&gt;&lt;a href="https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372"&gt;Cargo internals
         5121 thread on using a declarative format to specify external dependencies&lt;/a&gt;&lt;/p&gt;
         5122 &lt;/li&gt;
         5123 &lt;li&gt;
         5124 &lt;p&gt;&lt;a href="https://github.com/joshtriplett/metadeps"&gt;Run pkg-config from declarative dependencies in Cargo.toml&lt;/a&gt;&lt;/p&gt;
         5125 &lt;/li&gt;
         5126 &lt;/ul&gt;</content><category term="misc"></category><category term="rust"></category><category term="meson"></category></entry><entry><title>Who wrote librsvg?</title><link href="https://people.gnome.org/~federico/blog/who-wrote-librsvg.html" rel="alternate"></link><published>2019-02-15T13:12:19-06:00</published><updated>2019-02-15T13:12:19-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-02-15:/~federico/blog/who-wrote-librsvg.html</id><summary type="html">&lt;p&gt;Authors by lines of code, each year:&lt;/p&gt;
         5127 &lt;p&gt;&lt;img alt="Librsvg authors by lines of code by year" src="https://people.gnome.org/~federico/blog/images/librsvg-authors-2019-02.png"&gt;&lt;/p&gt;
         5128 &lt;p&gt;Authors by percentage of lines of code, each year:&lt;/p&gt;
         5129 &lt;p&gt;&lt;img alt="Librsvg authors by percentage of lines of code by year" src="https://people.gnome.org/~federico/blog/images/librsvg-authors-normalized-2019-02.png"&gt;&lt;/p&gt;
         5130 &lt;p&gt;Which lines of code remain each year?&lt;/p&gt;
         5131 &lt;p&gt;&lt;img alt="Lines of code that remain each year" src="https://people.gnome.org/~federico/blog/images/librsvg-lines-of-code-2019-02.png"&gt;&lt;/p&gt;
         5132 &lt;p&gt;The shitty thing about a gradual rewrite is that a few people end up
         5133 "owning" all the lines of source code.  Hopefully this post is a little …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Authors by lines of code, each year:&lt;/p&gt;
         5134 &lt;p&gt;&lt;img alt="Librsvg authors by lines of code by year" src="https://people.gnome.org/~federico/blog/images/librsvg-authors-2019-02.png"&gt;&lt;/p&gt;
         5135 &lt;p&gt;Authors by percentage of lines of code, each year:&lt;/p&gt;
         5136 &lt;p&gt;&lt;img alt="Librsvg authors by percentage of lines of code by year" src="https://people.gnome.org/~federico/blog/images/librsvg-authors-normalized-2019-02.png"&gt;&lt;/p&gt;
         5137 &lt;p&gt;Which lines of code remain each year?&lt;/p&gt;
         5138 &lt;p&gt;&lt;img alt="Lines of code that remain each year" src="https://people.gnome.org/~federico/blog/images/librsvg-lines-of-code-2019-02.png"&gt;&lt;/p&gt;
         5139 &lt;p&gt;The shitty thing about a gradual rewrite is that a few people end up
         5140 "owning" all the lines of source code.  Hopefully this post is a little
         5141 acknowledgment of the people that made librsvg possible.&lt;/p&gt;
         5142 &lt;p&gt;The charts are made with the incredible tool
         5143 &lt;a href="https://github.com/erikbern/git-of-theseus"&gt;git-of-theseus&lt;/a&gt; — thanks
         5144 to &lt;a href="https://mastodon.art/@norwin"&gt;@norwin@mastodon.art&lt;/a&gt; for digging it
         5145 up!  Its README also points to a
         5146 &lt;a href="https://github.com/src-d/hercules"&gt;Hercules&lt;/a&gt; plotter with awesome
         5147 graphs.  You know, for if you needed something to keep your computer
         5148 busy during the weekend.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category></entry><entry><title>Librsvg's GObject boilerplate is in Rust now</title><link href="https://people.gnome.org/~federico/blog/librsvg-gobject-in-rust.html" rel="alternate"></link><published>2019-01-23T18:12:44-06:00</published><updated>2019-01-23T18:12:44-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-01-23:/~federico/blog/librsvg-gobject-in-rust.html</id><summary type="html">&lt;p&gt;The other day I wrote about how &lt;a href="https://people.gnome.org/~federico/blog/librsvg-is-almost-rustified.html"&gt;most of librsvg's library code is in
         5149 Rust now&lt;/a&gt;.  &lt;/p&gt;
         5150 &lt;p&gt;Today I finished porting the GObject boilerplate for the main
         5151 &lt;code&gt;RsvgHandle&lt;/code&gt; object into Rust.  This means that the C code no longer
         5152 calls things like &lt;code&gt;g_type_register_static()&lt;/code&gt;, nor implements
         5153 &lt;code&gt;rsvg_handle_class_init()&lt;/code&gt; and such; all those are …&lt;/p&gt;</summary><content type="html">&lt;p&gt;The other day I wrote about how &lt;a href="https://people.gnome.org/~federico/blog/librsvg-is-almost-rustified.html"&gt;most of librsvg's library code is in
         5154 Rust now&lt;/a&gt;.  &lt;/p&gt;
         5155 &lt;p&gt;Today I finished porting the GObject boilerplate for the main
         5156 &lt;code&gt;RsvgHandle&lt;/code&gt; object into Rust.  This means that the C code no longer
         5157 calls things like &lt;code&gt;g_type_register_static()&lt;/code&gt;, nor implements
         5158 &lt;code&gt;rsvg_handle_class_init()&lt;/code&gt; and such; all those are in Rust now.  How
         5159 is this done?&lt;/p&gt;
         5160 &lt;h2&gt;The life-changing magic of glib::subclass&lt;/h2&gt;
         5161 &lt;p&gt;&lt;a href="https://coaxion.net/blog/"&gt;Sebastian Dröge&lt;/a&gt; has been working for many months on refining
         5162 utilities to make it possible to subclass GObjects in Rust, with
         5163 little or no unsafe code.  This &lt;a href="https://github.com/gtk-rs/glib/tree/master/src/subclass"&gt;subclass&lt;/a&gt; module is now part of
         5164 &lt;a href="https://github.com/gtk-rs/glib"&gt;glib-rs&lt;/a&gt;, the Rust bindings to GLib.  &lt;/p&gt;
         5165 &lt;p&gt;Librsvg now uses the subclassing functionality in glib-rs, which takes
         5166 care of some things automatically:&lt;/p&gt;
         5167 &lt;ul&gt;
         5168 &lt;li&gt;Registering your GObject types at runtime.&lt;/li&gt;
         5169 &lt;li&gt;Creating safe traits on which you can implement &lt;code&gt;class_init&lt;/code&gt;,
         5170   &lt;code&gt;instance_init&lt;/code&gt;, &lt;code&gt;set_property&lt;/code&gt;, &lt;code&gt;get_property&lt;/code&gt;, and all the usual
         5171   GObject paraphernalia.&lt;/li&gt;
         5172 &lt;/ul&gt;
         5173 &lt;p&gt;Check this out:&lt;/p&gt;
         5174 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib&lt;/span&gt;::&lt;span class="n"&gt;subclass&lt;/span&gt;::&lt;span class="n"&gt;prelude&lt;/span&gt;::&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5175 
         5176 &lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ObjectSubclass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5177 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;NAME&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nb"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;RsvgHandle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5178 
         5179 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;ParentType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib&lt;/span&gt;::&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5180 
         5181 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Instance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RsvgHandle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5182 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RsvgHandleClass&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5183 
         5184 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;glib_object_subclass&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5185 
         5186 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;class_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;klass&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RsvgHandleClass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5187 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;klass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;install_properties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PROPERTIES&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5188 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5189 
         5190 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Self&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5191 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5192 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5193 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5194 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5195 
         5196 &lt;p&gt;In the &lt;code&gt;impl&lt;/code&gt; line, &lt;code&gt;Handle&lt;/code&gt; is librsvg's internals object — what used
         5197 to be &lt;code&gt;RsvgHandlePrivate&lt;/code&gt; in the C code.&lt;/p&gt;
         5198 &lt;p&gt;The following lines say this:&lt;/p&gt;
         5199 &lt;ul&gt;
         5200 &lt;li&gt;
         5201 &lt;p&gt;&lt;code&gt;const NAME: &amp;amp;'static str = "RsvgHandle";&lt;/code&gt; - the name of the type,
         5202   for GType's perusal.&lt;/p&gt;
         5203 &lt;/li&gt;
         5204 &lt;li&gt;
         5205 &lt;p&gt;&lt;code&gt;type ParentType = glib::Object;&lt;/code&gt; - Parent class.&lt;/p&gt;
         5206 &lt;/li&gt;
         5207 &lt;li&gt;
         5208 &lt;p&gt;&lt;code&gt;type Instance&lt;/code&gt;, &lt;code&gt;type Class&lt;/code&gt; - Structs with &lt;code&gt;#[repr(C)]&lt;/code&gt;,
         5209   equivalent to GObject's class and instance structs.&lt;/p&gt;
         5210 &lt;/li&gt;
         5211 &lt;li&gt;
         5212 &lt;p&gt;&lt;code&gt;glib_object_subclass!();&lt;/code&gt; - All the boilerplate happens here
         5213   automatically.&lt;/p&gt;
         5214 &lt;/li&gt;
         5215 &lt;li&gt;
         5216 &lt;p&gt;&lt;code&gt;fn class_init&lt;/code&gt; - Should be familiar to anyone who implements
         5217   GObjects!&lt;/p&gt;
         5218 &lt;/li&gt;
         5219 &lt;/ul&gt;
         5220 &lt;p&gt;And then, a couple of the property declarations:&lt;/p&gt;
         5221 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PROPERTIES&lt;/span&gt;: &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;subclass&lt;/span&gt;::&lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5222 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;subclass&lt;/span&gt;::&lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;flags&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5223 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;ParamSpec&lt;/span&gt;::&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5224 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5225 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Flags&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5226 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Loading flags&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5227 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;HandleFlags&lt;/span&gt;::&lt;span class="n"&gt;static_type&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5228 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5229 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;ParamFlags&lt;/span&gt;::&lt;span class="n"&gt;READWRITE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParamFlags&lt;/span&gt;::&lt;span class="n"&gt;CONSTRUCT_ONLY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5230 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5231 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5232 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;subclass&lt;/span&gt;::&lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dpi-x&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5233 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;ParamSpec&lt;/span&gt;::&lt;span class="n"&gt;double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5234 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5235 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Horizontal DPI&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5236 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Horizontal resolution in dots per inch&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5237 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5238 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;::&lt;span class="n"&gt;MAX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5239 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5240 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;ParamFlags&lt;/span&gt;::&lt;span class="n"&gt;READWRITE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParamFlags&lt;/span&gt;::&lt;span class="n"&gt;CONSTRUCT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5241 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5242 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5243 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ... etcetera&lt;/span&gt;
         5244 &lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5245 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5246 
         5247 &lt;p&gt;This is quite similar to the way C code usually registers properties
         5248 for new GObject subclasses.&lt;/p&gt;
         5249 &lt;p&gt;The moment at which a new GObject subclass gets registered against the
         5250 GType system is in the &lt;code&gt;foo_get_type()&lt;/code&gt; call.  This is the C code in
         5251 librsvg for that:&lt;/p&gt;
         5252 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;GType&lt;/span&gt; &lt;span class="nf"&gt;rsvg_handle_rust_get_type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         5253 
         5254 &lt;span class="n"&gt;GType&lt;/span&gt;
         5255 &lt;span class="nf"&gt;rsvg_handle_get_type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         5256 &lt;span class="p"&gt;{&lt;/span&gt;
         5257     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rsvg_handle_rust_get_type&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
         5258 &lt;span class="p"&gt;}&lt;/span&gt;
         5259 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5260 
         5261 &lt;p&gt;And the Rust function that actually implements this:&lt;/p&gt;
         5262 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5263 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;rsvg_handle_rust_get_type&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;glib_sys&lt;/span&gt;::&lt;span class="n"&gt;GType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5264 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;::&lt;span class="n"&gt;get_type&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;to_glib&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5265 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5266 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5267 
         5268 &lt;p&gt;Here, &lt;code&gt;Handle::get_type()&lt;/code&gt; gets implemented automatically by
         5269 Sebastian's &lt;a href="https://github.com/gtk-rs/glib/tree/master/src/subclass"&gt;subclass&lt;/a&gt; traits.  It gets things like the type name and
         5270 the parent class from the &lt;code&gt;impl ObjectSubclass for Handle&lt;/code&gt; we saw
         5271 above, and calls &lt;code&gt;g_type_register_static()&lt;/code&gt; internally.&lt;/p&gt;
         5272 &lt;p&gt;I can confirm now that implementing GObjects in Rust in this way, and
         5273 exposing them to C, really works and is actually quite pleasant to
         5274 do.  &lt;a href="https://gitlab.gnome.org/federico/librsvg/blob/subclass/rsvg_internals/src/c_api.rs"&gt;You can look at librsvg's Rust code for GObject here&lt;/a&gt;.&lt;/p&gt;
         5275 &lt;h2&gt;Further work&lt;/h2&gt;
         5276 &lt;p&gt;There is some auto-generated C code to register librsvg's error enum
         5277 and a flags type against GType; I'll move those to Rust over the next
         5278 few days.&lt;/p&gt;
         5279 &lt;p&gt;Then, I think I'll try to actually remove all of the library's entry
         5280 points from the C code and implement them in Rust.  Right now each C
         5281 function is really just a single call to a Rust function, so this
         5282 should be trivial-ish to do.&lt;/p&gt;
         5283 &lt;p&gt;I'm waiting for a glib-rs release, the first one that will have the
         5284 &lt;code&gt;glib::subclass&lt;/code&gt; code in it, before merging all of the above into
         5285 librsvg's master branch.&lt;/p&gt;
         5286 &lt;h2&gt;A new Rust API for librsvg?&lt;/h2&gt;
         5287 &lt;p&gt;Finally, this got me thinking about what to do about the Rust bindings
         5288 to librsvg itself.  The &lt;a href="https://github.com/selaux/rsvg-rs"&gt;rsvg crate&lt;/a&gt; uses the gtk-rs
         5289 machinery to generate the binding:  it reads the &lt;a href="https://people.gnome.org/~federico/blog/magic-of-gobject-introspection.html"&gt;GObject
         5290 Introspection&lt;/a&gt; data from &lt;code&gt;Rsvg.gir&lt;/code&gt; and generates a Rust binding
         5291 for it.&lt;/p&gt;
         5292 &lt;p&gt;However, the resulting API is mostly identical to the C API.  There is
         5293 an &lt;code&gt;rsvg::Handle&lt;/code&gt; with the same methods as the ones from C's
         5294 &lt;code&gt;RsvgHandle&lt;/code&gt;... and that API is not particularly Rusty.&lt;/p&gt;
         5295 &lt;p&gt;At some point I had an unfinished branch to &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commits/import-rsvg-rs"&gt;merge rsvg-rs into
         5296 librsvg&lt;/a&gt;.  The intention was that librsvg's build procedure
         5297 would first build &lt;code&gt;librsvg.so&lt;/code&gt; itself, then generate &lt;code&gt;Rsvg.gir&lt;/code&gt; as
         5298 usual, and &lt;strong&gt;then&lt;/strong&gt; generate rsvg-rs from that.  But I got tired of
         5299 fucking with Autotools, and didn't finish integrating the projects.&lt;/p&gt;
         5300 &lt;p&gt;Rsvg-rs is an &lt;em&gt;okay&lt;/em&gt; Rust API for using librsvg.  It still works
         5301 perfectly well from the &lt;a href="https://github.com/selaux/rsvg-rs"&gt;standalone crate&lt;/a&gt;.  However, now
         5302 that all the functionality of librsvg is in Rust, I would like to take
         5303 this opportunity to experiment with a better API for loading and
         5304 rendering SVGs from Rust.  This may make it more clear how to refactor
         5305 the toplevel of the library.  Maybe the &lt;code&gt;librsvg&lt;/code&gt; project can provide
         5306 its own Rust crate for public consumption, in addition to the usual
         5307 &lt;code&gt;librsvg.so&lt;/code&gt; and &lt;code&gt;Rsvg.gir&lt;/code&gt; which need to remain with a stable API and
         5308 ABI.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category><category term="rust"></category></entry><entry><title>Librsvg is almost rustified now</title><link href="https://people.gnome.org/~federico/blog/librsvg-is-almost-rustified.html" rel="alternate"></link><published>2019-01-10T12:28:11-06:00</published><updated>2019-01-10T12:28:11-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2019-01-10:/~federico/blog/librsvg-is-almost-rustified.html</id><summary type="html">&lt;p&gt;Since a few days ago, librsvg's library implementation is almost 100%
         5309 Rust code.  Paolo Borelli's and Carlos Martín Nieto's latest commits
         5310 made it possible.&lt;/p&gt;
         5311 &lt;p&gt;What does "almost 100% Rust code" mean here?&lt;/p&gt;
         5312 &lt;ul&gt;
         5313 &lt;li&gt;
         5314 &lt;p&gt;The C code no longer has struct fields that refer to the library's
         5315   real work.  The only field …&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Since a few days ago, librsvg's library implementation is almost 100%
         5316 Rust code.  Paolo Borelli's and Carlos Martín Nieto's latest commits
         5317 made it possible.&lt;/p&gt;
         5318 &lt;p&gt;What does "almost 100% Rust code" mean here?&lt;/p&gt;
         5319 &lt;ul&gt;
         5320 &lt;li&gt;
         5321 &lt;p&gt;The C code no longer has struct fields that refer to the library's
         5322   real work.  The only field in &lt;code&gt;RsvgHandlePrivate&lt;/code&gt; is an opaque
         5323   pointer to a Rust-side structure.  All the rest of the library's
         5324   data lives in Rust structs.&lt;/p&gt;
         5325 &lt;/li&gt;
         5326 &lt;li&gt;
         5327 &lt;p&gt;The public API is implemented in C, but it is just stubs that
         5328   immediately call into Rust functions.  For example:&lt;/p&gt;
         5329 &lt;/li&gt;
         5330 &lt;/ul&gt;
         5331 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;gboolean&lt;/span&gt;
         5332 &lt;span class="nf"&gt;rsvg_handle_render_cairo_sub&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RsvgHandle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cairo_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         5333 &lt;span class="p"&gt;{&lt;/span&gt;
         5334     &lt;span class="n"&gt;g_return_val_if_fail&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RSVG_IS_HANDLE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;FALSE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         5335     &lt;span class="n"&gt;g_return_val_if_fail&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FALSE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         5336 
         5337     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rsvg_handle_rust_render_cairo_sub&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         5338 &lt;span class="p"&gt;}&lt;/span&gt;
         5339 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5340 
         5341 &lt;ul&gt;
         5342 &lt;li&gt;
         5343 &lt;p&gt;The GObject boilerplate and supporting code is still in C:
         5344   &lt;code&gt;rsvg_handle_class_init&lt;/code&gt; and &lt;code&gt;set_property&lt;/code&gt; and friends.&lt;/p&gt;
         5345 &lt;/li&gt;
         5346 &lt;li&gt;
         5347 &lt;p&gt;All the high-level tests are still done in C.&lt;/p&gt;
         5348 &lt;/li&gt;
         5349 &lt;li&gt;
         5350 &lt;p&gt;The gdk-pixbuf loader for SVG files is done in C.&lt;/p&gt;
         5351 &lt;/li&gt;
         5352 &lt;/ul&gt;
         5353 &lt;p&gt;Someone posted a &lt;a href="https://www.reddit.com/r/rust/comments/ae5xwd/librsvg_oxidation/"&gt;chart on Reddit about the rustification of librsvg&lt;/a&gt;,
         5354 comparing lines of code in each language vs. time.&lt;/p&gt;
         5355 &lt;h2&gt;Rustifying the remaining C code&lt;/h2&gt;
         5356 &lt;p&gt;There is only a handful of very small functions from the public API
         5357 still implemented in C, and I am converting them one by one to Rust.
         5358 These are just helper functions built on top of other public API that
         5359 does the real work.&lt;/p&gt;
         5360 &lt;p&gt;Converting the gdk-pixbuf loader to Rust seems like writing a little
         5361 glue code for the loadable module; the actual loading is just a couple
         5362 of calls to librsvg's API.&lt;/p&gt;
         5363 &lt;h3&gt;Rsvg-rs in rsvg?&lt;/h3&gt;
         5364 &lt;p&gt;Converting the tests to Rust... ideally this would use the &lt;a href="https://github.com/selaux/rsvg-rs"&gt;rsvg-rs&lt;/a&gt;
         5365 bindings; for example, it is what I already use for &lt;a href="https://gitlab.gnome.org/federico/rsvg-bench"&gt;rsvg-bench&lt;/a&gt;, a
         5366 benchmarking program for librsvg.&lt;/p&gt;
         5367 &lt;p&gt;I have an &lt;a href="https://gitlab.gnome.org/federico/librsvg/commits/import-rsvg-rs"&gt;unfinished branch to merge the rsvg-rs repository&lt;/a&gt;
         5368 into librsvg's own repository.  This is because...&lt;/p&gt;
         5369 &lt;ol&gt;
         5370 &lt;li&gt;Librsvg builds its library, &lt;code&gt;librsvg.so&lt;/code&gt;&lt;/li&gt;
         5371 &lt;li&gt;Gobject-introspection runs on &lt;code&gt;librsvg.so&lt;/code&gt; and the source code, and
         5372    produces &lt;code&gt;librsvg.gir&lt;/code&gt;&lt;/li&gt;
         5373 &lt;li&gt;Rsvg-rs's build system calls &lt;a href="https://github.com/gtk-rs/gir/"&gt;gir&lt;/a&gt; on &lt;code&gt;librsvg.gir&lt;/code&gt; to generate the
         5374    Rust binding's code.&lt;/li&gt;
         5375 &lt;/ol&gt;
         5376 &lt;p&gt;As you can imagine, doing all of this with Autotools is... rather
         5377 convoluted.  It gives me a lot of anxiety to think that there is also
         5378 an &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commits/wip/meson"&gt;unfinished branch to port the build system to Meson&lt;/a&gt;, where
         5379 &lt;em&gt;probably&lt;/em&gt; doing the .so→.gir→rs chain would be easier, but who
         5380 knows.  Help in this area is &lt;strong&gt;much&lt;/strong&gt; appreciated!&lt;/p&gt;
         5381 &lt;h3&gt;An alternative?&lt;/h3&gt;
         5382 &lt;p&gt;Rustified tests could, of course, call the C API of librsvg by hand,
         5383 in &lt;code&gt;unsafe&lt;/code&gt; code.  This may not be idiomatic, but sounds like it could
         5384 be done relatively quickly.&lt;/p&gt;
         5385 &lt;h2&gt;Future work&lt;/h2&gt;
         5386 &lt;p&gt;There are two options to get rid of all the C code in the library, and
         5387 just leave C header files for public consumption:&lt;/p&gt;
         5388 &lt;ol&gt;
         5389 &lt;li&gt;
         5390 &lt;p&gt;Do the GObject implementation in Rust, using Sebastian Dröge's work
         5391    from GStreamer to do this easily.&lt;/p&gt;
         5392 &lt;/li&gt;
         5393 &lt;li&gt;
         5394 &lt;p&gt;Work on making &lt;a href="https://gitlab.gnome.org/federico/gnome-class"&gt;gnome-class&lt;/a&gt; powerful enough to implement the librsvg
         5395    API directly, and in an ABI-compatible fashion to what there is
         5396    right now.&lt;/p&gt;
         5397 &lt;/li&gt;
         5398 &lt;/ol&gt;
         5399 &lt;p&gt;The second case will probably build upon the first one, since one of
         5400 my plans for gnome-class is to make it generate code that uses
         5401 Sebastian's, instead of generating all the GObject boilerplate by
         5402 hand.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category><category term="rust"></category></entry><entry><title>In support of Coraline Ada Ehmke</title><link href="https://people.gnome.org/~federico/blog/in-support-of-coraline.html" rel="alternate"></link><published>2018-12-07T14:00:06-06:00</published><updated>2018-12-07T14:00:06-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-12-07:/~federico/blog/in-support-of-coraline.html</id><summary type="html">&lt;p&gt;Last night, the linux.org DNS was hijacked and redirected to a page
         5403 that doxed her.  Coraline is doing extremely valuable work with the
         5404 &lt;a href="https://www.contributor-covenant.org/"&gt;Contributor Covenant&lt;/a&gt; code of conduct, which many free software
         5405 projects have &lt;a href="https://www.contributor-covenant.org/adopters"&gt;adopted&lt;/a&gt; already.&lt;/p&gt;
         5406 &lt;p&gt;Coraline has been working for years in making free software, and
         5407 computer technology …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Last night, the linux.org DNS was hijacked and redirected to a page
         5408 that doxed her.  Coraline is doing extremely valuable work with the
         5409 &lt;a href="https://www.contributor-covenant.org/"&gt;Contributor Covenant&lt;/a&gt; code of conduct, which many free software
         5410 projects have &lt;a href="https://www.contributor-covenant.org/adopters"&gt;adopted&lt;/a&gt; already.&lt;/p&gt;
         5411 &lt;p&gt;Coraline has been working for years in making free software, and
         5412 computer technology circles in general, a welcome place for
         5413 underrepresented groups.&lt;/p&gt;
         5414 &lt;p&gt;I hope Coraline stays safe and strong.  You can &lt;a href="https://www.patreon.com/coraline"&gt;support her directly
         5415 on Patreon&lt;/a&gt;.&lt;/p&gt;</content><category term="misc"></category><category term="code-of-conduct"></category></entry><entry><title>My GUADEC 2018 presentation</title><link href="https://people.gnome.org/~federico/blog/guadec-2018-presentation.html" rel="alternate"></link><published>2018-12-04T18:57:00-06:00</published><updated>2018-12-06T15:09:43-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-12-04:/~federico/blog/guadec-2018-presentation.html</id><summary type="html">&lt;p&gt;I just realized that I forgot to publish my presentation from this
         5416 year's GUADEC.  Sorry, here it is!&lt;/p&gt;
         5417 &lt;p&gt;&lt;a href="https://people.gnome.org/~federico/blog/docs/fmq-refactoring-c-to-rust.pdf"&gt;&lt;img alt="Patterns of refactoring C to Rust - link to PDF" src="https://people.gnome.org/~federico/blog/images/fmq-refactoring-c-to-rust.png"&gt;&lt;/a&gt;&lt;/p&gt;
         5418 &lt;p&gt;You can also get the &lt;a href="https://people.gnome.org/~federico/blog/docs/fmq-refactoring-c-to-rust.odp"&gt;ODP file&lt;/a&gt; for the presentation.  This is
         5419 released under a &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC-BY-SA license&lt;/a&gt;.&lt;/p&gt;
         5420 &lt;p&gt;This is the &lt;a href="http://videos.guadec.org/2018/GUADEC%202018%20-%20Federico%20Mena%20Quintero%20-%20Patterns%20of%20refactoring%20C%20to%20Rust-5mVMycYmoWE.mp4"&gt;video of the presentation&lt;/a&gt;.&lt;/p&gt;
         5421 &lt;p&gt;&lt;strong&gt;&lt;em&gt;Update Dec/06:&lt;/em&gt;&lt;/strong&gt; Keen readers spotted an &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/391"&gt;incorrect …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;I just realized that I forgot to publish my presentation from this
         5422 year's GUADEC.  Sorry, here it is!&lt;/p&gt;
         5423 &lt;p&gt;&lt;a href="https://people.gnome.org/~federico/blog/docs/fmq-refactoring-c-to-rust.pdf"&gt;&lt;img alt="Patterns of refactoring C to Rust - link to PDF" src="https://people.gnome.org/~federico/blog/images/fmq-refactoring-c-to-rust.png"&gt;&lt;/a&gt;&lt;/p&gt;
         5424 &lt;p&gt;You can also get the &lt;a href="https://people.gnome.org/~federico/blog/docs/fmq-refactoring-c-to-rust.odp"&gt;ODP file&lt;/a&gt; for the presentation.  This is
         5425 released under a &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC-BY-SA license&lt;/a&gt;.&lt;/p&gt;
         5426 &lt;p&gt;This is the &lt;a href="http://videos.guadec.org/2018/GUADEC%202018%20-%20Federico%20Mena%20Quintero%20-%20Patterns%20of%20refactoring%20C%20to%20Rust-5mVMycYmoWE.mp4"&gt;video of the presentation&lt;/a&gt;.&lt;/p&gt;
         5427 &lt;p&gt;&lt;strong&gt;&lt;em&gt;Update Dec/06:&lt;/em&gt;&lt;/strong&gt; Keen readers spotted an &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/391"&gt;incorrect use of opaque
         5428 pointers&lt;/a&gt;; I've updated the example code in the presentation to
         5429 match &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/merge_requests/161"&gt;Jordan's fix with the recommended usage&lt;/a&gt;.  That merge
         5430 request has an interesting conversation on FFI esoterica, too.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category><category term="rust"></category><category term="talks"></category></entry><entry><title>Refactoring allowed URLs in librsvg</title><link href="https://people.gnome.org/~federico/blog/refactoring-allowed-urls-in-librsvg.html" rel="alternate"></link><published>2018-11-29T11:31:37-06:00</published><updated>2018-11-29T11:31:37-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-11-29:/~federico/blog/refactoring-allowed-urls-in-librsvg.html</id><summary type="html">&lt;p&gt;While in the middle of converting librsvg's code that processes XML from C
         5431 to Rust, I went into a digression that has to do with the way librsvg
         5432 decides which files are allowed to be referenced from within an SVG.&lt;/p&gt;
         5433 &lt;h1&gt;Resource references in SVG&lt;/h1&gt;
         5434 &lt;p&gt;SVG files can reference other files …&lt;/p&gt;</summary><content type="html">&lt;p&gt;While in the middle of converting librsvg's code that processes XML from C
         5435 to Rust, I went into a digression that has to do with the way librsvg
         5436 decides which files are allowed to be referenced from within an SVG.&lt;/p&gt;
         5437 &lt;h1&gt;Resource references in SVG&lt;/h1&gt;
         5438 &lt;p&gt;SVG files can reference other files, i.e. they are not
         5439 self-contained.  For example, there can be an element like &lt;code&gt;&amp;lt;image
         5440 xlink:href="foo.png"&amp;gt;&lt;/code&gt;, or one can request that a sub-element of
         5441 another SVG be included with &lt;code&gt;&amp;lt;use xlink:href="secondary.svg#foo"&amp;gt;&lt;/code&gt;.
         5442 Finally, there is the &lt;code&gt;xi:include&lt;/code&gt; mechanism to include chunks of text
         5443 or XML into another XML file.&lt;/p&gt;
         5444 &lt;p&gt;Since librsvg is sometimes used to render untrusted files that come from
         5445 the internet, it needs to be careful not to allow those files to
         5446 reference any random resource on the filesystem.  We don't want
         5447 something like
         5448 &lt;code&gt;&amp;lt;text&amp;gt;&amp;lt;xi:include href="/etc/passwd" parse="text"/&amp;gt;&amp;lt;/text&amp;gt;&lt;/code&gt;
         5449 or something equally nefarious that would exfiltrate a random file
         5450 into the rendered output.&lt;/p&gt;
         5451 &lt;p&gt;Also, want to catch malicious SVGs that want to "phone home" by
         5452 referencing a network resource like
         5453 &lt;code&gt;&amp;lt;image xlink:href="http://evil.com/pingback.jpg"&amp;gt;&lt;/code&gt;.&lt;/p&gt;
         5454 &lt;p&gt;So, librsvg is careful to have a single place where it can load
         5455 secondary resources, and first it validates the resource's URL to see
         5456 if it is allowed.&lt;/p&gt;
         5457 &lt;p&gt;The actual validation rules are not very important for this
         5458 discussion; they are something like "no absolute URLs allowed" (so you
         5459 can't request &lt;code&gt;/etc/passwd&lt;/code&gt;, "only siblings or (grand)children of
         5460 siblings allowed" (so &lt;code&gt;foo.svg&lt;/code&gt; can request &lt;code&gt;bar.svg&lt;/code&gt; and
         5461 &lt;code&gt;subdir/bar.svg&lt;/code&gt;, but not &lt;code&gt;../../bar.svg&lt;/code&gt;).&lt;/p&gt;
         5462 &lt;h1&gt;The code&lt;/h1&gt;
         5463 &lt;p&gt;There was a central function &lt;code&gt;rsvg_io_acquire_stream()&lt;/code&gt; which took a
         5464 URL as a string.  The code assumed that that URL had been first
         5465 validated with a function called &lt;code&gt;allow_load(url)&lt;/code&gt;.  While the code's
         5466 structure guaranteed that all the places that may acquire a stream
         5467 would actually go through &lt;code&gt;allow_load()&lt;/code&gt; first, the structure of the
         5468 code in Rust made it possible to actually make it impossible to
         5469 acquire a disallowed URL.&lt;/p&gt;
         5470 &lt;p&gt;Before:&lt;/p&gt;
         5471 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;allow_load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5472 
         5473 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;acquire_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;gio&lt;/span&gt;::&lt;span class="n"&gt;InputStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib&lt;/span&gt;::&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5474 
         5475 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;rsvg_acquire_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;gio&lt;/span&gt;::&lt;span class="n"&gt;InputStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LoadingError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5476 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;allow_load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5477 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;acquire_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5478 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5479 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoadingError&lt;/span&gt;::&lt;span class="n"&gt;NotAllowed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5480 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5481 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5482 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5483 
         5484 &lt;p&gt;The refactored code now has an &lt;code&gt;AllowedUrl&lt;/code&gt; type that encapsulates a
         5485 URL, plus the promise that it &lt;strong&gt;has&lt;/strong&gt; gone through these steps:&lt;/p&gt;
         5486 &lt;ul&gt;
         5487 &lt;li&gt;The URL has been run through a URL well-formedness parser.&lt;/li&gt;
         5488 &lt;li&gt;The resource is allowed to be loaded following librsvg's rules.&lt;/li&gt;
         5489 &lt;/ul&gt;
         5490 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;AllowedUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// from the Url parsing crate&lt;/span&gt;
         5491 
         5492 &lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AllowedUrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5493 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_href&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;href&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AllowedUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5494 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Url&lt;/span&gt;::&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// may return LoadingError::InvalidUrl&lt;/span&gt;
         5495 
         5496 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;allow_load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5497 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AllowedUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5498 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5499 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoadingError&lt;/span&gt;::&lt;span class="n"&gt;NotAllowed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5500 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5501 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5502 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5503 
         5504 &lt;span class="c1"&gt;// new prototype&lt;/span&gt;
         5505 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;acquire_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;AllowedUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;gio&lt;/span&gt;::&lt;span class="n"&gt;InputStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib&lt;/span&gt;::&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5506 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5507 
         5508 &lt;p&gt;This forces callers to validate the URLs as soon as possible, right
         5509 after they get them from the SVG file.  Now it is not possible to
         5510 request a stream unless the URL has been validated first.&lt;/p&gt;
         5511 &lt;h1&gt;Plain URIs vs. fragment identifiers&lt;/h1&gt;
         5512 &lt;p&gt;Some of the elements in SVG that reference other data require full
         5513 files:&lt;/p&gt;
         5514 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="n"&gt;xlink&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo.png&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;fragments&lt;/span&gt; &lt;span class="n"&gt;allowed&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
         5515 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5516 
         5517 &lt;p&gt;And some others, that reference particular elements in secondary SVGs,
         5518 require a fragment ID:&lt;/p&gt;
         5519 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;xlink&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;icons.svg#app_name&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="n"&gt;fragment&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
         5520 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5521 
         5522 &lt;p&gt;And finally, the &lt;code&gt;feImage&lt;/code&gt; element, used to paste an image as part of
         5523 a filter effects pipeline, allows either:&lt;/p&gt;
         5524 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
         5525 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;feImage&lt;/span&gt; &lt;span class="n"&gt;xlink&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo.png&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
         5526 
         5527 &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="n"&gt;just&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;SVG&lt;/span&gt; &lt;span class="kr"&gt;and&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
         5528 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;feImage&lt;/span&gt; &lt;span class="n"&gt;xlink&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo.svg#element&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
         5529 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5530 
         5531 &lt;p&gt;So, I introduced a general &lt;code&gt;Href&lt;/code&gt; parser :&lt;/p&gt;
         5532 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Href&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5533 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;PlainUri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5534 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;WithFragment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Fragment&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5535 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5536 
         5537 &lt;span class="sd"&gt;/// Optional URI, mandatory fragment id&lt;/span&gt;
         5538 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Fragment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5539 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5540 
         5541 &lt;p&gt;The parts of the code that absolutely require a fragment id now take a
         5542 &lt;code&gt;Fragment&lt;/code&gt;.  Parts which require a &lt;code&gt;PlainUri&lt;/code&gt; can unwrap that case.&lt;/p&gt;
         5543 &lt;p&gt;The next step is making those structs contain an &lt;code&gt;AllowedUrl&lt;/code&gt;
         5544 directly, instead of just strings, so that for callers, obtaining a
         5545 fully validated name is a one-step operation.&lt;/p&gt;
         5546 &lt;p&gt;In general, the code is moving towards a scheme where all file I/O is
         5547 done at loading time.  Right now, some of those external references
         5548 get resolved at rendering time, which is somewhat awkward (for
         5549 example, at rendering time the caller has no chance to use a
         5550 &lt;code&gt;GCancellable&lt;/code&gt; to cancel loading).  This refactoring to do early
         5551 validation is leaving the code in a very nice state.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category><category term="rust"></category></entry><entry><title>Thessaloniki GNOME+Rust Hackfest 2018</title><link href="https://people.gnome.org/~federico/blog/thessaloniki-gnome-rust-2018.html" rel="alternate"></link><published>2018-11-27T17:37:31-06:00</published><updated>2018-11-27T17:37:31-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-11-27:/~federico/blog/thessaloniki-gnome-rust-2018.html</id><summary type="html">&lt;p&gt;A couple of weeks ago we had the &lt;a href="https://wiki.gnome.org/Hackfests/Rust2018-2"&gt;fourth GNOME+Rust hackfest&lt;/a&gt;, this time
         5552 in Thessaloniki, Greece.  This is the beautiful city that will host
         5553 next year's GUADEC, but fortunately GUADEC will be in summertime!&lt;/p&gt;
         5554 &lt;p&gt;We held the hackfest at the &lt;a href="http://coho.gr/"&gt;CoHo&lt;/a&gt; coworking space, a small, cozy
         5555 office between the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;A couple of weeks ago we had the &lt;a href="https://wiki.gnome.org/Hackfests/Rust2018-2"&gt;fourth GNOME+Rust hackfest&lt;/a&gt;, this time
         5556 in Thessaloniki, Greece.  This is the beautiful city that will host
         5557 next year's GUADEC, but fortunately GUADEC will be in summertime!&lt;/p&gt;
         5558 &lt;p&gt;We held the hackfest at the &lt;a href="http://coho.gr/"&gt;CoHo&lt;/a&gt; coworking space, a small, cozy
         5559 office between the University and the sea.&lt;/p&gt;
         5560 &lt;p&gt;Every such hackfest I am overwhelmed by the kind hackers who work on
         5561 [gnome-class], the code generator for GObject implementations in
         5562 Rust.&lt;/p&gt;
         5563 &lt;p&gt;Mredlek has been working on generalizing the code generators in
         5564 gnome-class, so that we can have the following from the same run:&lt;/p&gt;
         5565 &lt;ul&gt;
         5566 &lt;li&gt;
         5567 &lt;p&gt;Rust code generation, for the GObject implementations themselves.
         5568   Thanks to mredlek, this is much cleaner than it was before; now both
         5569   classes and interfaces share the same code for most of the
         5570   boilerplate.&lt;/p&gt;
         5571 &lt;/li&gt;
         5572 &lt;li&gt;
         5573 &lt;p&gt;GObject Introspection (&lt;code&gt;.gir&lt;/code&gt;) generation, so that language bindings
         5574   can be generated automatically.&lt;/p&gt;
         5575 &lt;/li&gt;
         5576 &lt;li&gt;
         5577 &lt;p&gt;C header files (&lt;code&gt;.h&lt;/code&gt;), so the generated GObjects can be called from
         5578   C code as usual.&lt;/p&gt;
         5579 &lt;/li&gt;
         5580 &lt;/ul&gt;
         5581 &lt;p&gt;So far, Rust and GIR work; C header files are not generated yet.&lt;/p&gt;
         5582 &lt;p&gt;Mredlek is a new contributor to gnome-class, but unfortunately was not
         5583 able to attend the hackfest.  Not only did he rewrite the gnome-class
         5584 parser using the new version of &lt;a href="https://docs.rs/syn/0.15.22/syn/"&gt;syn&lt;/a&gt;; he also added support for
         5585 passing owned types to GObject methods, such as &lt;code&gt;String&lt;/code&gt; and
         5586 &lt;code&gt;Variant&lt;/code&gt;.  But the biggest thing is probably that mredlek made it a
         5587 lot easier to debug the generated Rust source; see &lt;a href="https://federico.pages.gitlab.gnome.org/gnome-class/doc/gobject_gen/#debugging-aids-and-examining-generated-code"&gt;the documentation
         5588 on debugging&lt;/a&gt; for details.&lt;/p&gt;
         5589 &lt;p&gt;Speaking of which, thanks to Jordan Petridis for making the
         5590 documentation be published automatically from Gitlab's Continuous
         5591 Integration pipelines.&lt;/p&gt;
         5592 &lt;p&gt;Alex Crichton kindly refactored our error propagation code, and &lt;a href="https://federico.pages.gitlab.gnome.org/gnome-class/book/errors.html"&gt;even
         5593 wrote docs on it&lt;/a&gt;!  Along with Jordan, they updated the
         5594 code for the Rust 2018 edition, and generally wrangled the build
         5595 process to conform with the lastest Rust nightlies.  Alex also made
         5596 code generation a lot faster, by offloading auto-indentation to an
         5597 external &lt;code&gt;rustfmt&lt;/code&gt; process, instead of using it as a crate:  using the
         5598 &lt;code&gt;rustfmt&lt;/code&gt; crate meant that the compiler had a lot more work to do.
         5599 During the whole hackfest, Alex was very helpful with Rust questions
         5600 in general.  While my strategy to see what the compiler does is to
         5601 examine the disassembly in gdb, his strategy seems to be to look at
         5602 the LLVM intermediate representation instead... OMG.&lt;/p&gt;
         5603 &lt;h1&gt;And we can derive very simple GtkWidgets now!&lt;/h1&gt;
         5604 &lt;p&gt;Saving the best for last... Antoni Boucher, the author of &lt;a href="http://relm.ml/"&gt;relm&lt;/a&gt;, has
         5605 been working on making it possible to derive from &lt;code&gt;gtk::Widget&lt;/code&gt;.  Once
         5606 &lt;a href="https://gitlab.gnome.org/federico/gnome-class/merge_requests/40"&gt;this merge request&lt;/a&gt; is done, we'll have an example of
         5607 deriving from &lt;code&gt;gtk::DrawingArea&lt;/code&gt; from Rust with very little code.&lt;/p&gt;
         5608 &lt;p&gt;Normally, the &lt;a href="https://gtk-rs.org/"&gt;gtk-rs&lt;/a&gt; bindings work as a statically-generated binding
         5609 for GObject, which really is a type hierarchy defined at runtime.  The
         5610 static binding really wants to know what is a subclass of what:  it
         5611 needs to know in advance that &lt;code&gt;Button&lt;/code&gt;'s hierarchy is &lt;code&gt;Button → Bin →
         5612 Container → Widget → Object&lt;/code&gt;, plus all the &lt;code&gt;GTypeInterface&lt;/code&gt;s supported
         5613 by any of those classes.  Antoni has been working on making
         5614 gnome-class extract that information automatically from GIR files, so
         5615 that the gtk-rs macros that define new types will get all the
         5616 necessary information.&lt;/p&gt;
         5617 &lt;h1&gt;Future work&lt;/h1&gt;
         5618 &lt;p&gt;There are still &lt;a href="https://gitlab.gnome.org/GNOME/gtk/merge_requests/415"&gt;bugs&lt;/a&gt; in the GIR pipeline that prevent us
         5619 from deriving, say, from &lt;code&gt;gtk::Container&lt;/code&gt;, but hopefully these will be
         5620 resolved soon.&lt;/p&gt;
         5621 &lt;p&gt;Sebastian Dröge has been refactoring his Rust tools to create GObject
         5622 subclasses with very idiomatic and refined Rust code.  This is now at
         5623 a state where gnome-class itself could generate that sort of code,
         5624 instead of generating all the boilerplate from scratch.  So, we'll
         5625 start doing that, and integrating the necessary bits into gtk-rs as
         5626 well.&lt;/p&gt;
         5627 &lt;p&gt;Finally, during the last day I took a little break from gnome-class to
         5628 work on librsvg.  Julian Sparber has been updating the code to use new
         5629 bindings in cairo-rs, and is also adding a &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/merge_requests/152"&gt;new API&lt;/a&gt; to
         5630 fetch an SVG element's geometry precisely.&lt;/p&gt;
         5631 &lt;h1&gt;Thessaloniki&lt;/h1&gt;
         5632 &lt;p&gt;Oh, boy, I wish the weather had been warmer.  The city looks
         5633 delightful to walk around, especially in the narrow streets on the
         5634 hills.  Can't wait to see it in summer during GUADEC.&lt;/p&gt;
         5635 &lt;h1&gt;Thanks&lt;/h1&gt;
         5636 &lt;p&gt;Finally, thanks to &lt;a href="http://coho.gr/"&gt;CoHo&lt;/a&gt; for hosting the hackfest, and to the GNOME
         5637 Foundation for sponsoring my travel and accomodation.  And to
         5638 &lt;a href="https://www.centricular.com/"&gt;Centricular&lt;/a&gt; for taking us all to dinner!&lt;/p&gt;
         5639 &lt;p&gt;Special thanks to Jordan Petridis for being on top of everything
         5640 build-wise all the time.&lt;/p&gt;
         5641 &lt;p&gt;&lt;img alt="Sponsored by the GNOME Foundation" src="https://people.gnome.org/~federico/blog/images/sponsored-by-foundation.png"&gt;&lt;/p&gt;</content><category term="misc"></category><category term="gnome"></category><category term="rust"></category></entry><entry><title>Propagating Errors</title><link href="https://people.gnome.org/~federico/blog/propagating-errors.html" rel="alternate"></link><published>2018-11-21T13:58:12-06:00</published><updated>2018-11-21T13:58:12-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-11-21:/~federico/blog/propagating-errors.html</id><summary type="html">&lt;p&gt;Lately, I have been converting the code in librsvg that handles XML
         5642 from C to Rust.  For many technical reasons, the library still uses
         5643 libxml2, GNOME's historic XML parsing library, but some of the
         5644 callbacks to handle XML events like &lt;code&gt;start_element&lt;/code&gt;, &lt;code&gt;end_element&lt;/code&gt;,
         5645 &lt;code&gt;characters&lt;/code&gt;, are now implemented in Rust.  This has …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Lately, I have been converting the code in librsvg that handles XML
         5646 from C to Rust.  For many technical reasons, the library still uses
         5647 libxml2, GNOME's historic XML parsing library, but some of the
         5648 callbacks to handle XML events like &lt;code&gt;start_element&lt;/code&gt;, &lt;code&gt;end_element&lt;/code&gt;,
         5649 &lt;code&gt;characters&lt;/code&gt;, are now implemented in Rust.  This has meant that I'm
         5650 running into all the cases where the original C code in librsvg failed
         5651 to handle errors properly; Rust really makes it obvious when that
         5652 happens.&lt;/p&gt;
         5653 &lt;p&gt;In this post I want to talk a bit about propagating errors.  You call
         5654 a function, it returns an error, and then what?&lt;/p&gt;
         5655 &lt;h2&gt;What can fail?&lt;/h2&gt;
         5656 &lt;p&gt;It turns out that this question is highly context-dependent.  Let's
         5657 say a program is starting up and tries to read a configuration file.
         5658 What could go wrong?&lt;/p&gt;
         5659 &lt;ul&gt;
         5660 &lt;li&gt;
         5661 &lt;p&gt;The file doesn't exist.  Maybe it is the very first time the program
         5662   is run, and so there &lt;em&gt;isn't&lt;/em&gt; a configuration file at all?  Can the
         5663   program provide a default configuration in this case?  Or does it
         5664   absolutely need a pre-written configuration file to be somewhere?&lt;/p&gt;
         5665 &lt;/li&gt;
         5666 &lt;li&gt;
         5667 &lt;p&gt;The file can't be parsed.  Should the program warn the user and
         5668   exit, or should it revert to a default configuration (should it
         5669   overwrite the file with valid, default values)?  &lt;em&gt;Can&lt;/em&gt;
         5670   the program warn the user, or is it a user-less program that at best
         5671   can just shout into the void of a server-side log file?&lt;/p&gt;
         5672 &lt;/li&gt;
         5673 &lt;li&gt;
         5674 &lt;p&gt;The file can be parsed, but the values are invalid.  Same questions
         5675   as the case above.&lt;/p&gt;
         5676 &lt;/li&gt;
         5677 &lt;li&gt;
         5678 &lt;p&gt;Etcetera.&lt;/p&gt;
         5679 &lt;/li&gt;
         5680 &lt;/ul&gt;
         5681 &lt;p&gt;At each stage, the code will probably see very low-level errors ("file
         5682 not found", "I/O error", "parsing failed", "value is out of range").
         5683 What the code decides to do, or what it is able to do at any
         5684 particular stage, depends both on the semantics you want from the
         5685 program, and from the code structure itself.&lt;/p&gt;
         5686 &lt;h2&gt;Structuring the problem&lt;/h2&gt;
         5687 &lt;p&gt;This is an easy, but very coarse way of handling things:&lt;/p&gt;
         5688 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;gboolean&lt;/span&gt;
         5689 &lt;span class="nf"&gt;read_configuration&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config_file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         5690 &lt;span class="p"&gt;{&lt;/span&gt;
         5691     &lt;span class="cm"&gt;/* open the file */&lt;/span&gt;
         5692 
         5693     &lt;span class="cm"&gt;/* parse it */&lt;/span&gt;
         5694 
         5695     &lt;span class="cm"&gt;/* set global variables to the configuration values */&lt;/span&gt;
         5696 
         5697     &lt;span class="cm"&gt;/* return true if success, or false if failure */&lt;/span&gt;
         5698 &lt;span class="p"&gt;}&lt;/span&gt;
         5699 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5700 
         5701 &lt;p&gt;What is bad about this?  Let's see:&lt;/p&gt;
         5702 &lt;ul&gt;
         5703 &lt;li&gt;
         5704 &lt;p&gt;The calling code just gets a success/failure condition.  In the case
         5705   of failure, it doesn't get to know why things failed.&lt;/p&gt;
         5706 &lt;/li&gt;
         5707 &lt;li&gt;
         5708 &lt;p&gt;If the function sets global variables with configuration values as
         5709   they get read... and something goes wrong and the function returns
         5710   an error... the caller ends up possibly in an inconsistent state,
         5711   with a set of configuration variables that are only halfway-set.&lt;/p&gt;
         5712 &lt;/li&gt;
         5713 &lt;li&gt;
         5714 &lt;p&gt;If the function finds parse errors, well, do you really want to call
         5715   UI code from inside it?  The caller might be a better place to make
         5716   that decision.&lt;/p&gt;
         5717 &lt;/li&gt;
         5718 &lt;/ul&gt;
         5719 &lt;h2&gt;A slightly better structure&lt;/h2&gt;
         5720 &lt;p&gt;Let's add an enumeration to indicate the possible errors, and a
         5721 structure of configuration values.&lt;/p&gt;
         5722 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;ConfigError&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5723 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ConfigFileDoesntExist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5724 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// config file has bad syntax or something&lt;/span&gt;
         5725 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// config file has an invalid value&lt;/span&gt;
         5726 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5727 
         5728 &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;ConfigValues&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5729 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// a bunch of fields here with the program&amp;#39;s configuration&lt;/span&gt;
         5730 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5731 
         5732 &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;read_configuration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ConfigValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ConfigError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5733 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// open the file, or return Err(ConfigError::ConfigFileDoesntExist)&lt;/span&gt;
         5734 
         5735 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// parse the file; or return Err(ConfigError::ParseError)&lt;/span&gt;
         5736 
         5737 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// validate the values, or return Err(ConfigError::ValueError)&lt;/span&gt;
         5738 
         5739 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// if everything succeeds, return Ok(ConfigValues)&lt;/span&gt;
         5740 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5741 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5742 
         5743 &lt;p&gt;This is better, in that the caller decides what to do with the
         5744 validated &lt;code&gt;ConfigValues&lt;/code&gt;:  maybe it can just copy them to the
         5745 program's global variables for configuration.&lt;/p&gt;
         5746 &lt;p&gt;However, this scheme doesn't give the caller all the information it
         5747 would like to present a really good error message.  For example, the
         5748 caller will get to know if there is a parse error, but it doesn't know
         5749 specifically what failed during parsing.  Similarly, it will just get
         5750 to know if there was an invalid value, but not which one.&lt;/p&gt;
         5751 &lt;h2&gt;Ah, so the problem is fractal&lt;/h2&gt;
         5752 &lt;p&gt;We could have new structs to represent the little errors, and then
         5753 make them part of the original error enum:&lt;/p&gt;
         5754 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;ParseError&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5755 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;: &lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5756 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt;: &lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5757 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;error_reason&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5758 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5759 
         5760 &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5761 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;config_key&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5762 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;error_reason&lt;/span&gt;: &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5763 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5764 
         5765 &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;ConfigError&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5766 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ConfigFileDoesntExist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5767 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// we put those structs in here&lt;/span&gt;
         5768 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5769 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5770 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5771 
         5772 &lt;p&gt;Is that enough?  It depends.&lt;/p&gt;
         5773 &lt;p&gt;The &lt;code&gt;ParseError&lt;/code&gt; and &lt;code&gt;ValueError&lt;/code&gt; structs have individual
         5774 &lt;code&gt;error_reason&lt;/code&gt; fields, which are strings.  Presumably, one could have
         5775 a &lt;code&gt;ParseError&lt;/code&gt; with &lt;code&gt;error_reason = "unexpected token"&lt;/code&gt;, or a
         5776 &lt;code&gt;ValueError&lt;/code&gt; with &lt;code&gt;error_reason = "cannot be a negative number"&lt;/code&gt;.&lt;/p&gt;
         5777 &lt;p&gt;One problem with this is that if the low-level errors come with error
         5778 messages in English, then the caller has to know how to localize them
         5779 to the user's language.  Also, if they don't have a machine-readable
         5780 error code, then the calling code may not have enough information to
         5781 decide what do do with the error.&lt;/p&gt;
         5782 &lt;p&gt;Let's say we had a &lt;code&gt;ParseErrorKind&lt;/code&gt; enum with variants like
         5783 &lt;code&gt;UnexpectedToken&lt;/code&gt;, &lt;code&gt;EndOfFile&lt;/code&gt;, etc.  This is fine; it lets the
         5784 calling code know the &lt;em&gt;reason&lt;/em&gt; for the error.  Also, there can be a
         5785 &lt;code&gt;gimme_localized_error_message()&lt;/code&gt; method for that particular type of
         5786 error.&lt;/p&gt;
         5787 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;ParseErrorKind&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5788 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;UnexpectedToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5789 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;EndOfFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5790 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;MissingComma&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5791 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ... etc.&lt;/span&gt;
         5792 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5793 
         5794 &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;ParseError&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5795 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;: &lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5796 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt;: &lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5797 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;: &lt;span class="nc"&gt;ParseErrorKind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5798 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5799 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5800 
         5801 &lt;p&gt;How can we expand this?  Maybe the &lt;code&gt;ParseErrorKind::UnexpectedToken&lt;/code&gt;
         5802 variant wants to contain data that indicates &lt;em&gt;which&lt;/em&gt; token it got that
         5803 was wrong, so it would be &lt;code&gt;UnexpectedToken(String)&lt;/code&gt; or something
         5804 similar.&lt;/p&gt;
         5805 &lt;p&gt;But is &lt;em&gt;that&lt;/em&gt; useful to the calling code?  For our example program,
         5806 which is reading a configuration file... it probably only needs to
         5807 know if it could parse the file, but maybe it doesn't really need any
         5808 additional details on the reason for the parse error, other than
         5809 having something useful to present to the user.  Whether it is
         5810 appropriate to burden the user with the actual details... does the app
         5811 expect to make it the user's job to fix broken configuration files?
         5812 Yes for a web server, where the user is a sysadmin; probably not for a
         5813 random end-user graphical app, where people shouldn't need to write
         5814 configuration files by hand in the first place (should &lt;em&gt;those&lt;/em&gt; have a
         5815 "Details" section in the error message window?  I don't know!).&lt;/p&gt;
         5816 &lt;p&gt;Maybe the low-level parsing/validation code &lt;em&gt;can&lt;/em&gt; emit those detailed
         5817 errors.  But how can we propagate them to something more useful to the
         5818 upper layers of the code?&lt;/p&gt;
         5819 &lt;h2&gt;Translation and propagation&lt;/h2&gt;
         5820 &lt;p&gt;Maybe our original &lt;code&gt;read_configuration()&lt;/code&gt; function can translate the
         5821 low-level errors into high-level ones:&lt;/p&gt;
         5822 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;read_configuration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ConfigValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ConfigError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5823 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// open file&lt;/span&gt;
         5824 
         5825 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cannot_open_file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5826 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ConfigError&lt;/span&gt;::&lt;span class="n"&gt;ConfigFileDoesntExist&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5827 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5828 
         5829 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read_the_file&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;map_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;oops&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;maybe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;we&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;need&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;an&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IoError&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;case&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;too&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5830 
         5831 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// parse file&lt;/span&gt;
         5832 
         5833 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;map_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;higher&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5834 
         5835 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// validate&lt;/span&gt;
         5836 
         5837 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;validated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;map_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;higher&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5838 
         5839 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// yay!&lt;/span&gt;
         5840 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ConfigValues&lt;/span&gt;::&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5841 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         5842 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5843 
         5844 &lt;p&gt;Etcetera.  It is up to each part of the code to decide what do do with
         5845 lower-level errors.  Can it recover from them?  Should it fail the
         5846 whole operation and return a higher-level error?  Should it warn the
         5847 user right there?&lt;/p&gt;
         5848 &lt;h2&gt;Language facilities&lt;/h2&gt;
         5849 &lt;p&gt;C makes it really easy to ignore errors, and pretty hard to present
         5850 detailed errors like the above.  One could mimic what Rust is actually
         5851 doing with a collection of &lt;code&gt;union&lt;/code&gt; and &lt;code&gt;struct&lt;/code&gt; and &lt;code&gt;enum&lt;/code&gt;, but this
         5852 gets very awkward very fast.&lt;/p&gt;
         5853 &lt;p&gt;Rust provides these facilities at the language level, and the idioms
         5854 around &lt;code&gt;Result&lt;/code&gt; and error handling are very nice to use.  There are
         5855 even crates like &lt;a href="https://boats.gitlab.io/failure/intro.html"&gt;&lt;code&gt;failure&lt;/code&gt;&lt;/a&gt; that go a long way towards
         5856 automating error translation, propagation, and conversion to strings
         5857 for presenting to users.&lt;/p&gt;
         5858 &lt;h2&gt;Infinite details&lt;/h2&gt;
         5859 &lt;p&gt;I've been recommending &lt;a href="http://joeduffyblog.com/2016/02/07/the-error-model/"&gt;The Error Model&lt;/a&gt; to anyone who
         5860 comes into a discussion of error handling in programming languages.
         5861 It's a long, detailed, but very enlightening read on recoverable
         5862 vs. unrecoverable errors, simple error codes vs. exceptions
         5863 vs. monadic results, the performance/reliability/ease of use of each
         5864 model... Definitely worth a read.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category></entry><entry><title>My gdk-pixbuf braindump</title><link href="https://people.gnome.org/~federico/blog/my-gdk-pixbuf-braindump.html" rel="alternate"></link><published>2018-09-05T21:35:41-05:00</published><updated>2018-09-06T07:49:38-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-09-05:/~federico/blog/my-gdk-pixbuf-braindump.html</id><summary type="html">&lt;p&gt;I want to write a braindump on the stuff that I remember from
         5865 gdk-pixbuf's history.  There is some talk about replacing it with
         5866 something newer; hopefully this history will show some things that
         5867 worked, some that didn't, and why.&lt;/p&gt;
         5868 &lt;h2&gt;The beginnings&lt;/h2&gt;
         5869 &lt;p&gt;Gdk-pixbuf started as a replacement for Imlib, the image …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I want to write a braindump on the stuff that I remember from
         5870 gdk-pixbuf's history.  There is some talk about replacing it with
         5871 something newer; hopefully this history will show some things that
         5872 worked, some that didn't, and why.&lt;/p&gt;
         5873 &lt;h2&gt;The beginnings&lt;/h2&gt;
         5874 &lt;p&gt;Gdk-pixbuf started as a replacement for Imlib, the image loading and
         5875 rendering library that GNOME used in its earliest versions.  Imlib
         5876 came from the Enlightenment project; it provided an easy API around
         5877 the idiosyncratic libungif, libjpeg, libpng, etc., and it maintained
         5878 decoded images in memory with a uniform representation.  Imlib also
         5879 worked as an image cache for the Enlightenment window manager, which
         5880 made memory management very inconvenient for GNOME.&lt;/p&gt;
         5881 &lt;p&gt;Imlib worked well as a "just load me an image" library.  It showed
         5882 that a small, uniform API to load various image formats into a common
         5883 representation was desirable.  And in those days, hiding all the
         5884 complexities of displaying images in X was very important indeed.&lt;/p&gt;
         5885 &lt;h2&gt;The initial API&lt;/h2&gt;
         5886 &lt;p&gt;Gdk-pixbuf replaced Imlib, and added two important features:
         5887 reference counting for image data, and support for an alpha channel.&lt;/p&gt;
         5888 &lt;p&gt;Gdk-pixbuf appeared with support for RGB(A) images.  And although in
         5889 theory it was possible to grow the API to support other
         5890 representations, &lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/gdk-pixbuf/gdk-pixbuf-core.h#L132-144"&gt;&lt;code&gt;GdkColorspace&lt;/code&gt;&lt;/a&gt; never acquired anything other than
         5891 &lt;code&gt;GDK_COLORSPACE_RGB&lt;/code&gt;, and the &lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/gdk-pixbuf/gdk-pixbuf-core.h#L269-271"&gt;&lt;code&gt;bits_per_sample&lt;/code&gt;&lt;/a&gt; argument to some
         5892 functions &lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/gdk-pixbuf/gdk-pixbuf.c#L478"&gt;only ever supported being &lt;code&gt;8&lt;/code&gt;&lt;/a&gt;.  The presence or absence of an alpha
         5893 channel was done with a &lt;code&gt;gboolean&lt;/code&gt; argument in conjunction with that
         5894 single &lt;code&gt;GDK_COLORSPACE_RGB&lt;/code&gt; value; we didn't have something like
         5895 &lt;a href="https://gitlab.freedesktop.org/cairo/cairo/blob/201791a5/src/cairo.h#L385-424"&gt;&lt;code&gt;cairo_format_t&lt;/code&gt;&lt;/a&gt; which actually specifies the pixel format in single
         5896 enum values.&lt;/p&gt;
         5897 &lt;p&gt;While all the code in gdk-pixbuf carefully checks that those
         5898 conditions are met — RGBA at 8 bits per channel —, some applications
         5899 inadvertently assume that &lt;em&gt;that&lt;/em&gt; is the only possible case, and would get
         5900 into trouble really fast if gdk-pixbuf ever started returning pixbufs
         5901 with different color spaces or depths.&lt;/p&gt;
         5902 &lt;p&gt;One can still see the battle between bilevel-alpha
         5903 vs. continuous-alpha in &lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/gdk-pixbuf/gdk-pixbuf-core.h#L108-130"&gt;this enum&lt;/a&gt;:&lt;/p&gt;
         5904 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt;
         5905 &lt;span class="p"&gt;{&lt;/span&gt;
         5906         &lt;span class="n"&gt;GDK_PIXBUF_ALPHA_BILEVEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         5907         &lt;span class="n"&gt;GDK_PIXBUF_ALPHA_FULL&lt;/span&gt;
         5908 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;GdkPixbufAlphaMode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         5909 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         5910 
         5911 &lt;p&gt;Fortunately, only the "&lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib.h#L62-70"&gt;render this pixbuf with alpha to an Xlib
         5912 drawable&lt;/a&gt;"  functions take values of this type:  before the Xrender
         5913 days, it was a Big Deal to draw an image with alpha to an X window,
         5914 and applications often opted to use a bitmask instead, even if they
         5915 had jagged edges as a result.&lt;/p&gt;
         5916 &lt;h2&gt;Pixel formats&lt;/h2&gt;
         5917 &lt;p&gt;The only pixel format that ever got implemented was unpremultiplied
         5918 RGBA on all platforms.  Back then I didn't understand &lt;a href="https://keithp.com/~keithp/porterduff/p253-porter.pdf"&gt;premultiplied
         5919 alpha&lt;/a&gt;!  Also, the GIMP followed that scheme, and copying
         5920 it seemed like the easiest thing.&lt;/p&gt;
         5921 &lt;p&gt;After gdk-pixbuf, libart also copied that pixel format, I think.&lt;/p&gt;
         5922 &lt;p&gt;But later we got Cairo, Pixman, and all the Xrender stack.  These
         5923 prefer premultiplied ARGB.  Moreover, Cairo prefers it if each pixel
         5924 is actually a 32-bit value, with the ARGB values inside it in
         5925 platform-endian order.  So if you look at a memory dump, a Cairo pixel
         5926 looks like BGRA on a little-endian box, while it looks like ARGB on a
         5927 big-endian box.&lt;/p&gt;
         5928 &lt;p&gt;Every time we paint a &lt;code&gt;GdkPixbuf&lt;/code&gt; to a &lt;code&gt;cairo_t&lt;/code&gt;, there is a
         5929 conversion from unpremultiplied RGBA to premultiplied, platform-endian
         5930 ARGB.  I talked a bit about this in &lt;a href="https://people.gnome.org/~federico/blog/reducing-image-copies.html"&gt;Reducing the number of image
         5931 copies in GNOME&lt;/a&gt;.&lt;/p&gt;
         5932 &lt;h2&gt;The loading API&lt;/h2&gt;
         5933 &lt;p&gt;The public loading API in gdk-pixbuf, and its relationship to loader
         5934 plug-ins, evolved in interesting ways.&lt;/p&gt;
         5935 &lt;p&gt;At first the public API and loaders only implemented &lt;code&gt;load_from_file&lt;/code&gt;:
         5936 you gave the library a &lt;code&gt;FILE *&lt;/code&gt; and it gave you back a &lt;code&gt;GdkPixbuf&lt;/code&gt;.
         5937 Back then we didn't have a robust MIME sniffing framework in the form
         5938 of a library, so gdk-pixbuf got its own.  This lives in the
         5939 mostly-obsolete &lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/gdk-pixbuf/gdk-pixbuf-io.h#L329-359"&gt;&lt;code&gt;GdkPixbufFormat&lt;/code&gt;&lt;/a&gt; machinery; it
         5940 even has its own &lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/gdk-pixbuf/gdk-pixbuf-io.c#L125-175"&gt;little language&lt;/a&gt; for sniffing file headers!
         5941 Nowadays we do most MIME sniffing with GIO.&lt;/p&gt;
         5942 &lt;p&gt;After the intial &lt;code&gt;load_from_file&lt;/code&gt; API... I think we got progressive
         5943 loading first, and animation support aftewards.&lt;/p&gt;
         5944 &lt;h2&gt;Progressive loading&lt;/h2&gt;
         5945 &lt;p&gt;This where the calling program feeds chunks of bytes to the library,
         5946 and at the end a fully-formed &lt;code&gt;GdkPixbuf&lt;/code&gt; comes out, instead of having
         5947 a single "read a whole file" operation.&lt;/p&gt;
         5948 &lt;p&gt;We conflated this with a way to get &lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/gdk-pixbuf/gdk-pixbuf-loader.h#L72-77"&gt;updates on how the image area gets
         5949 modified&lt;/a&gt; as the data gets parsed.  I think we wanted to support the
         5950 case of a web browser, which downloads images slowly over the network,
         5951 and gradually displays them as they are downloaded.  In 1998, images
         5952 downloading slowly over the network was a real concern!&lt;/p&gt;
         5953 &lt;p&gt;It took a lot of very careful work to convert the image loaders, which
         5954 parsed a whole file at a time, into loaders that could maintain some
         5955 state between each time that they got handed an extra bit of buffer.&lt;/p&gt;
         5956 &lt;p&gt;It also sounded easy to implement the progressive updating API by
         5957 simply emitting a signal that said, "this rectangular area got updated
         5958 from the last read".  It could handle the case of reading whole
         5959 scanlines, or a few pixels, or even area-based updates for progressive
         5960 JPEGs and PNGs.&lt;/p&gt;
         5961 &lt;p&gt;The internal API for the image format loaders still keeps a
         5962 distinction between the "load a whole file" API and the "load an image
         5963 in chunks".  Not all loaders got redone to simply just use the second
         5964 one:  &lt;code&gt;io-jpeg.c&lt;/code&gt; &lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/gdk-pixbuf/io-jpeg.c#L554-722"&gt;still implements loading whole files&lt;/a&gt; by calling the
         5965 corresponding libjpeg functions.  I think it could remove that code
         5966 and use the progressive loading functions instead.&lt;/p&gt;
         5967 &lt;h2&gt;Animations&lt;/h2&gt;
         5968 &lt;p&gt;Animations:  we followed the GIF model for animations, in which each
         5969 frame overlays the previous one, and there's a delay set between each
         5970 frame.  This is not a video file; it's a hacky flipbook.&lt;/p&gt;
         5971 &lt;p&gt;However, animations presented the problem that the whole gdk-pixbuf
         5972 API was meant for static images, and now we needed to support
         5973 multi-frame images as well.&lt;/p&gt;
         5974 &lt;p&gt;We defined the "correct" way to use the gdk-pixbuf library as to
         5975 actually try to load an animation, and then see if it is a
         5976 single-frame image, in which case you can just get a &lt;code&gt;GdkPixbuf&lt;/code&gt; for
         5977 the only frame and use it.&lt;/p&gt;
         5978 &lt;p&gt;Or, if you got an animation, that would be a &lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/gdk-pixbuf/gdk-pixbuf-animation.h"&gt;&lt;code&gt;GdkPixbufAnimation&lt;/code&gt;&lt;/a&gt;
         5979 object, from which you could ask for an iterator to get each frame as
         5980 a separate &lt;code&gt;GdkPixbuf&lt;/code&gt;.&lt;/p&gt;
         5981 &lt;p&gt;However, the progressive updating API never got extended to really
         5982 support animations.  So, we have awkward functions like
         5983 &lt;code&gt;gdk_pixbuf_animation_iter_on_currently_loading_frame()&lt;/code&gt; instead.&lt;/p&gt;
         5984 &lt;h2&gt;Necessary accretion&lt;/h2&gt;
         5985 &lt;p&gt;Gdk-pixbuf got support for saving just a few formats:  JPEG, PNG,
         5986 TIFF, ICO, and some of the formats that are implemented with the
         5987 Windows-native loaders.&lt;/p&gt;
         5988 &lt;p&gt;Over time gdk-pixbuf got support for preserving some metadata-ish
         5989 chunks from formats that provide it:  DPI, color profiles, image
         5990 comments, hotspots for cursors/icons...&lt;/p&gt;
         5991 &lt;p&gt;While an image is being loaded with the progressive loaders, there is
         5992 a clunky way to specify that one doesn't want the actual size of the
         5993 image, but another size instead.  The loader can handle that situation
         5994 itself, hopefully if an image format actually embeds different sizes
         5995 in it.  Or if not, the main loading code will rescale the full loaded
         5996 image into the size specified by the application.&lt;/p&gt;
         5997 &lt;h2&gt;Historical cruft&lt;/h2&gt;
         5998 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/gdk-pixbuf/gdk-pixdata.h"&gt;&lt;code&gt;GdkPixdata&lt;/code&gt;&lt;/a&gt; - a way to embed binary image data in executables, with a
         5999 funky encoding.  Nowadays it's just easier to directly store a PNG or
         6000 JPEG or whatever in a &lt;code&gt;GResource&lt;/code&gt;.&lt;/p&gt;
         6001 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/contrib/gdk-pixbuf-xlib/"&gt;&lt;code&gt;contrib/gdk-pixbuf-xlib&lt;/code&gt;&lt;/a&gt; - to deal with old-style X drawables.
         6002 Hopefully mostly unused now, but there's a good number of mostly old,
         6003 third-party software that still uses gdk-pixbuf as an image loader and
         6004 renderer to X drawables.&lt;/p&gt;
         6005 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/gdk-pixbuf/gdk-pixbuf-transform.h"&gt;&lt;code&gt;gdk-pixbuf-transform.h&lt;/code&gt;&lt;/a&gt; - Gdk-pixbuf had some very high-quality
         6006 scaling functions, which the original versions of EOG used for the
         6007 core of the image viewer.  Nowadays Cairo is the preferred way of
         6008 doing this, since it not only does scaling, but general affine
         6009 transformations as well.  Did you know that
         6010 &lt;code&gt;gdk_pixbuf_composite_color&lt;/code&gt; takes 17 arguments, and it can composite
         6011 an image with alpha on top of a checkerboard?  Yes, that used to be
         6012 the core of EOG.&lt;/p&gt;
         6013 &lt;h2&gt;Debatable historical cruft&lt;/h2&gt;
         6014 &lt;p&gt;&lt;code&gt;gdk_pixbuf_get_pixels()&lt;/code&gt;.  This lets the program look into the actual
         6015 pixels of a loaded pixbuf, and modify them.  Gdk-pixbuf just did not
         6016 have a concept of immutability.&lt;/p&gt;
         6017 &lt;p&gt;Back in GNOME 1.x / 2.x, when it was fashionable to put icons beside
         6018 menu items, or in toolbar buttons, applications would load their icon
         6019 images, and modify them in various ways before setting them onto the
         6020 corresponding widgets.  Some things they did:  load a colorful icon,
         6021 desaturate it for "insensitive" command buttons or menu items, or
         6022 simulate desaturation by compositing a 1x1-pixel checkerboard on the
         6023 icon image.  Or lighten the icon and set it as the "prelight" one onto
         6024 widgets.&lt;/p&gt;
         6025 &lt;p&gt;The concept of "decode an image and just give me the pixels" is of
         6026 course useful.  Image viewers, image processing programs, and all
         6027 those, of course need this functionality.&lt;/p&gt;
         6028 &lt;p&gt;However, these days GTK would prefer to have a way to decode an image,
         6029 and ship it as fast as possible ot the GPU, without intermediaries.
         6030 There is all sorts of awkward machinery in the GTK widgets that
         6031 can consume either an icon from an icon theme, or a user-supplied
         6032 image, or one of the various schemes for providing icons that GTK has
         6033 acquired over the years.&lt;/p&gt;
         6034 &lt;p&gt;It is interesting to note that &lt;code&gt;gdk_pixbuf_get_pixels()&lt;/code&gt; was available
         6035 pretty much since the beginning, but it was only until much later that
         6036 we got &lt;code&gt;gdk_pixbuf_get_pixels_with_length()&lt;/code&gt;, the "give me the &lt;code&gt;guchar
         6037 *&lt;/code&gt; buffer and also its length" function, so that calling code has a
         6038 chance of actually checking for buffer overruns.  (... and it is one
         6039 of the broken "give me a length" functions that returns a &lt;code&gt;guint&lt;/code&gt;
         6040 rather than a &lt;code&gt;gsize&lt;/code&gt;.  There is a better
         6041 &lt;code&gt;gdk_pixbuf_get_byte_length()&lt;/code&gt; which actually returns a &lt;code&gt;gsize&lt;/code&gt;,
         6042 though.)&lt;/p&gt;
         6043 &lt;h2&gt;Problems with mutable pixbufs&lt;/h2&gt;
         6044 &lt;p&gt;The main problem is that as things are right now, we have no
         6045 flexibility in changing the internal representation of image data to
         6046 make it better for current idioms:  GPU-specific pixel formats may not
         6047 be unpremultiplied RGBA data.&lt;/p&gt;
         6048 &lt;p&gt;We have no API to say, "this pixbuf has been modified", akin to
         6049 &lt;code&gt;cairo_surface_mark_dirty()&lt;/code&gt;:  once an application calls
         6050 &lt;code&gt;gdk_pixbuf_get_pixels()&lt;/code&gt;, gdk-pixbuf or GTK have to assume that the
         6051 data &lt;em&gt;will&lt;/em&gt; be changed and they have to re-run the pipeline to send
         6052 the image to the GPU (format conversions?  caching?  creating a
         6053 texture?).&lt;/p&gt;
         6054 &lt;p&gt;Also, ever since the beginnings of the gdk-pixbuf API, we had a way to
         6055 create pixbufs from arbitrary user-supplied RGBA buffers: the
         6056 &lt;code&gt;gdk_pixbuf_new_from_data&lt;/code&gt; functions.  One problem with this scheme is
         6057 that memory management of the buffer is up to the calling application,
         6058 so the resulting pixbuf isn't free to handle those resources as it
         6059 pleases.&lt;/p&gt;
         6060 &lt;p&gt;A relatively recent addition is &lt;code&gt;gdk_pixbuf_new_from_bytes()&lt;/code&gt;, which
         6061 takes a &lt;code&gt;GBytes&lt;/code&gt; buffer instead of a random &lt;code&gt;guchar *&lt;/code&gt;.  When a pixbuf
         6062 is created that way, it is &lt;em&gt;assumed&lt;/em&gt; to be immutable, since a &lt;code&gt;GBytes&lt;/code&gt;
         6063 is basically a shared reference into a byte buffer, and it's just
         6064 easier to think of it as immutable.  (Nothing in C actually enforces
         6065 immutability, but the API indicates that convention.)&lt;/p&gt;
         6066 &lt;p&gt;Internally, &lt;code&gt;GdkPixbuf&lt;/code&gt; actually prefers to be created from a
         6067 &lt;code&gt;GBytes&lt;/code&gt;.  It will &lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/blob/36939ecb/gdk-pixbuf/gdk-pixbuf.c#L719-743"&gt;downgrade itself&lt;/a&gt; to a &lt;code&gt;guchar *&lt;/code&gt; buffer if
         6068 something calls the old &lt;code&gt;gdk_pixbuf_get_pixels()&lt;/code&gt;; in the best case,
         6069 that will just take ownership of the internal buffer from the
         6070 &lt;code&gt;GBytes&lt;/code&gt; (if the &lt;code&gt;GBytes&lt;/code&gt; has a single reference count); in the worst
         6071 case, it will copy the buffer from the &lt;code&gt;GBytes&lt;/code&gt; and retain ownership
         6072 of that copy.  In either case, when the pixbuf downgrades itself to
         6073 pixels, it is assumed that the calling application will modify the
         6074 pixel data.&lt;/p&gt;
         6075 &lt;h2&gt;What would immutable pixbufs look like?&lt;/h2&gt;
         6076 &lt;p&gt;I mentioned this a bit in "&lt;a href="https://people.gnome.org/~federico/blog/reducing-image-copies.html"&gt;Reducing Copies&lt;/a&gt;".  The
         6077 loaders in gdk-pixbuf would create immutable pixbufs, with an internal
         6078 representation that is friendly to GPUs.  In the proposed scheme, that
         6079 internal representation would be a Cairo image surface; it can be
         6080 something else if GTK/GDK eventually prefer a different way of
         6081 shipping image data into the toolkit.&lt;/p&gt;
         6082 &lt;p&gt;Those pixbufs would be immutable.  In true C fashion we can call it
         6083 undefined behavior to change the pixel data (say, an app could request
         6084 &lt;code&gt;gimme_the_cairo_surface&lt;/code&gt; and tweak it, but that would not be
         6085 supported).&lt;/p&gt;
         6086 &lt;p&gt;I think we could also have a "just give me the pixels" API, and a
         6087 "create a pixbuf from these pixels" one, but those would be one-time
         6088 conversions at the edge of the API.  Internally, the pixel data that
         6089 actually lives inside a &lt;code&gt;GdkPixbuf&lt;/code&gt; would remain immutable, in some
         6090 preferred representation, which is not necessarily what the
         6091 application sees.&lt;/p&gt;
         6092 &lt;h2&gt;What worked well&lt;/h2&gt;
         6093 &lt;p&gt;A small API to load multiple image formats, and paint the images
         6094 easily to the screen, while handling most of the X awkwardness
         6095 semi-automatically, was very useful!&lt;/p&gt;
         6096 &lt;p&gt;A way to get and modify pixel data: applications clearly like doing
         6097 this.  We can formalize it as an application-side thing only, and keep
         6098 the internal representation immutable and in a format that can evolve
         6099 according to the needs of the internal API.&lt;/p&gt;
         6100 &lt;p&gt;Pluggable loaders, up to a point.  Gdk-pixbuf doesn't support all the
         6101 image formats in the world out of the box, but it is relatively easy
         6102 for third-parties to provide loaders that, once installed, are
         6103 automatically usable for all applications.&lt;/p&gt;
         6104 &lt;h2&gt;What didn't work well&lt;/h2&gt;
         6105 &lt;p&gt;Having effectively two pixel formats supported, and nothing else:
         6106 gdk-pixbuf does packed RGB and unpremultiplied RGBA, and that's it.
         6107 This isn't completely terrible:  applications which really want to
         6108 know about indexed or grayscale images, or high bit-depth ones, are
         6109 &lt;em&gt;probably&lt;/em&gt; specialized enough that they can afford to have their own
         6110 custom loaders with all the functionality they need.&lt;/p&gt;
         6111 &lt;p&gt;Pluggable loaders, up to a point.  While it is relatively easy to
         6112 create third-party loaders, installation is awkward from a system's
         6113 perspective: one has to run the script to regenerate the loader cache,
         6114 there are more shared libraries running around, and the loaders are
         6115 not sandboxed by default.&lt;/p&gt;
         6116 &lt;p&gt;I'm not sure if it's worthwhile to let any application read "any"
         6117 image format if gdk-pixbuf supports it.  If your word processor lets
         6118 you paste an image into the document... do you want it to use
         6119 gdk-pixbuf's limited view of things and include a high bit-depth image
         6120 with its probably inadequate conversions?  Or would you rather do some
         6121 processing by hand to ensure that the image looks as good as it can,
         6122 in the format that your word processor actually supports?  I don't
         6123 know.&lt;/p&gt;
         6124 &lt;p&gt;The API for animations is very awkward.  We don't even support
         6125 APNG... but honestly I don't recall actually seeing one of those in
         6126 the wild.&lt;/p&gt;
         6127 &lt;p&gt;The progressive loading API is awkward.  The "feed some bytes into the
         6128 loader" part is mostly okay; the "notify me about changes to the pixel
         6129 data" is questionable nowadays.  Web browsers don't use it; they
         6130 implement their own loaders.  Even EOG doesn't use it.&lt;/p&gt;
         6131 &lt;p&gt;I think most code that actually connects to &lt;code&gt;GdkPixbufLoader&lt;/code&gt;'s
         6132 signals only uses the &lt;code&gt;size-prepared&lt;/code&gt; signal — the one that gets
         6133 emitted soon after reading the image headers, when the loader gets to
         6134 know the dimensions of the image.  Apps sometimes use this to say,
         6135 "this image is W*H pixels in size", but don't actually decode the
         6136 rest of the image.&lt;/p&gt;
         6137 &lt;p&gt;The gdk-pixbuf model of static images, or GIF animations, doesn't work
         6138 well for multi-page TIFFs.  I'm not sure if this is actualy a problem.
         6139 Again, applications with actual needs for multi-page TIFFs are
         6140 probably specialized enough that they will want a full-featured TIFF
         6141 loader of their own.&lt;/p&gt;
         6142 &lt;h2&gt;Awkward architectures&lt;/h2&gt;
         6143 &lt;h3&gt;Thumbnailers&lt;/h3&gt;
         6144 &lt;p&gt;The thumbnailing system has slowly been moving towards a model where
         6145 we actually have thumbnailers specific to each file format, instead of
         6146 just assuming that we can dump any image into a gdk-pixbuf loader.&lt;/p&gt;
         6147 &lt;p&gt;If we take this all the way, we would be able to remove some weird
         6148 code in, for example, the JPEG pixbuf loader.  Right now it supports
         6149 loading images at a size that the calling code requests, not only at
         6150 the "natural" size of the JPEG.  The thumbnailer can say, "I want to
         6151 load this JPEG at 128x128 pixels" or whatever, and &lt;em&gt;in theory&lt;/em&gt; the
         6152 JPEG loader will do the minimal amount of work required to do that.
         6153 It's not 100% clear to me if this is actually working as intended, or
         6154 if we downscale the whole image anyway.&lt;/p&gt;
         6155 &lt;p&gt;We had a distinction between in-process and out-of-process
         6156 thumbnailers, and it had to do with the way pixbuf loaders are used;
         6157 I'm not sure if they are all out-of-process and sandboxed now.&lt;/p&gt;
         6158 &lt;h3&gt;Non-raster data&lt;/h3&gt;
         6159 &lt;p&gt;There is a gdk-pixbuf loader for SVG images which uses librsvg
         6160 internally, but only in a very basic way:  it simply loads the SVG at
         6161 its preferred size.  Librsvg jumps through some hoops to compute a
         6162 "preferred size" for SVGs, as not all of them actually indicate one.
         6163 The SVG model would rather have the renderer say that the SVG is to be
         6164 inserted into a rectangle of certain width/height, and
         6165 scaled/positioned inside the rectangle according to some other
         6166 parameters (i.e. like one would put it inside an HTML document, with a
         6167 &lt;code&gt;preserveAspectRatio&lt;/code&gt; attribute and all that).  GNOME applications
         6168 historically operated with a different model, one of "load me an
         6169 image, I'll scale it to whatever size, and paint it".&lt;/p&gt;
         6170 &lt;p&gt;This gdk-pixbuf loader for SVG files gets used for the SVG
         6171 thumbnailer, or more accurately, the "throw random images into a
         6172 gdk-pixbuf loader" thumbnailer.  It may be better/cleaner to have a
         6173 specific thumbnailer for SVGs instead.&lt;/p&gt;
         6174 &lt;p&gt;Even EOG, our by-default image viewer, doesn't use the gdk-pixbuf
         6175 loader for SVGs: it actually special-cases them and uses librsvg
         6176 directly, to be able to load an SVG once and re-render it at different
         6177 sizes if one changes the zoom factor, for example.&lt;/p&gt;
         6178 &lt;p&gt;GTK reads its SVG icons... without using librsvg... by assuming that
         6179 librsvg installed its gdk-pixbuf loader, so it loads them as any
         6180 normal raster image.  This kind of dirty, but I can't quite pinpoint
         6181 why.  I'm sure it would be convenient for icon themes to ship a single
         6182 SVG with tons of icons, and some metadata on their &lt;code&gt;id&lt;/code&gt;s, so that GTK
         6183 could pick them out of the SVG file with &lt;code&gt;rsvg_render_cairo_sub()&lt;/code&gt; or
         6184 something.  Right now icon theme authors are responsible for splitting
         6185 out those huge SVGs into many little ones, one for each icon, and I
         6186 don't think that's their favorite thing in the world to do :)&lt;/p&gt;
         6187 &lt;h3&gt;Exotic raster data&lt;/h3&gt;
         6188 &lt;p&gt;High bit-depth images... would you expect EOG to be able to load them?
         6189 Certainly; maybe not with all the fancy conversions from a real RAW
         6190 photo editor.  But maybe this can be done as EOG-specific plugins,
         6191 rather than as low in the platform as the gdk-pixbuf loaders?&lt;/p&gt;
         6192 &lt;p&gt;(Same thing for thumbnailing high bit-depth images:  the loading code
         6193 should just provide its own thumbnailer program for those.)&lt;/p&gt;
         6194 &lt;h3&gt;Non-image metadata&lt;/h3&gt;
         6195 &lt;p&gt;The &lt;code&gt;gdk_pixbuf_set_option&lt;/code&gt; / &lt;code&gt;gdk_pixbuf_get_option&lt;/code&gt; family of
         6196 functions is so that pixbuf loaders can set key/value pairs of strings
         6197 onto a pixbuf.  Loaders use this for &lt;code&gt;comment&lt;/code&gt; blocks, or ICC profiles
         6198 for color calibration, or DPI information for images that have it, or
         6199 EXIF data from photos.  It is up to applications to actually use this
         6200 information.&lt;/p&gt;
         6201 &lt;p&gt;It's a bit uncomfortable that gdk-pixbuf makes no promises about the
         6202 kind of raster data it gives to the caller:  right now it is raw
         6203 RGB(A) data that is not gamma-corrected nor in any particular color
         6204 space.  It is up to the caller to see if the pixbuf has an ICC profile
         6205 attached to it as an &lt;code&gt;option&lt;/code&gt;.  Effectively, this means that
         6206 applications don't know if they are getting SRGB, or linear RGB, or
         6207 what... unless they specifically care to look.&lt;/p&gt;
         6208 &lt;p&gt;The gdk-pixbuf API could probably make promises:  if you call &lt;em&gt;this
         6209 function&lt;/em&gt; you will get SRGB data; if you call &lt;em&gt;this other function&lt;/em&gt;,
         6210 you'll get the raw RGBA data and we'll tell you its
         6211 colorspace/gamma/etc.&lt;/p&gt;
         6212 &lt;p&gt;The various &lt;code&gt;set_option&lt;/code&gt; / &lt;code&gt;get_option&lt;/code&gt; pairs are also usable by the
         6213 gdk-pixbuf &lt;em&gt;saving&lt;/em&gt; code (up to now we have just talked about
         6214 loaders).  I don't know enough about how applications use the saving
         6215 code in gdk-pixbuf... the thumbnailers use it to save PNGs or JPEGs,
         6216 but other apps?  No idea.&lt;/p&gt;
         6217 &lt;h2&gt;What I would like to see&lt;/h2&gt;
         6218 &lt;p&gt;&lt;strong&gt;Immutable pixbufs in a useful format.&lt;/strong&gt; I've started &lt;a href="https://gitlab.gnome.org/GNOME/gdk-pixbuf/merge_requests/6"&gt;work on
         6219 this&lt;/a&gt; in a merge request; the internal code is now ready
         6220 to take in different internal representations of pixel data.  My goal
         6221 is to make Cairo image surfaces the preferred, immutable, internal
         6222 representation.  This would give us a
         6223 &lt;code&gt;gdk_pixbuf_get_cairo_surface()&lt;/code&gt;, which pretty much everything that
         6224 needs one reimplements by hand.&lt;/p&gt;
         6225 &lt;p&gt;&lt;strong&gt;Find places that assume mutable pixbufs.&lt;/strong&gt; To gradually deprecate
         6226 mutable pixbufs, I think we would need to audit applications and
         6227 libraries to find places that cause &lt;code&gt;GdkPixbuf&lt;/code&gt; structures to degrade
         6228 into mutable ones:  basically, find callers of
         6229 &lt;code&gt;gdk_pixbuf_get_pixels()&lt;/code&gt; and related functions, see what they do, and
         6230 reimplement them differently.  Maybe they don't need to tint icons by
         6231 hand anymore?  Maybe they &lt;em&gt;don't need icons&lt;/em&gt; anymore, given our
         6232 changing UI paradigms?  Maybe they are using gdk-pixbuf as an image
         6233 loader only?&lt;/p&gt;
         6234 &lt;p&gt;&lt;strong&gt;Reconsider the loading-updates API.&lt;/strong&gt;  Do we need the
         6235 &lt;code&gt;GdkPixbufLoader::area-updated&lt;/code&gt; signal at all?  Does anything break
         6236 if we just... not emit it, or just emit it once at the end of the
         6237 loading process?  (Caveat: keeping it unchanged more or less means
         6238 that "immutable pixbufs" as loaded by gdk-pixbuf actually mutate while
         6239 being loaded, and this mutation is exposed to applications.)&lt;/p&gt;
         6240 &lt;p&gt;&lt;strong&gt;Sandboxed loaders.&lt;/strong&gt;  While these days gdk-pixbuf loaders prefer the
         6241 progressive feed-it-bytes API, sandboxed loaders would maybe prefer a
         6242 read-a-whole-file approach.  I don't know enough about memfd or how
         6243 sandboxes pass data around to know how either would work.&lt;/p&gt;
         6244 &lt;p&gt;&lt;strong&gt;Move loaders to Rust.&lt;/strong&gt;  Yes, really.  Loaders are
         6245 security-sensitive, and while we &lt;em&gt;do&lt;/em&gt; need to sandbox them, it would
         6246 certainly be better to do them in a memory-safe language.  There are
         6247 already pure Rust-based image loaders: &lt;a href="https://crates.io/crates/jpeg-decoder"&gt;JPEG&lt;/a&gt;,
         6248 &lt;a href="https://crates.io/crates/png"&gt;PNG&lt;/a&gt;, &lt;a href="https://github.com/PistonDevelopers/image-tiff"&gt;TIFF&lt;/a&gt;, &lt;a href="https://github.com/PistonDevelopers/image-gif"&gt;GIF&lt;/a&gt;, &lt;a href="https://github.com/PistonDevelopers/image/tree/master/src/ico"&gt;ICO&lt;/a&gt;.
         6249 I have no idea how featureful they are.  We can certainly try them
         6250 with gdk-pixbuf's own suite of test images.  We can modify them to add
         6251 hooks for things like a &lt;code&gt;size-prepared&lt;/code&gt; notification, if they don't
         6252 already have a way to read "just the image headers".&lt;/p&gt;
         6253 &lt;p&gt;Rust makes it very easy to plug in &lt;a href="https://crates.io/crates/criterion"&gt;micro-benchmarks&lt;/a&gt;,
         6254 &lt;a href="https://crates.io/crates/afl"&gt;fuzz testing&lt;/a&gt;, and other modern amenities.  These would be
         6255 perfect for improving the loaders.&lt;/p&gt;
         6256 &lt;p&gt;I started &lt;a href="https://gitlab.gnome.org/federico/gdk-pixbuf/tree/rust-loader/gdk-pixbuf/rust"&gt;sketching a Rust backend for gdk-pixbuf
         6257 loaders&lt;/a&gt; some months ago, but there's nothing useful
         6258 yet.  One mismatch between gdk-pixbuf's model for loaders, and the
         6259 existing Rust codecs, is that Rust codecs generally take something
         6260 that implements the &lt;code&gt;Read&lt;/code&gt; trait: a blocking API to read bytes from
         6261 abstract sources; it's a pull API.  The gdk-pixbuf model is a push
         6262 API: the calling code creates a loader object, and then pushes bytes
         6263 into it.  The gdk-pixbuf convenience functions that take a
         6264 &lt;code&gt;GInputStream&lt;/code&gt; basically do this:&lt;/p&gt;
         6265 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gdk_pixbuf_loader_new&lt;/span&gt; &lt;span class="p"&gt;(...);&lt;/span&gt;
         6266 
         6267 &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;more_bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         6268     &lt;span class="n"&gt;n_read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g_input_stream_read&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;
         6269     &lt;span class="n"&gt;gdk_pixbuf_loader_write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;
         6270 &lt;span class="p"&gt;}&lt;/span&gt;
         6271 
         6272 &lt;span class="n"&gt;gdk_pixbuf_loader_close&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         6273 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6274 
         6275 &lt;p&gt;However, this cannot be flipped around easily.  We could probably use
         6276 a second thread (easy, safe to do in Rust) to make the reader/decoder
         6277 thread block while the main thread pushes bytes into it.&lt;/p&gt;
         6278 &lt;p&gt;Also, I don't know how the Rust bindings for GIO present things like
         6279 &lt;code&gt;GInputStream&lt;/code&gt; and friends, with our nice async cancellables and all
         6280 that.&lt;/p&gt;
         6281 &lt;p&gt;&lt;strong&gt;Deprecate animations?&lt;/strong&gt;  Move that code to EOG, just so one can look
         6282 at memes in it?  Do any "real apps" actually use GIF animations for
         6283 their UI?&lt;/p&gt;
         6284 &lt;p&gt;&lt;strong&gt;Formalize promises around returned color profiles, gamma, etc.&lt;/strong&gt;  As
         6285 mentioned above: have an "easy API" that returns SRGB, and a "raw API"
         6286 that returns the ARGB data from the image, plus info on its ICC
         6287 profile, gamma, or any other info needed to turn this into a
         6288 "good enough to be universal" representation.  (I &lt;em&gt;think&lt;/em&gt; all the
         6289 Apple APIs that pass colors around do so with an ICC profile attached,
         6290 which seems... pretty much necessary for correctness.)&lt;/p&gt;
         6291 &lt;p&gt;&lt;strong&gt;Remove the internal MIME-sniffing machinery.&lt;/strong&gt;  And just use GIO's.&lt;/p&gt;
         6292 &lt;p&gt;&lt;strong&gt;Deprecate the crufty/old APIs in gdk-pixbuf.&lt;/strong&gt;
         6293 Scaling/transformation, compositing, &lt;code&gt;GdkPixdata&lt;/code&gt;,
         6294 &lt;code&gt;gdk-pixbuf-csource&lt;/code&gt;, all those.  Pixel crunching can be done by
         6295 Cairo; the others are better done with &lt;code&gt;GResource&lt;/code&gt; these days.&lt;/p&gt;
         6296 &lt;p&gt;&lt;strong&gt;Figure out if we want blessed codecs; fix thumbnailers.&lt;/strong&gt; Link those
         6297 loaders statically, unconditionally.  Exotic formats can go in their
         6298 own custom thumbnailers.  Figure out if we want sandboxed loaders for
         6299 everything, or just for user-side images (not ones read from the
         6300 trusted system installation).&lt;/p&gt;
         6301 &lt;p&gt;&lt;strong&gt;Have GTK4 communicate clearly about its drawing model.&lt;/strong&gt; I think we
         6302 are having a disconnect between the GUI chrome, which is CSS/GPU
         6303 friendly, and graphical content generated by applications, which by
         6304 default right now is done via Cairo.  And having Cairo as a to-screen
         6305 and to-printer API is certainly very convenient!  You Wouldn't Print a
         6306 GUI, but certainly you would print a displayed document.&lt;/p&gt;
         6307 &lt;p&gt;It would also be useful for GTK4 to actually define what its preferred
         6308 image format is if it wants to ship it to the GPU with as little work
         6309 as possible.  Maybe it's a Cairo image surface?  Maybe something else?&lt;/p&gt;
         6310 &lt;h2&gt;Conclusion&lt;/h2&gt;
         6311 &lt;p&gt;We seem to change imaging models every ten years or so.  Xlib, then
         6312 Xrender with Cairo, then GPUs and CSS-based drawing for widgets.
         6313 We've gone from trusted data on your local machine, to potentially malicious data that
         6314 rains from the Internet.  Gdk-pixbuf has spanned all of these periods
         6315 so far, and it is due for a big change.&lt;/p&gt;</content><category term="misc"></category><category term="gnome"></category><category term="gdk-pixbuf"></category></entry><entry><title>Debugging an Rc&lt;T&gt; reference leak in Rust</title><link href="https://people.gnome.org/~federico/blog/debugging-reference-leak-in-rust.html" rel="alternate"></link><published>2018-08-29T16:47:13-05:00</published><updated>2018-08-29T16:47:13-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-08-29:/~federico/blog/debugging-reference-leak-in-rust.html</id><summary type="html">&lt;p&gt;The &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/325"&gt;bug&lt;/a&gt; that caused two brown-paper-bag released in librsvg —
         6316 because it was leaking all the SVG nodes — has been interesting.&lt;/p&gt;
         6317 &lt;p&gt;&lt;em&gt;Memory leaks in Rust?  Isn't it supposed to prevent that?&lt;/em&gt;&lt;/p&gt;
         6318 &lt;p&gt;Well, yeah, but the leaks were caused by the C side of things, and by
         6319 &lt;code&gt;unsafe&lt;/code&gt; code in Rust, which …&lt;/p&gt;</summary><content type="html">&lt;p&gt;The &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/325"&gt;bug&lt;/a&gt; that caused two brown-paper-bag released in librsvg —
         6320 because it was leaking all the SVG nodes — has been interesting.&lt;/p&gt;
         6321 &lt;p&gt;&lt;em&gt;Memory leaks in Rust?  Isn't it supposed to prevent that?&lt;/em&gt;&lt;/p&gt;
         6322 &lt;p&gt;Well, yeah, but the leaks were caused by the C side of things, and by
         6323 &lt;code&gt;unsafe&lt;/code&gt; code in Rust, which does not prevent leaks.&lt;/p&gt;
         6324 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/federico/librsvg/commit/29af8b19ea103f754c318cfbf8b03c31265f0394"&gt;The first part of the bug&lt;/a&gt; was easy: C code started calling a
         6325 function implemented in Rust, which returns a newly-acquired reference
         6326 to an SVG node.  The old code simply got a pointer to the node,
         6327 without acquiring a reference.  The new code was forgetting to
         6328 &lt;code&gt;rsvg_node_unref()&lt;/code&gt;.  No biggie.&lt;/p&gt;
         6329 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/commit/2d3ddca130d7d023daedf77a6ab58fefec510292"&gt;The second part of the bug&lt;/a&gt; was trickier to find.  The C code
         6330 was apparently calling all the functions to unref nodes as
         6331 appropriate, and even calling the &lt;code&gt;rsvg_tree_free()&lt;/code&gt; function in the
         6332 end; this is the "free the whole SVG tree" function.&lt;/p&gt;
         6333 &lt;p&gt;There are these types:&lt;/p&gt;
         6334 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// We take a pointer to this and expose it as an opaque pointer to C&lt;/span&gt;
         6335 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;RsvgTree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6336 
         6337 &lt;span class="c1"&gt;// This is the real structure we care about&lt;/span&gt;
         6338 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6339 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// This is the Rc that was getting leaked&lt;/span&gt;
         6340 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;: &lt;span class="nc"&gt;Rc&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6341 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6342 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6343 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6344 
         6345 &lt;p&gt;&lt;code&gt;Tree&lt;/code&gt; is the real struct that holds the root of the SVG tree and some
         6346 other data.  Each node is an &lt;code&gt;Rc&amp;lt;Node&amp;gt;&lt;/code&gt;; the root node was getting
         6347 leaked (... and all the children, recursively) because its reference
         6348 count never went down from 1.&lt;/p&gt;
         6349 &lt;p&gt;&lt;code&gt;RsvgTree&lt;/code&gt; is just an empty type.  The code does an unsafe cast of
         6350 &lt;code&gt;*const Tree&lt;/code&gt; as &lt;code&gt;*const RsvgTree&lt;/code&gt; in order to expose a raw pointer to
         6351 the C code.&lt;/p&gt;
         6352 &lt;p&gt;The &lt;code&gt;rsvg_tree_free()&lt;/code&gt; function, callable from C, looked like this:&lt;/p&gt;
         6353 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6354 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;rsvg_tree_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tree&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RsvgTree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6355 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6356 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;::&lt;span class="n"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6357 &lt;span class="w"&gt;                         &lt;/span&gt;&lt;span class="c1"&gt;// ^ this returns a Box&amp;lt;RsvgTree&amp;gt; which is an empty type!&lt;/span&gt;
         6358 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6359 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6360 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6361 
         6362 &lt;p&gt;When we call &lt;code&gt;Box::from_raw()&lt;/code&gt; on a &lt;code&gt;*mut RsvgTree&lt;/code&gt;, it gives us back
         6363 a &lt;code&gt;Box&amp;lt;RsvgTree&amp;gt;&lt;/code&gt;... which is a box of a zero-sized type.  So, the program
         6364 frees zero memory when the box gets dropped.&lt;/p&gt;
         6365 &lt;p&gt;The code was missing this cast:&lt;/p&gt;
         6366 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6367 &lt;span class="w"&gt;                                 &lt;/span&gt;&lt;span class="c1"&gt;// ^ this cast to the actual type inside the Box&lt;/span&gt;
         6368 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;::&lt;span class="n"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6369 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6370 
         6371 &lt;p&gt;So, &lt;code&gt;tree as *mut Tree&lt;/code&gt; gives us a value which will cause
         6372 &lt;code&gt;Box::from_raw()&lt;/code&gt; to return a &lt;code&gt;Box&amp;lt;Tree&amp;gt;&lt;/code&gt;, which is what we intended.
         6373 Dropping the box will drop the &lt;code&gt;Tree&lt;/code&gt;, reduce the last reference count
         6374 on the root node, and free all the nodes recursively.&lt;/p&gt;
         6375 &lt;h2&gt;Monitoring an &lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;/code&gt;'s reference count in gdb&lt;/h2&gt;
         6376 &lt;p&gt;So, how does one set a gdb watchpoint on the reference count?&lt;/p&gt;
         6377 &lt;p&gt;First I set a breakpoint on a function which I knew would get passed
         6378 the &lt;code&gt;Rc&amp;lt;Node&amp;gt;&lt;/code&gt; I care about:&lt;/p&gt;
         6379 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;(gdb) b &amp;lt;rsvg_internals::structure::NodeSvg as rsvg_internals::node::NodeTrait&amp;gt;::set_atts
         6380 Breakpoint 3 at 0x7ffff71f3aaa: file rsvg_internals/src/structure.rs, line 131.
         6381 
         6382 (gdb) c
         6383 Continuing.
         6384 
         6385 Thread 1 &amp;quot;rsvg-convert&amp;quot; hit Breakpoint 3, &amp;lt;rsvg_internals::structure::NodeSvg as rsvg_internals::node::NodeTrait&amp;gt;::set_atts (self=0x646c60, node=0x64c890, pbag=0x64c820) at rsvg_internals/src/structure.rs:131
         6386 
         6387 (gdb) p node
         6388 $5 = (alloc::rc::Rc&amp;lt;rsvg_internals::node::Node&amp;gt; *) 0x64c890
         6389 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6390 
         6391 &lt;p&gt;Okay, &lt;code&gt;node&lt;/code&gt; is a reference to an &lt;code&gt;Rc&amp;lt;Node&amp;gt;&lt;/code&gt;.  What's inside?&lt;/p&gt;
         6392 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;(gdb) p *node
         6393 $6 = {ptr = {pointer = {__0 = 0x625800}}, phantom = {&amp;lt;No data fields&amp;gt;}}
         6394 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6395 
         6396 &lt;p&gt;Why, a &lt;code&gt;pointer&lt;/code&gt; to the actual contents of the &lt;code&gt;Rc&lt;/code&gt;.  Look inside
         6397 again:&lt;/p&gt;
         6398 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;(gdb) p *node.ptr.pointer.__0
         6399 $9 = {strong = {value = {value = 3}}, weak = {value = {value = 1}},  ... and lots of extra crap ...
         6400 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6401 
         6402 &lt;p&gt;Aha!  There are the &lt;code&gt;strong&lt;/code&gt; and &lt;code&gt;weak&lt;/code&gt; reference counts.  So, set a
         6403 watchpoint on the strong reference count:&lt;/p&gt;
         6404 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;(gdb) set $ptr = &amp;amp;node.ptr.pointer.__0.strong.value.value
         6405 (gdb) watch *$ptr
         6406 Hardware watchpoint 4: *$ptr
         6407 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6408 
         6409 &lt;p&gt;Continue running the program until the reference count changes:&lt;/p&gt;
         6410 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;gdb&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
         6411 &lt;span class="nv"&gt;Thread&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;rsvg-convert&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;hit&lt;/span&gt; &lt;span class="nv"&gt;Hardware&lt;/span&gt; &lt;span class="nv"&gt;watchpoint&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;$&lt;span class="nv"&gt;ptr&lt;/span&gt;
         6412 
         6413 &lt;span class="nv"&gt;Old&lt;/span&gt; &lt;span class="nv"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
         6414 &lt;span class="nv"&gt;New&lt;/span&gt; &lt;span class="nv"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
         6415 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6416 
         6417 &lt;p&gt;At this point I can print a stack trace and see if it makes sense,
         6418 check that the refs/unrefs are matched, etc.&lt;/p&gt;
         6419 &lt;p&gt;TL;DR: dig into the &lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;/code&gt; until you find the reference count, and
         6420 watch it.  It's wrapped in several layers of Rust-y types; &lt;code&gt;NonNull&lt;/code&gt;
         6421 pointers, an &lt;code&gt;RcBox&lt;/code&gt; for the actual container of the refcount plus the
         6422 object it's wrapping, and &lt;code&gt;Cell&lt;/code&gt;s for the refcount values.  Just dig
         6423 until you reach the refcount values and they are there.&lt;/p&gt;
         6424 &lt;h2&gt;So, how did I find the missing cast?&lt;/h2&gt;
         6425 &lt;p&gt;Using that gdb recipe, I watched the reference count of the toplevel
         6426 SVG node change until the program exited.  When the program
         6427 terminated, the reference count was 1 — it should have dropped to 0 if
         6428 there was no memory leak.&lt;/p&gt;
         6429 &lt;p&gt;The last place where the toplevel node loses a reference is in
         6430 &lt;code&gt;rsvg_tree_free()&lt;/code&gt;.  I ran the program again and checked if that
         6431 function was being called; it &lt;em&gt;was&lt;/em&gt; being called correctly.  So I knew
         6432 that the problem must lie in that function.  After a little
         6433 head-scratching, I found the missing cast.  Other functions of the
         6434 form &lt;code&gt;rsvg_tree_whatever()&lt;/code&gt; had that cast, but &lt;code&gt;rsvg_tree_free()&lt;/code&gt; was
         6435 missing it.&lt;/p&gt;
         6436 &lt;p&gt;I think Rust now has better facilities to tag structs that are exposed
         6437 as raw pointers to &lt;code&gt;extern&lt;/code&gt; code, to avoid this kind of perilous
         6438 casting.  We'll see.&lt;/p&gt;
         6439 &lt;p&gt;In the meantime, apologies for the buggy releases!&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="gnome"></category><category term="librsvg"></category></entry><entry><title>Logging from Rust in librsvg</title><link href="https://people.gnome.org/~federico/blog/logging-in-librsvg.html" rel="alternate"></link><published>2018-08-03T19:29:43-05:00</published><updated>2018-08-03T19:29:43-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-08-03:/~federico/blog/logging-in-librsvg.html</id><summary type="html">&lt;p&gt;Over in &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/281"&gt;this issue&lt;/a&gt; we are discussing how to add debug logging
         6440 for librsvg.&lt;/p&gt;
         6441 &lt;p&gt;A popular way to add logging to Rust code is to use the &lt;a href="https://crates.io/crates/log"&gt;log&lt;/a&gt; crate.
         6442 This lets you sprinkle simple messages in your code:&lt;/p&gt;
         6443 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;something bad happened: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6444 &lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;a debug message&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6445 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6446 
         6447 &lt;p&gt;However, the &lt;a href="https://crates.io/crates/log"&gt;log …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;Over in &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/281"&gt;this issue&lt;/a&gt; we are discussing how to add debug logging
         6448 for librsvg.&lt;/p&gt;
         6449 &lt;p&gt;A popular way to add logging to Rust code is to use the &lt;a href="https://crates.io/crates/log"&gt;log&lt;/a&gt; crate.
         6450 This lets you sprinkle simple messages in your code:&lt;/p&gt;
         6451 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;something bad happened: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6452 &lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;a debug message&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6453 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6454 
         6455 &lt;p&gt;However, the &lt;a href="https://crates.io/crates/log"&gt;log&lt;/a&gt; create is just a facade, and by default the
         6456 messages do not get emitted anywhere.  The calling code has to set up
         6457 a logger.  Crates like &lt;a href="https://crates.io/crates/env_logger"&gt;env_logger&lt;/a&gt; let one set up a logger, during
         6458 program initialization, that gets configured through an environment
         6459 variable.&lt;/p&gt;
         6460 &lt;p&gt;And this is a problem for librsvg:  we are &lt;em&gt;not&lt;/em&gt; the program's
         6461 initialization!  Librsvg is a library; it doesn't have a &lt;code&gt;main()&lt;/code&gt;
         6462 function.  And since most of the calling code is not Rust, we can't
         6463 assume that they can call code that can initialize the logging
         6464 framework.&lt;/p&gt;
         6465 &lt;h2&gt;Why not use glib's logging stuff?&lt;/h2&gt;
         6466 &lt;p&gt;Currently this is a bit clunky to use from Rust, since glib's
         6467 structured logging functions are not bound yet in &lt;a href="http://gtk-rs.org/docs/glib/"&gt;glib-rs&lt;/a&gt;.  Maybe it
         6468 would be good to bind them and get this over with.&lt;/p&gt;
         6469 &lt;h2&gt;What user experience do we want?&lt;/h2&gt;
         6470 &lt;p&gt;In the past, what has worked well for me to do logging from libraries
         6471 is to allow the user to set an environment variable to control the
         6472 logging, or to drop a log configuration file in their $HOME.  The
         6473 former works well when the user is in control of running the program
         6474 that will print the logs; the latter is useful when the user is not
         6475 directly in control, like for gnome-shell, which gets launched through
         6476 a lot of magic during session startup.&lt;/p&gt;
         6477 &lt;p&gt;For librsvg, it's probably enough to just use an environment
         6478 variable.  Set &lt;code&gt;RSVG_LOG=parse_errors&lt;/code&gt;, run your program, and get
         6479 useful output.  &lt;a href="https://makezine.com/2016/06/10/push-button-receive-bacon/"&gt;Push button, receive bacon&lt;/a&gt;.&lt;/p&gt;
         6480 &lt;h2&gt;Other options in Rust?&lt;/h2&gt;
         6481 &lt;p&gt;There is a &lt;a href="https://crates.io/crates/slog"&gt;slog&lt;/a&gt; crate which looks promising.  Instead of using
         6482 context-less macros which depend on a single global logger, it
         6483 provides logging macros to which you pass a logger object.&lt;/p&gt;
         6484 &lt;p&gt;For librsvg, this means that the basic &lt;code&gt;RsvgHandle&lt;/code&gt; could create its
         6485 own logger, based on an environment variable or whatever, and pass it
         6486 around to all its child functions for when they need to log something.&lt;/p&gt;
         6487 &lt;p&gt;Slog supports structured logging, and seems to have some fancy output
         6488 modes.  We'll see.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category><category term="gnome"></category></entry><entry><title>Three big things happening in librsvg</title><link href="https://people.gnome.org/~federico/blog/three-big-things-happening-in-librsvg.html" rel="alternate"></link><published>2018-05-21T19:21:08-05:00</published><updated>2018-05-21T19:21:08-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-05-21:/~federico/blog/three-big-things-happening-in-librsvg.html</id><summary type="html">&lt;p&gt;I am incredibly happy because of three &lt;strong&gt;big&lt;/strong&gt; things that are going
         6489 on in librsvg right now:&lt;/p&gt;
         6490 &lt;ol&gt;
         6491 &lt;li&gt;
         6492 &lt;p&gt;Paolo Borelli finished porting all the CSS properties to Rust.
         6493    What was once a gigantic &lt;code&gt;RsvgState&lt;/code&gt; struct in C is totally gone,
         6494    along with all the janky C code to parse individual properties …&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;</summary><content type="html">&lt;p&gt;I am incredibly happy because of three &lt;strong&gt;big&lt;/strong&gt; things that are going
         6495 on in librsvg right now:&lt;/p&gt;
         6496 &lt;ol&gt;
         6497 &lt;li&gt;
         6498 &lt;p&gt;Paolo Borelli finished porting all the CSS properties to Rust.
         6499    What was once a gigantic &lt;code&gt;RsvgState&lt;/code&gt; struct in C is totally gone,
         6500    along with all the janky C code to parse individual properties.
         6501    The process of porting &lt;code&gt;RsvgState&lt;/code&gt; to Rust has been going on &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/merge_requests/39"&gt;since
         6502    about two months ago&lt;/a&gt;, and has involved many multi-commit
         6503    merge requests and refactorings.  This is a tremendous amount of
         6504    really good work!  The result is all in Rust now in a &lt;code&gt;State&lt;/code&gt;
         6505    struct, which is opaque from C's viewpoint.  The only places in C
         6506    that still require accessors to the &lt;code&gt;State&lt;/code&gt; are in the filter
         6507    effects code.  Which brings me to...&lt;/p&gt;
         6508 &lt;/li&gt;
         6509 &lt;li&gt;
         6510 &lt;p&gt;Ivan Molodetskikh, my Summer of Code student, submitted his &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/merge_requests/64"&gt;first
         6511    merge request&lt;/a&gt; and it's merged to master now.  This ports
         6512    the bookkeeping infrastructure for SVG filters to Rust, and also
         6513    the &lt;code&gt;feOffset&lt;/code&gt; filter is ported now.  Right now the code doesn't do
         6514    anything fancy to iterate over the pixels of Cairo image surfaces;
         6515    that will come later.  I am very happy that filters, which were a
         6516    huge barrier, are now starting to get chipped away into nicer code.&lt;/p&gt;
         6517 &lt;/li&gt;
         6518 &lt;li&gt;
         6519 &lt;p&gt;I have started to move librsvg's old representation of CSS
         6520    properties into something that can really represent properties that
         6521    are not specified, or explicitly set to &lt;code&gt;inherit&lt;/code&gt; from an SVG
         6522    element's parent, or set to a normal value.  Librsvg never had a
         6523    representation of property values that actually matched the SVG/CSS
         6524    specs; it just knew whether a property was specified or not for an
         6525    element.  This worked fine for properties which the spec mandates
         6526    that they should inherit automatically, but those that &lt;em&gt;don't&lt;/em&gt;,
         6527    were handled through special hacks.  The new code makes this a lot
         6528    cleaner.  It should also make it easier to copy Servo's idioms for
         6529    property inheritance.&lt;/p&gt;
         6530 &lt;/li&gt;
         6531 &lt;/ol&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category><category term="gnome"></category></entry><entry><title>Reducing the number of image copies in GNOME</title><link href="https://people.gnome.org/~federico/blog/reducing-image-copies.html" rel="alternate"></link><published>2018-05-14T07:45:11-05:00</published><updated>2018-05-14T07:45:11-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-05-14:/~federico/blog/reducing-image-copies.html</id><summary type="html">&lt;p&gt;&lt;a href="https://magcius.github.io/xplain/article/"&gt;Our graphics stack&lt;/a&gt; that deals with images has evolved a lot
         6532 over the years.&lt;/p&gt;
         6533 &lt;h1&gt;In ye olden days&lt;/h1&gt;
         6534 &lt;p&gt;In the context of GIMP/GNOME, the only thing that knew how to draw RGB
         6535 images to X11 windows (doing palette mapping for 256-color graphics
         6536 cards and dithering if necessary) was the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://magcius.github.io/xplain/article/"&gt;Our graphics stack&lt;/a&gt; that deals with images has evolved a lot
         6537 over the years.&lt;/p&gt;
         6538 &lt;h1&gt;In ye olden days&lt;/h1&gt;
         6539 &lt;p&gt;In the context of GIMP/GNOME, the only thing that knew how to draw RGB
         6540 images to X11 windows (doing palette mapping for 256-color graphics
         6541 cards and dithering if necessary) was the GIMP.  Later, when GTK+ was
         6542 written, it exported a &lt;code&gt;GtkPreview&lt;/code&gt; widget, which could take an RGB
         6543 image buffer supplied by the application and render it to an X window
         6544 — this was what GIMP plug-ins could use in their user interface to
         6545 show, well, previews of what they were about to do with the user's
         6546 images.  Later we got some obscure magic in a &lt;code&gt;GdkColorContext&lt;/code&gt;
         6547 object, which helped allocate X11 colors for the X drawing primitives.
         6548 In turn, &lt;code&gt;GdkColorContext&lt;/code&gt; came from the port that Miguel and I did of
         6549 XmHTML's color context object (and for those that remember, XmHTML
         6550 became the first version of GtkHtml; later it was rewritten as a port
         6551 of KDE's HTML widget).  Thankfully all that stuff is gone now; we can
         6552 now assume that video cards are 24-bit RGB or better everywhere, and
         6553 there is no need to worry about limited color palettes and color
         6554 allocation.&lt;/p&gt;
         6555 &lt;p&gt;Later, we started using the Imlib library, from the Enlightenment
         6556 project, as an easy API to load images — the APIs from libungif,
         6557 libjpeg, libpng, etc. were not something one really wanted to use
         6558 directly — and also to keep images in memory with a uniform
         6559 representation.  Unfortunately, Imlib's memory management was
         6560 peculiar, as it was tied to Enlightenment's model for caching and
         6561 rendering loaded/scaled images.&lt;/p&gt;
         6562 &lt;p&gt;A bunch of people worked to write GdkPixbuf:  it kept Imlib's concepts
         6563 of a unified representation for image data, and an easy API to load
         6564 various image formats.  It added support for an alpha channel (we only
         6565 had 1-bit masks before), and it put memory management in the hands of
         6566 the calling application, in the form of reference counting.  GdkPixbuf
         6567 obtained some high-quality scaling functions, mainly for use by Eye Of
         6568 Gnome (our image viewer) and by applications that just needed scaling
         6569 instead of arbitrary transformations.&lt;/p&gt;
         6570 &lt;p&gt;Later, we got libart, the first library in GNOME to do antialiased
         6571 vector rendering and affine transformations.  Libart was more or less
         6572 compatible with GdkPixbuf:  they both had the same internal
         6573 representation for pixel data, but one had to pass the
         6574 pixels/width/height/rowstride around by hand.&lt;/p&gt;
         6575 &lt;h1&gt;Mea culpa&lt;/h1&gt;
         6576 &lt;p&gt;Back then I didn't understand &lt;a href="https://keithp.com/~keithp/porterduff/p253-porter.pdf"&gt;premultiplied alpha&lt;/a&gt;,
         6577 which is now ubiquitous.  The GIMP made the decision to use
         6578 non-premultiplied alpha when it introduced layers with transparency,
         6579 probably to "avoid losing data" from transparent pixels.  GdkPixbuf
         6580 follows the same scheme.&lt;/p&gt;
         6581 &lt;p&gt;(Now that the GIMP uses GEGL for its internal representation of
         6582 images... I have no idea what it does with respect to alpha.)&lt;/p&gt;
         6583 &lt;h1&gt;Cairo and afterwards&lt;/h1&gt;
         6584 &lt;p&gt;Some time after the libart days, we got Cairo and pixman.  Cairo had a
         6585 different representation of images than GdkPixbuf's, and it supported
         6586 more pixel formats and color models.&lt;/p&gt;
         6587 &lt;p&gt;GTK2 got patched to use Cairo in the toplevel API.  We still had a
         6588 dichotomy between Cairo's image surfaces, which are ARGB premultiplied
         6589 data in memory, and GdkPixbufs, which are RGBA non-premultiplied.
         6590 There are utilities in GTK+ to do these translations, but they are
         6591 inconvenient:  every time a program loads an image with GdkPixbuf's
         6592 easy API, a translation has to happen from non-premul RGBA to premul
         6593 ARGB.&lt;/p&gt;
         6594 &lt;p&gt;Having two formats means that we inevitably do translations back and
         6595 forth of practically the same data.  For example, when one embeds a
         6596 JPEG inside an SVG, librsvg will read that JPEG using GdkPixbuf,
         6597 translate it to Cairo's representation, composite it with Cairo onto
         6598 the final result, and finally translate the whole thing back to a
         6599 GdkPixbuf... if someone uses librsvg's legacy APIs to output pixbufs
         6600 instead of rendering directly to a Cairo surface.&lt;/p&gt;
         6601 &lt;p&gt;Who uses that legacy API?  GTK+, of course!  GTK+ loads scalable SVG
         6602 icons with GdkPixbuf's loader API, which dynamically links librsvg at
         6603 runtime:  in effect, GTK+ doesn't use librsvg directly.  And the SVG
         6604 pixbuf loader uses the "gimme a pixbuf" API in librsvg.&lt;/p&gt;
         6605 &lt;h1&gt;GPUs&lt;/h1&gt;
         6606 &lt;p&gt;Then, we got GPUs everywhere.  Each GPU has its own preferred pixel
         6607 format.  Image data has to be copied to the GPU at some point.
         6608 Cairo's ARGB needs to be translated to the GPU's preferred format and
         6609 alignment.&lt;/p&gt;
         6610 &lt;h1&gt;Summary so far&lt;/h1&gt;
         6611 &lt;ul&gt;
         6612 &lt;li&gt;
         6613 &lt;p&gt;Libraries that load images from standard formats have different
         6614   output formats.  Generally they can be coaxed into spitting ARGB or
         6615   RGBA, but we don't expect them to support any random representation
         6616   that a GPU may want.&lt;/p&gt;
         6617 &lt;/li&gt;
         6618 &lt;li&gt;
         6619 &lt;p&gt;GdkPixbuf uses non-premultiplied RGBA data, always in that order.&lt;/p&gt;
         6620 &lt;/li&gt;
         6621 &lt;li&gt;
         6622 &lt;p&gt;Cairo uses premultiplied ARGB in platform-endian 32-bit chunks:  if
         6623   each pixel is 0xaarrggbb, then the bytes are shuffled around
         6624   depending on whether the platform is little-endian or big-endian.&lt;/p&gt;
         6625 &lt;/li&gt;
         6626 &lt;li&gt;
         6627 &lt;p&gt;Cairo internally uses a subset of the formats supported by pixman.&lt;/p&gt;
         6628 &lt;/li&gt;
         6629 &lt;li&gt;
         6630 &lt;p&gt;GPUs use whatever they damn well please.&lt;/p&gt;
         6631 &lt;/li&gt;
         6632 &lt;li&gt;
         6633 &lt;p&gt;Hilarity ensues.&lt;/p&gt;
         6634 &lt;/li&gt;
         6635 &lt;/ul&gt;
         6636 &lt;h1&gt;What would we like to do?&lt;/h1&gt;
         6637 &lt;p&gt;We would like to reduce the number of translations between image
         6638 formats along the loading-processing-display pipeline.  Here is a
         6639 plan:&lt;/p&gt;
         6640 &lt;ul&gt;
         6641 &lt;li&gt;
         6642 &lt;p&gt;Make sure Cairo/pixman support the image formats that GPUs generally
         6643   prefer.  Have them do the necessary conversions if the rest of the
         6644   program passes an unsupported format.  Ensure that a Cairo image
         6645   surface can be created with the GPU's preferred format.&lt;/p&gt;
         6646 &lt;/li&gt;
         6647 &lt;li&gt;
         6648 &lt;p&gt;Make GdkPixbuf just be a wrapper around a Cairo image surface.
         6649   &lt;code&gt;GdkPixbuf&lt;/code&gt; is already an opaque structure, and it already knows how
         6650   to copy pixel data in case the calling code requests it, or wants to
         6651   turn a pixbuf from immutable to mutable.&lt;/p&gt;
         6652 &lt;/li&gt;
         6653 &lt;li&gt;
         6654 &lt;p&gt;Provide GdkPixbuf APIs that deal with Cairo image surfaces.  For
         6655   example, deprecate &lt;code&gt;gdk_pixbuf_new()&lt;/code&gt; and
         6656   &lt;code&gt;gdk_pixbuf_new_from_data()&lt;/code&gt;, in favor of a new
         6657   &lt;code&gt;gdk_pixbuf_new_from_cairo_image_surface()&lt;/code&gt;.  Instead of
         6658   &lt;code&gt;gdk_pixbuf_get_pixels()&lt;/code&gt; and related functions, have
         6659   &lt;code&gt;gdk_pixbuf_get_cairo_image_surface()&lt;/code&gt;.  Mark the "give me the pixel
         6660   data" functions as highly discouraged, and only for use really by
         6661   applications that want to use GdkPixbuf as an image loader and
         6662   little else.&lt;/p&gt;
         6663 &lt;/li&gt;
         6664 &lt;li&gt;
         6665 &lt;p&gt;Remove calls in GTK+ that cause image conversions; make them use
         6666   Cairo image surfaces directly, from GdkTexture up.&lt;/p&gt;
         6667 &lt;/li&gt;
         6668 &lt;li&gt;
         6669 &lt;p&gt;Audit applications to remove calls that cause image conversions.
         6670   Generally, look for where they use GdkPixbuf's deprecated APIs and
         6671   update them.&lt;/p&gt;
         6672 &lt;/li&gt;
         6673 &lt;/ul&gt;
         6674 &lt;h1&gt;Is this really a performance problem?&lt;/h1&gt;
         6675 &lt;p&gt;This is in the "&lt;a href="https://people.gnome.org/~federico/docs/2005-GNOME-Summit/html/img13.html"&gt;excess work&lt;/a&gt;" category of performance
         6676 issues.  All those conversions are not really slow (they don't make up
         6677 for the biggest part of profiles), but they are nevertheless things
         6678 that we could avoid doing.  We may get some speedups, but it's
         6679 probably more interesting to look at things like power consumption.&lt;/p&gt;
         6680 &lt;p&gt;Right now I'm seeing this as a cool, minor optimization, but more as
         6681 &lt;strong&gt;a way to gradually modernize our image API&lt;/strong&gt;.&lt;/p&gt;
         6682 &lt;p&gt;We seem to change imaging models every N years (X11 -&amp;gt; libart
         6683 -&amp;gt; Cairo -&amp;gt; render trees in GPUs -&amp;gt; ???).  It is very hard to change
         6684 applications to use different APIs.  In the meantime, we can provide a
         6685 more linear path for image data, instead of doing unnecessary
         6686 conversions everywhere.&lt;/p&gt;
         6687 &lt;h1&gt;Code&lt;/h1&gt;
         6688 &lt;p&gt;I have a &lt;a href="https://gitlab.gnome.org/federico/gdk-pixbuf/tree/use-cairo-surface-internally"&gt;&lt;code&gt;use-cairo-surface-internally&lt;/code&gt; branch in
         6689 gdk-pixbuf&lt;/a&gt;,
         6690 which I'll be working on this week.  Meanwhile, you may be interested
         6691 in the ongoing &lt;a href="https://wiki.gnome.org/Hackfests/Performance2018"&gt;Performance Hackfest in Cambridge&lt;/a&gt;!&lt;/p&gt;</content><category term="misc"></category><category term="performance"></category><category term="gdk-pixbuf"></category><category term="gnome"></category></entry><entry><title>Madrid GNOME+Rust Hackfest, part 3 (conclusion)</title><link href="https://people.gnome.org/~federico/blog/madrid-gnome-rust-3.html" rel="alternate"></link><published>2018-04-23T15:04:32-05:00</published><updated>2018-04-23T15:04:32-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-04-23:/~federico/blog/madrid-gnome-rust-3.html</id><summary type="html">&lt;p&gt;The last code I wrote during the hackfest was the start of code
         6692 generation for GObject interfaces.  This is so that you can do&lt;/p&gt;
         6693 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6694 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6695 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kr"&gt;virtual&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;frob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6696 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6697 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6698 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6699 
         6700 &lt;p&gt;and it will generate the appropriate &lt;code&gt;FooIface&lt;/code&gt; like one would expect
         6701 with the C versions of interfaces.&lt;/p&gt;
         6702 &lt;p&gt;It turns …&lt;/p&gt;</summary><content type="html">&lt;p&gt;The last code I wrote during the hackfest was the start of code
         6703 generation for GObject interfaces.  This is so that you can do&lt;/p&gt;
         6704 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6705 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6706 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kr"&gt;virtual&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;frob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6707 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6708 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6709 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6710 
         6711 &lt;p&gt;and it will generate the appropriate &lt;code&gt;FooIface&lt;/code&gt; like one would expect
         6712 with the C versions of interfaces.&lt;/p&gt;
         6713 &lt;p&gt;It turns out that this can share a lot of code from the existing code
         6714 generator for classes:  both classes and interfaces are "just virtual
         6715 method tables", plus signals and properties, and classes can actually
         6716 have per-instance fields and such.  I started refactoring the code
         6717 generator to allow this.&lt;/p&gt;
         6718 &lt;p&gt;I also took a second look at how to present good error messages when
         6719 the &lt;code&gt;syn&lt;/code&gt; crate encounters a parse error.  I need to sit down at home
         6720 and experiment with this carefully.&lt;/p&gt;
         6721 &lt;h2&gt;Back home&lt;/h2&gt;
         6722 &lt;p&gt;I'm back home now, jetlagged but very happy that gnome-class is in a much
         6723 more advanced a state than it was before the hackfest.  I'm &lt;strong&gt;very
         6724 thankful&lt;/strong&gt; that practically everyone worked on it!&lt;/p&gt;
         6725 &lt;p&gt;Also, &lt;strong&gt;thanks&lt;/strong&gt; to Alberto and Natalia for hosting me at their
         6726 apartment and showing me around Madrid, all while wrangling their
         6727 adorable baby Mario.  We had a lovely time on Saturday, and ate
         6728 excellent food downtown.&lt;/p&gt;
         6729 &lt;p&gt;&lt;img alt="Sponsored by the GNOME Foundation" src="https://people.gnome.org/~federico/blog/images/sponsored-badge-shadow.png"&gt;&lt;/p&gt;
         6730 &lt;p&gt;&lt;img alt="Hosted by OpenShine" src="https://www.openshine.com/wp-content/uploads/2016/03/openshine.png"&gt;&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="gnome"></category><category term="hackfests"></category></entry><entry><title>Madrid GNOME+Rust Hackfest, part 2</title><link href="https://people.gnome.org/~federico/blog/madrid-gnome-rust-2.html" rel="alternate"></link><published>2018-04-20T08:59:23+02:00</published><updated>2018-04-20T08:59:23+02:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-04-20:/~federico/blog/madrid-gnome-rust-2.html</id><summary type="html">&lt;p&gt;Hacking on &lt;a href="https://gitlab.gnome.org/federico/gnome-class"&gt;gnome-class&lt;/a&gt; continues apace!&lt;/p&gt;
         6731 &lt;p&gt;Philippe &lt;a href="https://gitlab.gnome.org/federico/gnome-class/merge_requests/8"&gt;updated our dependencies&lt;/a&gt;.&lt;/p&gt;
         6732 &lt;p&gt;Alberto made the syntax for per-instance &lt;a href="https://gitlab.gnome.org/federico/gnome-class/merge_requests/10"&gt;private structs&lt;/a&gt;
         6733 more ergonomic, and then made that code &lt;a href="https://gitlab.gnome.org/federico/gnome-class/merge_requests/12"&gt;nice and compact&lt;/a&gt;.&lt;/p&gt;
         6734 &lt;p&gt;Martin improved our &lt;a href="https://gitlab.gnome.org/federico/gnome-class/merge_requests/11"&gt;conversion&lt;/a&gt; from &lt;code&gt;CamelCase&lt;/code&gt; to
         6735 &lt;code&gt;snake_case&lt;/code&gt; for code generation.&lt;/p&gt;
         6736 &lt;p&gt;Daniel added initial support for &lt;a href="https://gitlab.gnome.org/federico/gnome-class/merge_requests/9"&gt;GObject properties&lt;/a&gt;.
         6737 This is not finished yet …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Hacking on &lt;a href="https://gitlab.gnome.org/federico/gnome-class"&gt;gnome-class&lt;/a&gt; continues apace!&lt;/p&gt;
         6738 &lt;p&gt;Philippe &lt;a href="https://gitlab.gnome.org/federico/gnome-class/merge_requests/8"&gt;updated our dependencies&lt;/a&gt;.&lt;/p&gt;
         6739 &lt;p&gt;Alberto made the syntax for per-instance &lt;a href="https://gitlab.gnome.org/federico/gnome-class/merge_requests/10"&gt;private structs&lt;/a&gt;
         6740 more ergonomic, and then made that code &lt;a href="https://gitlab.gnome.org/federico/gnome-class/merge_requests/12"&gt;nice and compact&lt;/a&gt;.&lt;/p&gt;
         6741 &lt;p&gt;Martin improved our &lt;a href="https://gitlab.gnome.org/federico/gnome-class/merge_requests/11"&gt;conversion&lt;/a&gt; from &lt;code&gt;CamelCase&lt;/code&gt; to
         6742 &lt;code&gt;snake_case&lt;/code&gt; for code generation.&lt;/p&gt;
         6743 &lt;p&gt;Daniel added initial support for &lt;a href="https://gitlab.gnome.org/federico/gnome-class/merge_requests/9"&gt;GObject properties&lt;/a&gt;.
         6744 This is not finished yet, but the initial parser and code generation
         6745 is done.&lt;/p&gt;
         6746 &lt;p&gt;Guillaume turned &lt;a href="https://github.com/gtk-rs/gir"&gt;gir&lt;/a&gt;, the binding generator in
         6747 &lt;a href="http://gtk-rs.org/"&gt;gtk-rs&lt;/a&gt;, from a binary into a library crate.  This will let
         6748 us have all the GObject Introspection information for parent classes
         6749 at compilation time.&lt;/p&gt;
         6750 &lt;p&gt;Antoni has been working on a tricky problem.  &lt;a href="https://gitlab.gnome.org/GNOME/gtk/blob/ecc612b1a2a0ec9791913cd22b4f94066f0448ae/gtk/gtkcontainer.h#L110"&gt;GTK+ structs that have
         6751 bitfields&lt;/a&gt; do not get reconstructed correctly from the
         6752 GObject Introspection information — &lt;a href="https://github.com/rust-lang/rfcs/issues/314"&gt;Rust does not handle C
         6753 bitfields yet&lt;/a&gt;.  This has two implications.
         6754 First, we lose some of the original struct fields in the generated
         6755 bindings.  Second, the sizes of the generated structs are not the
         6756 same as the original C structs, so &lt;code&gt;g_type_register_static()&lt;/code&gt;
         6757 complains that one is trying to register an invalid class.&lt;/p&gt;
         6758 &lt;p&gt;Yesterday we got as far as reading the &lt;a href="http://refspecs.linuxfoundation.org/elf/x86_64-abi-0.95.pdf"&gt;amd64&lt;/a&gt; and [ARM][arm]
         6759 ABI manuals to see what the hell C compilers are supposed to do for
         6760 laying out structs with bitfields.  Most likely, we will have a
         6761 temporary fix in &lt;a href="https://github.com/gtk-rs/gir"&gt;gir&lt;/a&gt;'s code generator so that it generates
         6762 structs with the same layout as the C ones, with padding in place of
         6763 the space for bitfields.  Later we can remove this when rustc gets
         6764 support for C bitfields.&lt;/p&gt;
         6765 &lt;p&gt;I've been working on support for GObject interfaces.  The basic
         6766 parsing is done; I'm about to refactor the code generation so I can
         6767 reuse the parts that fill vtables from classes.&lt;/p&gt;
         6768 &lt;p&gt;Yesterday we went to the Madrid Rust Meetup, a regular meeting of
         6769 rustaceans here.  Martin talked about WebRender; I talked about
         6770 refactoring C to port it to Rust, and then Alex talked about Rust's
         6771 plans for 2018.  Fun times.&lt;/p&gt;
         6772 &lt;p&gt;&lt;img alt="Sponsored by the GNOME Foundation" src="https://people.gnome.org/~federico/blog/images/sponsored-badge-shadow.png"&gt;&lt;/p&gt;
         6773 &lt;p&gt;&lt;img alt="Hosted by OpenShine" src="https://www.openshine.com/wp-content/uploads/2016/03/openshine.png"&gt;&lt;/p&gt;
         6774 &lt;p&gt;[arm]: &lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="gnome"></category><category term="hackfests"></category><category term="librsvg"></category></entry><entry><title>Madrid GNOME+Rust Hackfest, part 1</title><link href="https://people.gnome.org/~federico/blog/madrid-gnome-rust-1.html" rel="alternate"></link><published>2018-04-18T02:55:12-05:00</published><updated>2018-04-18T02:55:12-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-04-18:/~federico/blog/madrid-gnome-rust-1.html</id><summary type="html">&lt;p&gt;I'm in Madrid since Monday, at the &lt;a href="https://wiki.gnome.org/Hackfests/Rust2018"&gt;third GNOME+Rust hackfest&lt;/a&gt;!
         6775 The &lt;a href="https://www.openshine.com/"&gt;OpenShine&lt;/a&gt; folks are kindly letting us use their offices, on the
         6776 seventh floor of a building by the &lt;a href="https://www.openstreetmap.org/node/5303271991"&gt;Cuatro Caminos
         6777 roundabout&lt;/a&gt;.&lt;/p&gt;
         6778 &lt;p&gt;I am very, very thankful that this time everyone seems to be working
         6779 on developing &lt;a href="https://gitlab.gnome.org/federico/gnome-class"&gt;gnome-class&lt;/a&gt;.  It's …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I'm in Madrid since Monday, at the &lt;a href="https://wiki.gnome.org/Hackfests/Rust2018"&gt;third GNOME+Rust hackfest&lt;/a&gt;!
         6780 The &lt;a href="https://www.openshine.com/"&gt;OpenShine&lt;/a&gt; folks are kindly letting us use their offices, on the
         6781 seventh floor of a building by the &lt;a href="https://www.openstreetmap.org/node/5303271991"&gt;Cuatro Caminos
         6782 roundabout&lt;/a&gt;.&lt;/p&gt;
         6783 &lt;p&gt;I am very, very thankful that this time everyone seems to be working
         6784 on developing &lt;a href="https://gitlab.gnome.org/federico/gnome-class"&gt;gnome-class&lt;/a&gt;.  It's a difficult project for me, and
         6785 more brainpower is definitely welcome — all the indirection, type
         6786 conversion, GObject obscurity, and procedural macro shenanigans
         6787 definitely take a toll on oneself.&lt;/p&gt;
         6788 &lt;h1&gt;Gnome-class internals&lt;/h1&gt;
         6789 &lt;p&gt;&lt;img alt="Gnome-class internals on the whiteboard" src="https://people.gnome.org/~federico/blog/images/madrid-whiteboard.jpg"&gt;&lt;/p&gt;
         6790 &lt;p&gt;I explained how gnome-class works to the rest of the hackfest
         6791 attendees.  I've been writing a document on &lt;a href="https://federico.pages.gitlab.gnome.org/gnome-class/"&gt;gnome-class's
         6792 internals&lt;/a&gt;, so the whiteboard was a whirlwind tour through
         6793 it.&lt;/p&gt;
         6794 &lt;h1&gt;Error messages from the compiler&lt;/h1&gt;
         6795 &lt;p&gt;Antoni Boucher, the author of &lt;a href="http://relm.ml/"&gt;relm&lt;/a&gt; (a Rust crate to write GTK+
         6796 asynchronous widgets with an Elm-like model), explained to me how relm
         6797 manages to present good error messages from the Rust compiler, when
         6798 the user's code has mistakes.  Right now this is in a very bad state
         6799 in gnome-class: user errors within the invocation of the procedural
         6800 macro get shown by the compiler as errors &lt;em&gt;at&lt;/em&gt; the macro call, so you
         6801 don't get line number information that is meaningful.&lt;/p&gt;
         6802 &lt;p&gt;For a large part of the day we tried to refactor bits of gnome-class
         6803 to do something similar.  It is very slightly better now, but this
         6804 really requires me to sit down calmly, at home, and to fully
         6805 understand how relm does it and what changes are needed in the &lt;a href="https://github.com/dtolnay/syn"&gt;syn&lt;/a&gt;
         6806 parser crate to make it easy to present good errors.&lt;/p&gt;
         6807 &lt;p&gt;I think I'll continue this work at home, as there is a lot of source
         6808 code to understand:  the combinator parsers in &lt;a href="https://github.com/dtolnay/syn"&gt;syn&lt;/a&gt;, the error
         6809 handling scheme in &lt;a href="http://relm.ml/"&gt;relm&lt;/a&gt;, and the peculiarities of gnome-class.&lt;/p&gt;
         6810 &lt;h1&gt;Further work during the hackfest&lt;/h1&gt;
         6811 &lt;p&gt;Other people working on gnome-class are adding support for GObject
         6812 properties, inheritance from non-Rust classes, and improving the
         6813 ergonomics of class-private structures.&lt;/p&gt;
         6814 &lt;p&gt;I think I'll stop working on error messages for now, and focus instead
         6815 on either supporting GTypeInterfaces, or completing support for type
         6816 conversions for methods and signals.&lt;/p&gt;
         6817 &lt;h1&gt;Other happenings in Rust&lt;/h1&gt;
         6818 &lt;p&gt;Paolo Borelli has been &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/merge_requests/50"&gt;porting RsvgState to Rust&lt;/a&gt; in librsvg.
         6819 This is the big structure that holds all the CSS state for SVG
         6820 elements.  This is very meticulous work, and I'm thankful that Paolo
         6821 is paying good attention to it.  Soon we will have all the style
         6822 machinery for librsvg in Rust, which will make it easier to use the
         6823 &lt;a href="https://crates.io/crates/selectors"&gt;selectors crate from Servo&lt;/a&gt; instead of libcroco, as the
         6824 latter is unmaintained.&lt;/p&gt;
         6825 &lt;h1&gt;Food&lt;/h1&gt;
         6826 &lt;p&gt;&lt;img alt="Food in Madrid" src="https://people.gnome.org/~federico/blog/images/madrid-food.jpg"&gt;&lt;/p&gt;
         6827 &lt;p&gt;Ah, Spanish food.  We have been enjoying cheese, jamón, tortilla,
         6828 pimientos, oxtail stews, natillas, café con leche...&lt;/p&gt;
         6829 &lt;h1&gt;Thanks&lt;/h1&gt;
         6830 &lt;p&gt;Thanks to &lt;a href="https://www.openshine.com/"&gt;OpenShine&lt;/a&gt; for hosting the hackfest, and to the GNOME
         6831 Foundation for sponsoring my travel.  And thanks for Alberto Ruiz for
         6832 putting me up in his house!&lt;/p&gt;
         6833 &lt;p&gt;&lt;img alt="Sponsored by the GNOME Foundation" src="https://people.gnome.org/~federico/blog/images/sponsored-badge-shadow.png"&gt;&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="gnome"></category><category term="hackfests"></category><category term="librsvg"></category></entry><entry><title>Refactoring some repetitive code to a Rust macro</title><link href="https://people.gnome.org/~federico/blog/refactoring-some-repetitive-code-to-a-macro.html" rel="alternate"></link><published>2018-03-23T11:01:30-06:00</published><updated>2018-03-23T11:01:30-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-03-23:/~federico/blog/refactoring-some-repetitive-code-to-a-macro.html</id><summary type="html">&lt;p&gt;I have started porting the code in librsvg that parses SVG's CSS
         6834 properties from C to Rust.  Many properties have symbolic values:&lt;/p&gt;
         6835 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;stroke-linejoin: miter | round | bevel | inherit
         6836 
         6837 stroke-linecap: butt | round | square | inherit
         6838 
         6839 fill-rule: nonzero | evenodd | inherit
         6840 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6841 
         6842 &lt;p&gt;&lt;code&gt;StrokeLinejoin&lt;/code&gt; is the first property that I ported.  First I had to
         6843 write a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I have started porting the code in librsvg that parses SVG's CSS
         6844 properties from C to Rust.  Many properties have symbolic values:&lt;/p&gt;
         6845 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;stroke-linejoin: miter | round | bevel | inherit
         6846 
         6847 stroke-linecap: butt | round | square | inherit
         6848 
         6849 fill-rule: nonzero | evenodd | inherit
         6850 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6851 
         6852 &lt;p&gt;&lt;code&gt;StrokeLinejoin&lt;/code&gt; is the first property that I ported.  First I had to
         6853 write a little bunch of machinery to allow CSS properties to be kept
         6854 in Rust-space instead of the main C structure that holds them
         6855 (upcoming blog post about that).  But for now, I just want to show how
         6856 this boiled down to a macro after refactoring.&lt;/p&gt;
         6857 &lt;h1&gt;First cut at the code&lt;/h1&gt;
         6858 &lt;p&gt;The &lt;code&gt;stroke-linejoin&lt;/code&gt; property can have the values &lt;code&gt;miter&lt;/code&gt;, &lt;code&gt;round&lt;/code&gt;,
         6859 &lt;code&gt;bevel&lt;/code&gt;, or &lt;code&gt;inherit&lt;/code&gt;.  Here is an enum definition for those values,
         6860 and the conventional machinery which librsvg uses to parse property values:&lt;/p&gt;
         6861 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[derive(Debug, Copy, Clone)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6862 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;StrokeLinejoin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6863 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Miter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6864 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Round&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6865 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Bevel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6866 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Inherit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6867 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6868 
         6869 &lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;StrokeLinejoin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6870 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6871 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;Err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6872 
         6873 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;: &lt;span class="nc"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;StrokeLinejoin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AttributeError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6874 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6875 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;miter&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StrokeLinejoin&lt;/span&gt;::&lt;span class="n"&gt;Miter&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6876 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;round&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StrokeLinejoin&lt;/span&gt;::&lt;span class="n"&gt;Round&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6877 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bevel&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StrokeLinejoin&lt;/span&gt;::&lt;span class="n"&gt;Bevel&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6878 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;inherit&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StrokeLinejoin&lt;/span&gt;::&lt;span class="n"&gt;Inherit&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6879 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AttributeError&lt;/span&gt;::&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;invalid value&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6880 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6881 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6882 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6883 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6884 
         6885 &lt;p&gt;We &lt;code&gt;match&lt;/code&gt; the allowed string values and map them to enum values.  No
         6886 big deal, right?&lt;/p&gt;
         6887 &lt;p&gt;Properties also have a default value.  For example, the SVG spec says
         6888 that if a shape doesn't have a &lt;code&gt;stroke-linejoin&lt;/code&gt; property specified,
         6889 it will use &lt;code&gt;miter&lt;/code&gt; by default.  Let's implement that:&lt;/p&gt;
         6890 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;StrokeLinejoin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6891 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;StrokeLinejoin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6892 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;StrokeLinejoin&lt;/span&gt;::&lt;span class="n"&gt;Miter&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6893 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6894 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6895 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6896 
         6897 &lt;p&gt;So far, we have three things:&lt;/p&gt;
         6898 &lt;ul&gt;
         6899 &lt;li&gt;An enum definition for the property's possible values.&lt;/li&gt;
         6900 &lt;li&gt;&lt;code&gt;impl Parse&lt;/code&gt; so we can parse the property from a string.&lt;/li&gt;
         6901 &lt;li&gt;&lt;code&gt;impl Default&lt;/code&gt; so the property knows its default value.&lt;/li&gt;
         6902 &lt;/ul&gt;
         6903 &lt;h1&gt;Where things got repetitive&lt;/h1&gt;
         6904 &lt;p&gt;The next property I ported was &lt;code&gt;stroke-linecap&lt;/code&gt;, which can take the
         6905 following values:&lt;/p&gt;
         6906 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[derive(Debug, Copy, Clone)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6907 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;StrokeLinecap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6908 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Butt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6909 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Round&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6910 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Square&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6911 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Inherit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6912 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6913 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6914 
         6915 &lt;p&gt;This is similar in shape to the &lt;code&gt;StrokeLinejoin&lt;/code&gt; enum above;
         6916 it's just different names.&lt;/p&gt;
         6917 &lt;p&gt;The parsing has exactly the same shape, and just different values:&lt;/p&gt;
         6918 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;StrokeLinecap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6919 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6920 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;Err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6921 
         6922 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;: &lt;span class="nc"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;StrokeLinecap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AttributeError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6923 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6924 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;butt&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StrokeLinecap&lt;/span&gt;::&lt;span class="n"&gt;Butt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6925 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;round&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StrokeLinecap&lt;/span&gt;::&lt;span class="n"&gt;Round&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6926 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;square&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StrokeLinecap&lt;/span&gt;::&lt;span class="n"&gt;Square&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6927 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;inherit&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StrokeLinecap&lt;/span&gt;::&lt;span class="n"&gt;Inherit&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6928 
         6929 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AttributeError&lt;/span&gt;::&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;invalid value&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6930 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6931 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6932 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6933 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6934 
         6935 &lt;p&gt;Same thing with the default:&lt;/p&gt;
         6936 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;StrokeLinecap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6937 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;StrokeLinecap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6938 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;StrokeLinecap&lt;/span&gt;::&lt;span class="n"&gt;Butt&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6939 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6940 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6941 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6942 
         6943 &lt;p&gt;Yes, the SVG spec has&lt;/p&gt;
         6944 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;butt&lt;/span&gt;
         6945 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6946 
         6947 &lt;p&gt;somewhere in it, much to the delight of the 12-year old in me.&lt;/p&gt;
         6948 &lt;h1&gt;Refactoring to a macro&lt;/h1&gt;
         6949 &lt;p&gt;Here I wanted to define a &lt;code&gt;make_ident_property!()&lt;/code&gt; macro that would
         6950 get invoked like this:&lt;/p&gt;
         6951 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;make_ident_property&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6952 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;StrokeLinejoin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6953 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;: &lt;span class="nc"&gt;Miter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6954 
         6955 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;miter&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Miter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6956 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;round&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Round&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6957 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bevel&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Bevel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6958 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;inherit&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Inherit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6959 &lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6960 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6961 
         6962 &lt;p&gt;It's called &lt;code&gt;make_ident_property&lt;/code&gt; because it makes a property
         6963 definition from simple string identifiers.  It has the name of the
         6964 property (&lt;code&gt;StrokeLinejoin&lt;/code&gt;), a &lt;code&gt;default&lt;/code&gt; value, and a few repeating
         6965 elements, one for each possible value.&lt;/p&gt;
         6966 &lt;p&gt;In Rust-speak, the macro's basic pattern is like this:&lt;/p&gt;
         6967 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make_ident_property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6968 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$name&lt;/span&gt;: &lt;span class="nc"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6969 &lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;: &lt;span class="cp"&gt;$default&lt;/span&gt;: &lt;span class="nc"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6970 &lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="cp"&gt;$($str_prop&lt;/span&gt;: &lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$variant&lt;/span&gt;: &lt;span class="nc"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6971 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6972 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;macro&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;will&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;here&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6973 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6974 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6975 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6976 
         6977 &lt;p&gt;Let's dissect that pattern:&lt;/p&gt;
         6978 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make_ident_property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6979 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$name&lt;/span&gt;: &lt;span class="nc"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6980 &lt;span class="c1"&gt;//   ^^^^^^^^^^^^ will match an identifier and put it in $name&lt;/span&gt;
         6981 
         6982 &lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;: &lt;span class="cp"&gt;$default&lt;/span&gt;: &lt;span class="nc"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6983 &lt;span class="c1"&gt;//            ^^^^^^^^^^^^^^^ will match an identifier and put it in $default&lt;/span&gt;
         6984 &lt;span class="c1"&gt;//   ^^^^^^^^ arbitrary text&lt;/span&gt;
         6985 
         6986 &lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="cp"&gt;$($str_prop&lt;/span&gt;: &lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$variant&lt;/span&gt;: &lt;span class="nc"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6987 &lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="o"&gt;^^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arbitrary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6988 &lt;span class="c1"&gt;//   ^^ start of repetition               ^^ end of repetition, repeats one or more times&lt;/span&gt;
         6989 
         6990 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6991 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6992 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6993 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         6994 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         6995 
         6996 &lt;p&gt;For example, saying "&lt;code&gt;$foo: ident&lt;/code&gt;" in a macro's pattern means that the
         6997 compiler will expect an identifier, and bind it to &lt;code&gt;$foo&lt;/code&gt; within the
         6998 macro's definition.&lt;/p&gt;
         6999 &lt;p&gt;Similarly, an &lt;code&gt;expr&lt;/code&gt; means that the compiler will
         7000 look for an expression — in this case, we want one of the string
         7001 values.&lt;/p&gt;
         7002 &lt;p&gt;In a macro pattern, anything that is not a binding is just arbitrary
         7003 text which must appear in the macro's invocation.  This is how we can
         7004 create a little syntax of our own within the macro:  the "&lt;code&gt;default:&lt;/code&gt;"
         7005 part, and the "&lt;code&gt;=&amp;gt;&lt;/code&gt;" inside each string/symbol pair.&lt;/p&gt;
         7006 &lt;p&gt;Finally, macro patterns allow repetition.  Anything within &lt;code&gt;$(...)&lt;/code&gt;
         7007 indicates repetition.  Here, &lt;code&gt;$(...)+&lt;/code&gt; indicates that the
         7008 compiler must match one or more of the repeating elements.&lt;/p&gt;
         7009 &lt;p&gt;I pasted the duplicated code, and substituted the actual symbol names
         7010 for the macro's bindings:&lt;/p&gt;
         7011 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make_ident_property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7012 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$name&lt;/span&gt;: &lt;span class="nc"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7013 &lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;: &lt;span class="cp"&gt;$default&lt;/span&gt;: &lt;span class="nc"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7014 &lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="cp"&gt;$($str_prop&lt;/span&gt;: &lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$variant&lt;/span&gt;: &lt;span class="nc"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7015 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7016 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cp"&gt;#[derive(Debug, Copy, Clone)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7017 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="cp"&gt;$name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7018 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="cp"&gt;$($variant&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7019 &lt;span class="c1"&gt;//          ^^^^^^^^^^^^^ this is how we invoke a repeated element&lt;/span&gt;
         7020 
         7021 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7022 
         7023 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7024 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="cp"&gt;$name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7025 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="cp"&gt;$name&lt;/span&gt;::&lt;span class="cp"&gt;$default&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7026 &lt;span class="c1"&gt;//              ^^^^^^^^^^^^^^^ construct an enum::variant&lt;/span&gt;
         7027 
         7028 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7029 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7030 
         7031 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7032 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7033 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;Err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7034 
         7035 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;: &lt;span class="nc"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cp"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AttributeError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7036 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7037 &lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="cp"&gt;$($str_prop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$name&lt;/span&gt;::&lt;span class="cp"&gt;$variant&lt;/span&gt;&lt;span class="p"&gt;),)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7038 &lt;span class="c1"&gt;//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expand repeated elements&lt;/span&gt;
         7039 
         7040 &lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AttributeError&lt;/span&gt;::&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;invalid value&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7041 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7042 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7043 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7044 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7045 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7046 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7047 
         7048 &lt;h1&gt;Getting rid of duplicated code&lt;/h1&gt;
         7049 &lt;p&gt;Now we have a macro that we can call to define new properties.
         7050 Librsvg now has this, which is much more readable than all the code
         7051 written by hand:&lt;/p&gt;
         7052 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;make_ident_property&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7053 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;StrokeLinejoin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7054 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;: &lt;span class="nc"&gt;Miter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7055 
         7056 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;miter&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Miter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7057 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;round&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Round&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7058 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bevel&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Bevel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7059 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;inherit&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Inherit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7060 &lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7061 
         7062 &lt;span class="n"&gt;make_ident_property&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7063 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;StrokeLinecap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7064 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;: &lt;span class="nc"&gt;Butt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// :)&lt;/span&gt;
         7065 
         7066 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;butt&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Butt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7067 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;round&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Round&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7068 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;square&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Square&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7069 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;inherit&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Inherit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7070 &lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7071 
         7072 &lt;span class="n"&gt;make_ident_property&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7073 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;FillRule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7074 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;: &lt;span class="nc"&gt;NonZero&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7075 
         7076 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;nonzero&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;NonZero&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7077 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;evenodd&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EvenOdd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7078 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;inherit&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Inherit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7079 &lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7080 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7081 
         7082 &lt;p&gt;Etcetera.  It's now easy to port similar symbol-based properties from
         7083 C to Rust.&lt;/p&gt;
         7084 &lt;p&gt;Eventually I'll need to refactor all the crap that deals with
         7085 inheritable properties, but that's for another time.&lt;/p&gt;
         7086 &lt;h1&gt;Conclusion and references&lt;/h1&gt;
         7087 &lt;p&gt;Rust macros are very powerful to refactor repetitive code like this.&lt;/p&gt;
         7088 &lt;p&gt;&lt;a href="https://doc.rust-lang.org/book/second-edition/appendix-04-macros.html"&gt;The Rust book&lt;/a&gt;
         7089 has an introductory appendix to macros, and &lt;a href="https://danielkeep.github.io/tlborm/book/index.html"&gt;The Little Book of Rust
         7090 Macros&lt;/a&gt; is a
         7091 fantastic resource that really dives into what you can do.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="librsvg"></category></entry><entry><title>Making sure the repository doesn't break, automatically</title><link href="https://people.gnome.org/~federico/blog/making-sure-the-repository-doesnt-break.html" rel="alternate"></link><published>2018-03-20T19:37:02-06:00</published><updated>2018-03-20T20:33:46-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-03-20:/~federico/blog/making-sure-the-repository-doesnt-break.html</id><summary type="html">&lt;p&gt;Gitlab has a fairly conventional Continuous Integration system:  you
         7092 push some commits, the CI pipelines build the code and presumably run
         7093 the test suite, and later you can know if this succeeded of failed.&lt;/p&gt;
         7094 &lt;p&gt;But by the time something fails, the broken code is already in the
         7095 public repository.&lt;/p&gt;
         7096 &lt;p&gt;The …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Gitlab has a fairly conventional Continuous Integration system:  you
         7097 push some commits, the CI pipelines build the code and presumably run
         7098 the test suite, and later you can know if this succeeded of failed.&lt;/p&gt;
         7099 &lt;p&gt;But by the time something fails, the broken code is already in the
         7100 public repository.&lt;/p&gt;
         7101 &lt;p&gt;The Rust community uses Bors, a bot that prevents this from happening:&lt;/p&gt;
         7102 &lt;ul&gt;
         7103 &lt;li&gt;
         7104 &lt;p&gt;You push some commits and submit a merge request.&lt;/p&gt;
         7105 &lt;/li&gt;
         7106 &lt;li&gt;
         7107 &lt;p&gt;A human looks at your merge request; they may tell you to make
         7108   changes, or they may tell Bors that your request is approved for
         7109   merging.&lt;/p&gt;
         7110 &lt;/li&gt;
         7111 &lt;li&gt;
         7112 &lt;p&gt;Bors looks for approved merge requests.  It merges each into a
         7113   &lt;em&gt;temporary branch&lt;/em&gt; and waits for the CI pipeline to run there.  If
         7114   CI passes, Bors automatically merges to master.  If CI fails, Bors
         7115   annotates the merge request with the failure, &lt;strong&gt;and the main
         7116   repository stays working&lt;/strong&gt;.&lt;/p&gt;
         7117 &lt;/li&gt;
         7118 &lt;/ul&gt;
         7119 &lt;p&gt;Bors also tells you if the mainline has moved forward and there's a
         7120 merge conflict.  In that case you need to do a rebase yourself; the
         7121 repository stays working in the meantime.&lt;/p&gt;
         7122 &lt;p&gt;This leads to a very fair, very transparent process for contributors
         7123 and for maintainers.  For all the details, watch &lt;a href="https://www.youtube.com/watch?v=dIageYT0Vgg"&gt;Emily Dunham's
         7124 presentation on Rust's community
         7125 automation&lt;/a&gt;
         7126 (&lt;a href="http://edunham.net/2016/09/27/rust_s_community_automation.html"&gt;transcript&lt;/a&gt;).&lt;/p&gt;
         7127 &lt;p&gt;For a description of where Bors came from, read &lt;a href="https://graydon.livejournal.com/186550.html"&gt;Graydon Hoare's
         7128 blog&lt;/a&gt;.&lt;/p&gt;
         7129 &lt;p&gt;&lt;a href="https://github.com/graydon/bors"&gt;Bors&lt;/a&gt; evolved into
         7130 &lt;a href="https://github.com/servo/homu"&gt;Homu&lt;/a&gt; and it is what Rust and Servo
         7131 use currently.  However, Homu depends on Github.&lt;/p&gt;
         7132 &lt;p&gt;I just found out that there is a &lt;a href="https://github.com/coldnight/homu-gitlab"&gt;port of Homu for
         7133 Gitlab&lt;/a&gt;.  Would anyone care
         7134 to set it up?&lt;/p&gt;
         7135 &lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href="https://a.weirder.earth/@bb010g/99719506883461036"&gt;Two&lt;/a&gt;
         7136 &lt;a href="https://octodon.social/@graydon/99719514193737493"&gt;people&lt;/a&gt; have
         7137 suggested porting &lt;a href="https://bors.tech/"&gt;Bors-ng&lt;/a&gt; to Gitlab instead,
         7138 &lt;a href="https://a.weirder.earth/@bb010g/99719537971696863"&gt;for scalability
         7139 reasons&lt;/a&gt;.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="gnome"></category><category term="librsvg"></category><category term="cairo"></category></entry><entry><title>Librsvg and Gnome-class accepting interns</title><link href="https://people.gnome.org/~federico/blog/interns-summer-2018.html" rel="alternate"></link><published>2018-03-12T19:00:08-06:00</published><updated>2018-03-13T10:04:33-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-03-12:/~federico/blog/interns-summer-2018.html</id><summary type="html">&lt;p&gt;I would like to mentor people for &lt;a href="https://gitlab.gnome.org/GNOME/librsvg"&gt;librsvg&lt;/a&gt; and &lt;a href="https://gitlab.gnome.org/federico/gnome-class"&gt;gnome-class&lt;/a&gt; this
         7140 Summer, both for &lt;a href="https://www.outreachy.org/"&gt;Outreachy&lt;/a&gt; and &lt;a href="https://wiki.gnome.org/Outreach/SummerOfCode"&gt;Summer of Code&lt;/a&gt;.&lt;/p&gt;
         7141 &lt;h1&gt;Librsvg projects&lt;/h1&gt;
         7142 &lt;p&gt;&lt;strong&gt;&lt;em&gt;Project:&lt;/em&gt;&lt;/strong&gt; &lt;a href="https://www.outreachy.org/2018-may-august/communities/gnome/"&gt;port filter effects from C to Rust&lt;/a&gt;&lt;/p&gt;
         7143 &lt;p&gt;Currently librsvg implements SVG filter effects in C.  These are basic
         7144 image processing filters like Gaussian blur, matrix convolution,
         7145 Porter-Duff alpha …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I would like to mentor people for &lt;a href="https://gitlab.gnome.org/GNOME/librsvg"&gt;librsvg&lt;/a&gt; and &lt;a href="https://gitlab.gnome.org/federico/gnome-class"&gt;gnome-class&lt;/a&gt; this
         7146 Summer, both for &lt;a href="https://www.outreachy.org/"&gt;Outreachy&lt;/a&gt; and &lt;a href="https://wiki.gnome.org/Outreach/SummerOfCode"&gt;Summer of Code&lt;/a&gt;.&lt;/p&gt;
         7147 &lt;h1&gt;Librsvg projects&lt;/h1&gt;
         7148 &lt;p&gt;&lt;strong&gt;&lt;em&gt;Project:&lt;/em&gt;&lt;/strong&gt; &lt;a href="https://www.outreachy.org/2018-may-august/communities/gnome/"&gt;port filter effects from C to Rust&lt;/a&gt;&lt;/p&gt;
         7149 &lt;p&gt;Currently librsvg implements SVG filter effects in C.  These are basic
         7150 image processing filters like Gaussian blur, matrix convolution,
         7151 Porter-Duff alpha compositing, etc.&lt;/p&gt;
         7152 &lt;p&gt;There are &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/milestones/4"&gt;some things&lt;/a&gt; that need to be done:&lt;/p&gt;
         7153 &lt;ul&gt;
         7154 &lt;li&gt;
         7155 &lt;p&gt;Split the single &lt;code&gt;rsvg-filter.c&lt;/code&gt; into multiple source files, so it's
         7156   easier to port each one individually.&lt;/p&gt;
         7157 &lt;/li&gt;
         7158 &lt;li&gt;
         7159 &lt;p&gt;Figure out the common infrasctructure: &lt;code&gt;RsvgFilter&lt;/code&gt;,
         7160   &lt;code&gt;RsvgFilterPrimitive&lt;/code&gt;.  All the filter use these to store
         7161   intermediate results when processing SVG elements.&lt;/p&gt;
         7162 &lt;/li&gt;
         7163 &lt;li&gt;
         7164 &lt;p&gt;Experiment with the correct Rust abstractions to process images
         7165   pixel-by-pixel.  We would like to omit per-pixel bounds checks on
         7166   array accesses.  The &lt;a href="https://crates.io/crates/image"&gt;image crate&lt;/a&gt; has some nice iterator
         7167   traits for pixels.  WebKit's implementation of SVG filters also has
         7168   interesting abstractions for things like the need for a sliding
         7169   window with edge handling for Gaussian blurs.&lt;/p&gt;
         7170 &lt;/li&gt;
         7171 &lt;li&gt;
         7172 &lt;p&gt;Ensure that our current filters code is actually working.  Not all
         7173   of the official SVG test suite's tests are in place right now for
         7174   the filter effects; it is likely that some of our implementation is
         7175   broken.&lt;/p&gt;
         7176 &lt;/li&gt;
         7177 &lt;/ul&gt;
         7178 &lt;p&gt;For this project, it will be especially helpful to have a little
         7179 background in image processing.  You don't need to be an expert; just
         7180 to have done some pixel crunching at some point.  You need to be able
         7181 to read C and write Rust.&lt;/p&gt;
         7182 &lt;p&gt;&lt;strong&gt;&lt;em&gt;Project:&lt;/em&gt;&lt;/strong&gt; &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/milestones/6"&gt;CSS styling with rust-selectors&lt;/a&gt;&lt;/p&gt;
         7183 &lt;p&gt;Librsvg uses an very simplistic algorithm for CSS cascading.  It uses
         7184 libcroco to parse CSS style data; libcroco is unmaintained and rather
         7185 prone to exploits.  I want to use Servo's selectors crate to do the
         7186 cascading; we already use the rust-cssparser crate as a tokenizer for
         7187 basic CSS properties.&lt;/p&gt;
         7188 &lt;ul&gt;
         7189 &lt;li&gt;
         7190 &lt;p&gt;For each node in its DOM tree, librsvg's &lt;code&gt;Node&lt;/code&gt; structure keeps a
         7191   &lt;code&gt;Vec&amp;lt;&amp;gt;&lt;/code&gt; of children.  &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/220"&gt;We need to move this to store the next
         7192   sibling and the first/last children instead&lt;/a&gt;.  This is the
         7193   data structure that rust-selectors prefers.  The Kuchiki crate has
         7194   an example implementation; borrowing some patterns from there could
         7195   also help us simplify our reference counting for nodes.&lt;/p&gt;
         7196 &lt;/li&gt;
         7197 &lt;li&gt;
         7198 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/223"&gt;Our styling machinery needs porting to Rust&lt;/a&gt;.  We have a
         7199   big &lt;code&gt;RsvgState&lt;/code&gt; struct which holds the CSS state for each node.  It
         7200   is easy to port this to Rust; it's more interesting to gradually
         7201   move it to a scheme like Servo's, with a distinction between
         7202   specified/computed/used values for each CSS property.&lt;/p&gt;
         7203 &lt;/li&gt;
         7204 &lt;/ul&gt;
         7205 &lt;p&gt;For this project, it will be helpful to know a bit of how CSS works.
         7206 Definitely be comfortable with Rust concepts like ownership and
         7207 borrowing.  You don't need to be an expert, but if you are going
         7208 through the "fighting the borrow checker" stage, you'll have a harder
         7209 time with this.  Or it may be what lets you grow out of it!  You need
         7210 to be able to read C and write Rust.&lt;/p&gt;
         7211 &lt;p&gt;&lt;strong&gt;&lt;em&gt;Bugs for newcomers:&lt;/em&gt;&lt;/strong&gt; We have a number of &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues?scope=all&amp;amp;utf8=%E2%9C%93&amp;amp;state=opened&amp;amp;label_name[]=4.%20Newcomers"&gt;easy bugs for newcomers
         7212 to librsvg&lt;/a&gt;.  Some of these are in the Rust part, some
         7213 in the C part, some in both &amp;mdash; take your pick!&lt;/p&gt;
         7214 &lt;h1&gt;Projects for gnome-class&lt;/h1&gt;
         7215 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/federico/gnome-class"&gt;Gnome-class&lt;/a&gt; is the code generator that lets you write
         7216 GObject implementations in Rust.  Or at least that's the intention
         7217 &amp;mdash; the project is in early development.  The code is so new that
         7218 &lt;a href="https://gitlab.gnome.org/federico/gnome-class/issues"&gt;practically all of our bugs&lt;/a&gt; are of an exploratory
         7219 nature.&lt;/p&gt;
         7220 &lt;p&gt;Gnome-class works like a little compiler.  This is from one of the
         7221 examples; note the call to &lt;code&gt;gobject_gen!&lt;/code&gt; in there:&lt;/p&gt;
         7222 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;SignalerPrivate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7223 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;: &lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7224 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7225 
         7226 &lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SignalerPrivate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7227 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Self&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7228 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;SignalerPrivate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7229 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;: &lt;span class="nc"&gt;Cell&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7230 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7231 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7232 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7233 
         7234 &lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7235 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Signaler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7236 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;InstancePrivate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SignalerPrivate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7237 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7238 
         7239 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Signaler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7240 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;value_changed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7241 
         7242 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;set_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;: &lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7243 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_priv&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7244 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7245 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emit_value_changed&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7246 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7247 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7248 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7249 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7250 
         7251 &lt;p&gt;Gnome-class implements this &lt;code&gt;gobject_gen!&lt;/code&gt; macro as follows:&lt;/p&gt;
         7252 &lt;ol&gt;
         7253 &lt;li&gt;
         7254 &lt;p&gt;First we parse the code inside the macro using the &lt;code&gt;syn&lt;/code&gt; crate.
         7255 This is a crate that lets you parse Rust source code from the
         7256 &lt;code&gt;TokenStream&lt;/code&gt; that the compiler hands to implementations of procedural
         7257 macros.  You give a &lt;code&gt;TokenStream&lt;/code&gt; to &lt;code&gt;syn&lt;/code&gt;, and it gives you back
         7258 structs that represent function definitions, &lt;code&gt;impl&lt;/code&gt; blocks,
         7259 expressions, etc.  From this parsing stage we build an Abstract Syntax
         7260 Tree (AST) that closely matches the structure of the code that the
         7261 user wrote.&lt;/p&gt;
         7262 &lt;/li&gt;
         7263 &lt;li&gt;
         7264 &lt;p&gt;Second, we take the AST and convert it to higher-level concepts,
         7265 while verifying that the code is semantically valid.  For example, we
         7266 build up a &lt;code&gt;Class&lt;/code&gt; structure for each defined GObject class, and
         7267 annotate it with the methods and signals that the user defined for it.
         7268 This stage is the High-level Internal Representation (HIR).&lt;/p&gt;
         7269 &lt;/li&gt;
         7270 &lt;li&gt;
         7271 &lt;p&gt;Third, we generate Rust code from the validated HIR.  For each
         7272 class, we write out the boilerplate needed to register it against the
         7273 GObject type system.  For each virtual method we write a trampoline to
         7274 let the C code call into the Rust implementation, and then write out
         7275 the actual Rust impl that the user wrote.  For each signal, we
         7276 register it against the GObjectClass, and write the appropriate
         7277 trampolines both to invoke the signal's default handler and any Rust
         7278 callbacks for signal handlers.&lt;/p&gt;
         7279 &lt;/li&gt;
         7280 &lt;/ol&gt;
         7281 &lt;p&gt;For this project, you definitely need to have written GObject code in
         7282 C in the past.  You don't need to know the GObject internals; just
         7283 know that there are things like type registration, signal creation,
         7284 argument marshalling, etc.&lt;/p&gt;
         7285 &lt;p&gt;You don't need to know about compiler internals.&lt;/p&gt;
         7286 &lt;p&gt;You don't need to have written Rust procedural macros; you can learn
         7287 as you go.  The code has enough infrastructure right now that you can
         7288 cut&amp;amp;paste useful bits to get started with new features.  You should
         7289 definitely be comfortable with the Rust borrow checker and simple
         7290 lifetimes &amp;mdash; again, you can cut&amp;amp;paste useful code already, and
         7291 I'm happy to help with those.&lt;/p&gt;
         7292 &lt;p&gt;This project demands a little patience.  Working on the implementation
         7293 of procedural macros is not the smoothest experience right now (one
         7294 needs to examine generated code carefully, and play some tricks with
         7295 the compiler to debug things), but it's getting better very fast.&lt;/p&gt;
         7296 &lt;h1&gt;How to apply as an intern&lt;/h1&gt;
         7297 &lt;p&gt;&lt;a href="https://www.outreachy.org/apply/"&gt;Details for Outreachy&lt;/a&gt;&lt;/p&gt;
         7298 &lt;p&gt;&lt;a href="https://wiki.gnome.org/Outreach/SummerOfCode/Students"&gt;Details for Summer of Code&lt;/a&gt;&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gnome-class"></category><category term="rust"></category><category term="gnome"></category><category term="mentoring"></category></entry><entry><title>Helping Cairo</title><link href="https://people.gnome.org/~federico/blog/helping-cairo.html" rel="alternate"></link><published>2018-03-06T18:22:52-06:00</published><updated>2018-03-06T18:22:52-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-03-06:/~federico/blog/helping-cairo.html</id><summary type="html">&lt;p&gt;&lt;a href="https://www.cairographics.org/"&gt;Cairo&lt;/a&gt; needs help.  It is the main 2D rendering library we use
         7299 in GNOME, and in particular, it's what librsvg uses to render all
         7300 SVGs.&lt;/p&gt;
         7301 &lt;p&gt;My immediate problem with Cairo is that it explodes when called with
         7302 floating-point coordinates that fall outside the range that its
         7303 internal fixed-point numbers can …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://www.cairographics.org/"&gt;Cairo&lt;/a&gt; needs help.  It is the main 2D rendering library we use
         7304 in GNOME, and in particular, it's what librsvg uses to render all
         7305 SVGs.&lt;/p&gt;
         7306 &lt;p&gt;My immediate problem with Cairo is that it explodes when called with
         7307 floating-point coordinates that fall outside the range that its
         7308 internal fixed-point numbers can represent.  There is no validation of
         7309 incoming data, so the polygon intersector ends up with data that makes
         7310 no sense, and it crashes.&lt;/p&gt;
         7311 &lt;p&gt;I've been studying how Cairo converts from floating-point to its
         7312 fixed-point representation, and it's a nifty little algorithm.  So I
         7313 thought, no problem, I'll add validation, see how to represent the
         7314 error state internally in Cairo, and see if clients are happy with
         7315 getting back a &lt;code&gt;cairo_t&lt;/code&gt; in an error state.&lt;/p&gt;
         7316 &lt;p&gt;Cairo has a very thorough test suite... &lt;strong&gt;&lt;em&gt;that doesn't pass&lt;/em&gt;&lt;/strong&gt;.  It
         7317 is documented to be very hard to pass fully for all rendering
         7318 backends.  This is understandable, as there may be bugs in X servers
         7319 or OpenGL implementations and such.  But for the basic, software-only,
         7320 in-memory image backend, Cairo should 100% pass its test suite all the
         7321 time.  This is not the case right now; in my tree, for all the tests
         7322 of the image backend I get&lt;/p&gt;
         7323 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mf"&gt;497&lt;/span&gt; &lt;span class="n"&gt;Passed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;54&lt;/span&gt; &lt;span class="n"&gt;Failed&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt; &lt;span class="n"&gt;crashed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;14&lt;/span&gt; &lt;span class="nb"&gt;exp&lt;/span&gt;&lt;span class="n"&gt;ected&lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;27&lt;/span&gt; &lt;span class="n"&gt;Skipped&lt;/span&gt;
         7324 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7325 
         7326 &lt;p&gt;I have been looking at test failures to see what needs fixing.  Some
         7327 reference images just need to be regenerated: there have been minor
         7328 changes in font rendering that broke the reference tests.  Some
         7329 others have small differences in rendering gradients - not noticeable
         7330 by eye, just by diff tools.&lt;/p&gt;
         7331 &lt;p&gt;But some tests, I have no idea what changed that made them break.&lt;/p&gt;
         7332 &lt;p&gt;Cairo's git repository is accessible through [cgit.freedesktop.org].
         7333 As far as I know there is no continuous integration infrastructure to
         7334 ensure that tests keep passing.&lt;/p&gt;
         7335 &lt;h1&gt;Adding minimal continuous testing&lt;/h1&gt;
         7336 &lt;p&gt;I've set up a &lt;a href="https://gitlab.com/federicomenaquintero/cairo/tree/105084-ft-font-face-init"&gt;Cairo repository at gitlab.com&lt;/a&gt;.  That branch
         7337 already has a &lt;a href="https://bugs.freedesktop.org/show_bug.cgi?id=105084"&gt;fix for an uninitialized-memory bug which leads to an
         7338 invalid &lt;code&gt;free()&lt;/code&gt;&lt;/a&gt;, and some regenerated test files.&lt;/p&gt;
         7339 &lt;p&gt;The repository &lt;a href="https://gitlab.com/federicomenaquintero/cairo/blob/105084-ft-font-face-init/.gitlab-ci.yml"&gt;is configured to run a continuous integration
         7340 pipeline&lt;/a&gt; on every commit.  The test artifacts can then be
         7341 downloaded when the test suite fails.  Right now it is only testing
         7342 the image backend, for in-memory software rendering.&lt;/p&gt;
         7343 &lt;h1&gt;Initial bugs&lt;/h1&gt;
         7344 &lt;p&gt;I've started reporting &lt;a href="https://gitlab.com/federicomenaquintero/cairo/issues"&gt;a few bugs&lt;/a&gt; against that repository for
         7345 tests that fail.  These should really be in Cairo's Bugzilla, but for
         7346 now Gitlab makes it much easier to include test images directly in the
         7347 bug descriptions, so that they are easier to browse.  Read on.&lt;/p&gt;
         7348 &lt;h1&gt;Would you like to help?&lt;/h1&gt;
         7349 &lt;p&gt;A lot of projects use Cairo.  We owe it to ourselves to have a library
         7350 with a test suite that doesn't break.  Getting to that point requires
         7351 several things:&lt;/p&gt;
         7352 &lt;ul&gt;
         7353 &lt;li&gt;Fixing current failures in the image backend.&lt;/li&gt;
         7354 &lt;li&gt;Setting up the CI infrastructure to be able to test other backends.&lt;/li&gt;
         7355 &lt;li&gt;Fixing failures in the other backends.&lt;/li&gt;
         7356 &lt;/ul&gt;
         7357 &lt;p&gt;If you have experience with Cairo, please take a look at the &lt;a href="https://gitlab.com/federicomenaquintero/cairo/issues"&gt;bugs&lt;/a&gt;.
         7358 You can see the &lt;a href="https://gitlab.com/federicomenaquintero/cairo/blob/105084-ft-font-face-init/.gitlab-ci.yml"&gt;CI&lt;/a&gt; configuration to see how to run the test
         7359 suite in the same fashion on your machine.&lt;/p&gt;
         7360 &lt;p&gt;I think we can make use of modern infrastructure like gitlab and
         7361 continuous integration to improve Cairo quickly.  Currently it suffers
         7362 from lack of attention and hostile tools.  Help us out if you can!&lt;/p&gt;</content><category term="misc"></category><category term="gnome"></category><category term="librsvg"></category><category term="cairo"></category></entry><entry><title>Quick and dirty checklist to update syn 0.11.x to syn 0.12</title><link href="https://people.gnome.org/~federico/blog/syn-012.html" rel="alternate"></link><published>2018-02-26T19:20:42-06:00</published><updated>2018-02-26T19:20:42-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-02-26:/~federico/blog/syn-012.html</id><summary type="html">&lt;p&gt;Today I ported &lt;a href="https://github.com/federicomenaquintero/gnome-class"&gt;gnome-class&lt;/a&gt; from version 0.11 of the &lt;a href="https://github.com/dtolnay/syn/"&gt;syn&lt;/a&gt; crate to
         7363 version 0.12.  &lt;code&gt;syn&lt;/code&gt; is a somewhat esoteric crate that you use to
         7364 parse Rust code... from a stream of tokens... from within the
         7365 implementation of a procedural macro.  Gnome-class implements a
         7366 mini-language inside your own Rust …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today I ported &lt;a href="https://github.com/federicomenaquintero/gnome-class"&gt;gnome-class&lt;/a&gt; from version 0.11 of the &lt;a href="https://github.com/dtolnay/syn/"&gt;syn&lt;/a&gt; crate to
         7367 version 0.12.  &lt;code&gt;syn&lt;/code&gt; is a somewhat esoteric crate that you use to
         7368 parse Rust code... from a stream of tokens... from within the
         7369 implementation of a procedural macro.  Gnome-class implements a
         7370 mini-language inside your own Rust code, and so it needs to parse
         7371 Rust!&lt;/p&gt;
         7372 &lt;p&gt;The API of &lt;code&gt;syn&lt;/code&gt; has changed &lt;em&gt;a lot&lt;/em&gt;, which is kind of a pain in the
         7373 ass — but the new API seems on the road to stabilization, and is nicer
         7374 indeed.&lt;/p&gt;
         7375 &lt;p&gt;Here is a quick list of things I had to change in gnome-class to
         7376 upgrade its version of &lt;code&gt;syn&lt;/code&gt;.&lt;/p&gt;
         7377 &lt;p&gt;There is no &lt;code&gt;extern crate synom&lt;/code&gt; anymore.  You can use &lt;code&gt;syn::synom&lt;/code&gt; now.&lt;/p&gt;
         7378 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;synom&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;-&amp;gt;   &lt;span class="nc"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syn&lt;/span&gt;::&lt;span class="n"&gt;synom&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7379 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7380 
         7381 &lt;p&gt;&lt;code&gt;SynomBuffer&lt;/code&gt; is now &lt;code&gt;TokenBuffer&lt;/code&gt;:&lt;/p&gt;
         7382 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;synom&lt;/span&gt;::&lt;span class="n"&gt;SynomBuffer&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-&amp;gt;  &lt;span class="nc"&gt;syn&lt;/span&gt;::&lt;span class="n"&gt;buffer&lt;/span&gt;:&lt;span class="nc"&gt;TokenBuffer&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7383 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7384 
         7385 &lt;p&gt;&lt;code&gt;PResult&lt;/code&gt;, the result of &lt;code&gt;Synom::parse()&lt;/code&gt;, now has the tuple's
         7386 arguments reversed:&lt;/p&gt;
         7387 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;PResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Cursor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7388 &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;PResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Cursor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7389 
         7390 &lt;span class="c1"&gt;// therefore:&lt;/span&gt;
         7391 
         7392 &lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Synom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MyThing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7393 
         7394 &lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MyThing&lt;/span&gt;::&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;-&amp;gt;  &lt;span class="nc"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MyThing&lt;/span&gt;::&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7395 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7396 
         7397 &lt;p&gt;The language tokens like &lt;code&gt;synom::tokens::Amp&lt;/code&gt;, and keywords like
         7398 &lt;code&gt;synom::tokens::Type&lt;/code&gt;, are easier to use now.  There is a &lt;code&gt;Token!&lt;/code&gt;
         7399 macro which you can use in type definitions, instead of having to
         7400 remember the particular name of each token type:&lt;/p&gt;
         7401 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;synom&lt;/span&gt;::&lt;span class="n"&gt;tokens&lt;/span&gt;::&lt;span class="n"&gt;Amp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-&amp;gt;  &lt;span class="nc"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7402 
         7403 &lt;span class="n"&gt;synom&lt;/span&gt;::&lt;span class="n"&gt;tokens&lt;/span&gt;::&lt;span class="n"&gt;For&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-&amp;gt;  &lt;span class="nc"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7404 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7405 
         7406 &lt;p&gt;And for the corresponding values when matching:&lt;/p&gt;
         7407 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;syn&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;::&lt;span class="n"&gt;Colon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-&amp;gt;  &lt;span class="nc"&gt;punct&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;:&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7408 
         7409 &lt;span class="n"&gt;syn&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;::&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;-&amp;gt;  &lt;span class="nc"&gt;keyword&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7410 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7411 
         7412 &lt;p&gt;And to instantiate them for quoting/spanning:&lt;/p&gt;
         7413 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;::&lt;span class="n"&gt;Comma&lt;/span&gt;::&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;to_tokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7414 &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(,)([&lt;/span&gt;&lt;span class="n"&gt;Span&lt;/span&gt;::&lt;span class="n"&gt;def_site&lt;/span&gt;&lt;span class="p"&gt;()]).&lt;/span&gt;&lt;span class="n"&gt;to_tokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7415 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7416 
         7417 &lt;p&gt;(OK, that one wasn't nicer after all.)&lt;/p&gt;
         7418 &lt;p&gt;To the get string for an &lt;code&gt;Ident&lt;/code&gt;:&lt;/p&gt;
         7419 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_str&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-&amp;gt;  &lt;span class="nc"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7420 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7421 
         7422 &lt;p&gt;There is no &lt;code&gt;Delimited&lt;/code&gt; anymore; instead there is a &lt;code&gt;Punctuated&lt;/code&gt;
         7423 struct.  My diff has this:&lt;/p&gt;
         7424 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;-  inputs: parens!(call!(Delimited::&amp;lt;MyThing, tokens::Comma&amp;gt;::parse_terminated)) &amp;gt;&amp;gt;
         7425 +  inputs: parens!(syn!(Punctuated&amp;lt;MyThing, Token!(,)&amp;gt;)) &amp;gt;&amp;gt;
         7426 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7427 
         7428 &lt;p&gt;There is no &lt;code&gt;syn::Mutability&lt;/code&gt; anymore; now it's an &lt;code&gt;Option&amp;lt;token&amp;gt;&lt;/code&gt;, so
         7429 basically&lt;/p&gt;
         7430 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;syn&lt;/span&gt;::&lt;span class="n"&gt;Mutability&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-&amp;gt;  &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7431 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7432 
         7433 &lt;p&gt;which I guess lets you refer to the span of the original &lt;code&gt;mut&lt;/code&gt; token
         7434 if you need.&lt;/p&gt;
         7435 &lt;p&gt;Some things changed names:&lt;/p&gt;
         7436 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;TypeTup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-&amp;gt;  &lt;span class="nc"&gt;TypeTuple&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;elems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7437 
         7438 &lt;span class="n"&gt;PatIdent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;                          &lt;/span&gt;-&amp;gt;  &lt;span class="nc"&gt;PatIdent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7439 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;: &lt;span class="nc"&gt;BindingMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Mutability&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="n"&gt;by_ref&lt;/span&gt;: &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7440 &lt;span class="w"&gt;                                            &lt;/span&gt;&lt;span class="n"&gt;mutability&lt;/span&gt;: &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7441 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ident&lt;/span&gt;: &lt;span class="nc"&gt;Ident&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;ident&lt;/span&gt;: &lt;span class="nc"&gt;Ident&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7442 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;subpat&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.,&lt;/span&gt;&lt;span class="w"&gt;                            &lt;/span&gt;&lt;span class="n"&gt;subpat&lt;/span&gt;: &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Pat&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7443 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;at_token&lt;/span&gt;: &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.,&lt;/span&gt;&lt;span class="w"&gt;                      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7444 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7445 
         7446 &lt;span class="n"&gt;TypeParen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ty&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-&amp;gt;  &lt;span class="nc"&gt;TypeParen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;others&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;like&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;too&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7447 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7448 
         7449 &lt;p&gt;(I don't know everything that changed names; gnome-class doesn't use
         7450 all the syn types yet; these are just the ones I've run into.)&lt;/p&gt;
         7451 &lt;p&gt;This new &lt;code&gt;syn&lt;/code&gt; is much better at acknowledging the fine points of
         7452 macro hygiene.  The &lt;a href="https://github.com/dtolnay/syn/tree/master/examples"&gt;examples directory&lt;/a&gt; is particularly instructive;
         7453 it shows how to properly span generated code vs. original code, so
         7454 compiler error messages are nice.  I &lt;a href="https://github.com/rust-lang-nursery/rustc-guide/issues/15"&gt;need to write something about
         7455 macro hygiene&lt;/a&gt; at some point.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="gnome"></category></entry><entry><title>Librsvg's continuous integration pipeline</title><link href="https://people.gnome.org/~federico/blog/librsvg-ci-pipeline.html" rel="alternate"></link><published>2018-02-23T16:25:13-06:00</published><updated>2018-02-23T16:25:13-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-02-23:/~federico/blog/librsvg-ci-pipeline.html</id><summary type="html">&lt;p&gt;&lt;a href="https://gitlab.gnome.org/alatiera"&gt;Jordan Petridis&lt;/a&gt; has been kicking ass by overhauling
         7456 librsvg's continous integration (CI) pipeline.  Take a look at this
         7457 beauty:&lt;/p&gt;
         7458 &lt;p&gt;&lt;img alt="Continuous integration pipeline" src="https://people.gnome.org/~federico/blog/images/librsvg-pipeline.png"&gt;&lt;/p&gt;
         7459 &lt;p&gt;On every push, we run the &lt;strong&gt;Test&lt;/strong&gt; stage.  This is a quick compilation
         7460 on a Fedora container that runs "&lt;code&gt;make check&lt;/code&gt;" and ensures that the
         7461 test suite passes.&lt;/p&gt;
         7462 &lt;p&gt;We have a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://gitlab.gnome.org/alatiera"&gt;Jordan Petridis&lt;/a&gt; has been kicking ass by overhauling
         7463 librsvg's continous integration (CI) pipeline.  Take a look at this
         7464 beauty:&lt;/p&gt;
         7465 &lt;p&gt;&lt;img alt="Continuous integration pipeline" src="https://people.gnome.org/~federico/blog/images/librsvg-pipeline.png"&gt;&lt;/p&gt;
         7466 &lt;p&gt;On every push, we run the &lt;strong&gt;Test&lt;/strong&gt; stage.  This is a quick compilation
         7467 on a Fedora container that runs "&lt;code&gt;make check&lt;/code&gt;" and ensures that the
         7468 test suite passes.&lt;/p&gt;
         7469 &lt;p&gt;We have a &lt;strong&gt;Lint&lt;/strong&gt; stage which can be run manually.  This runs &lt;code&gt;cargo
         7470 clippy&lt;/code&gt; to get Rust lints (check the style of Rust idioms), and &lt;code&gt;cargo
         7471 fmt&lt;/code&gt; to check indentation and code style and such.&lt;/p&gt;
         7472 &lt;p&gt;We have a &lt;strong&gt;Distro_test&lt;/strong&gt; stage which I think will be scheduled
         7473 weekly, using Gitlab's &lt;em&gt;Schedules&lt;/em&gt; feature, to check that the tests
         7474 pass on three major Linux distros.  Recently we had trouble with
         7475 different rendering due to differences in Freetype versions, which
         7476 broke the tests (&lt;em&gt;ahem, likely because &lt;/em&gt;&lt;em&gt;I&lt;/em&gt;&lt;em&gt; hadn't updated my
         7477 Freetype in a while and distros were already using a newer one&lt;/em&gt;); these
         7478 distro tests are intended to catch that.&lt;/p&gt;
         7479 &lt;p&gt;Finally, we have a &lt;strong&gt;Rustc_test&lt;/strong&gt; stage.  The various crates that
         7480 librsvg depends on have different minimum versions for the Rust
         7481 compiler.  These tests are intended to show when updating a dependency
         7482 changes the minimum Rust version on which librsvg would compile.  We
         7483 don't have a policy yet for "how far from $newest" we should always
         7484 work on, and it would be good to get input from distros on this.  I
         7485 think these Rust tests will be scheduled weekly as well.&lt;/p&gt;
         7486 &lt;p&gt;Jordan has been experimenting with the pipeline's stages and the
         7487 distro-specific idiosyncrasies for each build.  This pipeline depends
         7488 on some &lt;a href="https://gitlab.com/alatiera/librsvg-oci-images"&gt;custom-built container images&lt;/a&gt; that already have
         7489 librsvg's dependencies installed.  These images are built weekly in
         7490 &lt;code&gt;gitlab.com&lt;/code&gt;, so every week &lt;code&gt;gitlab.gnome.org&lt;/code&gt; gets fresh images for
         7491 librsvg's CI pipelines.  Once image registries are enabled in
         7492 &lt;code&gt;gitlab.gnome.org&lt;/code&gt;, we should be able to regenerate the container
         7493 images locally without depending on an external service.&lt;/p&gt;
         7494 &lt;p&gt;With the pre-built images, and caching of Rust artifacts, Jordan was
         7495 able to &lt;strong&gt;reduce the time for the "test on every commit" builds&lt;/strong&gt; from
         7496 around 20 minutes, to little under 4 minutes in the current
         7497 iteration.  This will get even faster if the builds start using ccache
         7498 and parallel builds from GNU make.&lt;/p&gt;
         7499 &lt;p&gt;Currently we have a problem in that &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/178"&gt;tests are failing on 32-bit
         7500 builds&lt;/a&gt;, and haven't had a chance to investigate the root
         7501 cause.  Hopefully we can add 32-bit jobs to the CI pipeline to catch
         7502 this breakage as soon as possible.&lt;/p&gt;
         7503 &lt;p&gt;Having all these container images built for the CI infrastructure also
         7504 means that it will be easy for people to &lt;strong&gt;set up a development
         7505 environment&lt;/strong&gt; for librsvg, even though we have &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/blob/b75c20fb3137af9610ff48d0d31ab45e008893ff/COMPILING.md#installing-dependencies-for-building"&gt;better instructions
         7506 now&lt;/a&gt; thanks to Jordan.  I haven't investigated setting up a
         7507 Flatpak-based environment; this would be nice to have as well.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category></entry><entry><title>RFC: Integrating rsvg-rs into librsvg</title><link href="https://people.gnome.org/~federico/blog/rfc-integrating-rsvg-rs-into-librsvg.html" rel="alternate"></link><published>2018-02-22T09:57:52-06:00</published><updated>2018-02-22T09:57:52-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-02-22:/~federico/blog/rfc-integrating-rsvg-rs-into-librsvg.html</id><summary type="html">&lt;p&gt;I have started an &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/207"&gt;RFC to integrate rsvg-rs into librsvg&lt;/a&gt;.
         7508 &lt;code&gt;rsvg-rs&lt;/code&gt; is the Rust binding to librsvg.  Like the &lt;a href="http://gtk-rs.org/"&gt;gtk-rs&lt;/a&gt; bindings,
         7509 it gets generated from a pre-built &lt;a href="https://people.gnome.org/~federico/blog/magic-of-gobject-introspection.html"&gt;GIR&lt;/a&gt; file.&lt;/p&gt;
         7510 &lt;p&gt;It would be nice for librsvg to provide the Rust binding by itself, so
         7511 that librsvg's own internal tools can be …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I have started an &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/207"&gt;RFC to integrate rsvg-rs into librsvg&lt;/a&gt;.
         7512 &lt;code&gt;rsvg-rs&lt;/code&gt; is the Rust binding to librsvg.  Like the &lt;a href="http://gtk-rs.org/"&gt;gtk-rs&lt;/a&gt; bindings,
         7513 it gets generated from a pre-built &lt;a href="https://people.gnome.org/~federico/blog/magic-of-gobject-introspection.html"&gt;GIR&lt;/a&gt; file.&lt;/p&gt;
         7514 &lt;p&gt;It would be nice for librsvg to provide the Rust binding by itself, so
         7515 that librsvg's own internal tools can be implemented in Rust —
         7516 currently all the tests are done in C, as are the &lt;code&gt;rsvg-convert(1)&lt;/code&gt; and
         7517 &lt;code&gt;rsvg-view-3(1)&lt;/code&gt; programs.&lt;/p&gt;
         7518 &lt;p&gt;There are some implications for how &lt;code&gt;rsvg-rs&lt;/code&gt; would get built then.
         7519 For librsvg's internal consumption, the binding can be built from the
         7520 &lt;code&gt;Rsvg-2.0.gir&lt;/code&gt; file that gets built out of the main &lt;code&gt;librsvg.so&lt;/code&gt;.  But
         7521 for public consumption of &lt;code&gt;rsvg-rs&lt;/code&gt;, when it is being used as a normal
         7522 crate and built by Cargo, that &lt;code&gt;Rsvg-2.0.gir&lt;/code&gt; needs to be already
         7523 built and available: it wouldn't be appropriate for Cargo to build
         7524 librsvg and the &lt;code&gt;.gir&lt;/code&gt; file itself.&lt;/p&gt;
         7525 &lt;p&gt;If this sort of thing interests you, &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/207"&gt;take a look at the RFC&lt;/a&gt;!&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category><category term="gnome"></category></entry><entry><title>Rust things I miss in C</title><link href="https://people.gnome.org/~federico/blog/rust-things-i-miss-in-c.html" rel="alternate"></link><published>2018-02-18T21:26:04-06:00</published><updated>2018-02-23T18:28:23-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-02-18:/~federico/blog/rust-things-i-miss-in-c.html</id><summary type="html">&lt;p&gt;Librsvg feels like it is reaching a tipping point, where suddenly it
         7526 seems like it would be easier to just port some major parts from C to
         7527 Rust than to just add accessors for them.  Also, more and more of the
         7528 meat of the library is in Rust now.&lt;/p&gt;
         7529 &lt;p&gt;I'm …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Librsvg feels like it is reaching a tipping point, where suddenly it
         7530 seems like it would be easier to just port some major parts from C to
         7531 Rust than to just add accessors for them.  Also, more and more of the
         7532 meat of the library is in Rust now.&lt;/p&gt;
         7533 &lt;p&gt;I'm switching back and forth a lot between C and Rust these days, and
         7534 C feels very, very primitive these days.&lt;/p&gt;
         7535 &lt;h1&gt;A sort of elegy to C&lt;/h1&gt;
         7536 &lt;p&gt;I fell in love with the C language about 24 years ago.  I learned the
         7537 basics of it by reading a Spanish translation of &lt;a href="https://en.wikipedia.org/wiki/The_C_Programming_Language"&gt;The C Programming
         7538 Language by K&amp;amp;R&lt;/a&gt; second edition.  I had been using Turbo Pascal
         7539 before in a reasonably low-level fashion, with pointers and manual
         7540 memory allocation, and C felt refreshing and empowering.&lt;/p&gt;
         7541 &lt;p&gt;K&amp;amp;R is a great book for its &lt;em&gt;style of writing&lt;/em&gt; and its conciseness of
         7542 programming.  This little book even taught you how to implement a
         7543 simple &lt;code&gt;malloc()&lt;/code&gt;/&lt;code&gt;free()&lt;/code&gt;, which was completely enlightening.  Even
         7544 low-level constructs that seemed part of the language could be
         7545 implemented in the language itself!&lt;/p&gt;
         7546 &lt;p&gt;I got good at C over the following years.  It is a small language,
         7547 with a small standard library.  It was probably the perfect language
         7548 to implement Unix kernels in 20,000 lines of code or so.&lt;/p&gt;
         7549 &lt;p&gt;The GIMP and GTK+ taught me how to do fancy object orientation in C.
         7550 GNOME taught me how to maintain large-scale software in C.  20,000
         7551 lines of C code started to seem like a project one could more or less
         7552 fully understand in a few weeks.&lt;/p&gt;
         7553 &lt;p&gt;But our code bases are not that small anymore.  Our software now has
         7554 &lt;em&gt;huge&lt;/em&gt; expectations on the features that are available in the
         7555 language's standard library.&lt;/p&gt;
         7556 &lt;h2&gt;Some good experiences with C&lt;/h2&gt;
         7557 &lt;p&gt;Reading the POV-Ray code source code for the first time and learning
         7558 how to do object orientation and inheritance in C.&lt;/p&gt;
         7559 &lt;p&gt;Reading the GTK+ source code and learning a C style that was legible,
         7560 maintainable, and clean.&lt;/p&gt;
         7561 &lt;p&gt;Reading SIOD's source code, then the early Guile sources, and seeing
         7562 how a Scheme interpreter can be written in C.&lt;/p&gt;
         7563 &lt;p&gt;Writing the initial versions of Eye of Gnome and fine-tuning the
         7564 microtile rendering.&lt;/p&gt;
         7565 &lt;h2&gt;Some bad experiences with C&lt;/h2&gt;
         7566 &lt;p&gt;In the Evolution team, when everything was crashing.  We had to buy a
         7567 Solaris machine just to be able to buy Purify; there was no Valgrind
         7568 back then.&lt;/p&gt;
         7569 &lt;p&gt;Debugging gnome-vfs threading deadlocks.&lt;/p&gt;
         7570 &lt;p&gt;Debugging Mesa and getting nowhere.&lt;/p&gt;
         7571 &lt;p&gt;Taking over the intial versions of Nautilus-share and seeing that it
         7572 never &lt;code&gt;free()&lt;/code&gt;d anything.&lt;/p&gt;
         7573 &lt;p&gt;Trying to refactor code where I had no idea about the memory
         7574 management strategy.&lt;/p&gt;
         7575 &lt;p&gt;Trying to turn code into a library when it is full of global variables
         7576 and no functions are &lt;code&gt;static&lt;/code&gt;.&lt;/p&gt;
         7577 &lt;p&gt;But anyway — let's get on with things in Rust I miss in C.&lt;/p&gt;
         7578 &lt;h1&gt;Automatic resource management&lt;/h1&gt;
         7579 &lt;p&gt;One of the first blog posts I read about Rust was "&lt;a href="http://blog.skylight.io/rust-means-never-having-to-close-a-socket/"&gt;Rust means never
         7580 having to close a socket&lt;/a&gt;".  Rust borrows C++'s ideas about
         7581 &lt;a href="http://wiki.c2.com/?ResourceAcquisitionIsInitialization"&gt;Resource Acquisition Is Initialization (RAII)&lt;/a&gt;, Smart Pointers,
         7582 adds in the single-ownership principle for values, and gives you
         7583 automatic, deterministic resource management in a very neat package.&lt;/p&gt;
         7584 &lt;ul&gt;
         7585 &lt;li&gt;
         7586 &lt;p&gt;Automatic: you don't &lt;code&gt;free()&lt;/code&gt; by hand.  Memory gets deallocated,
         7587   files get closed, mutexes get unlocked when they go out of scope.
         7588   If you are wrapping an external resource, you just implement the
         7589   &lt;a href="https://doc.rust-lang.org/book/second-edition/ch15-03-drop.html"&gt;Drop&lt;/a&gt; trait and that's basically it.  The wrapped resource feels
         7590   like part of the language since you don't have to babysit its
         7591   lifetime by hand.&lt;/p&gt;
         7592 &lt;/li&gt;
         7593 &lt;li&gt;
         7594 &lt;p&gt;Deterministic: resources get created (memory allocated, initialized,
         7595   files opened, etc.), and they get destroyed when they go out of
         7596   scope.  There is no garbage collection: things really get terminated
         7597   when you close a brace.  You start to see your program's data
         7598   lifetimes as a tree of function calls.&lt;/p&gt;
         7599 &lt;/li&gt;
         7600 &lt;/ul&gt;
         7601 &lt;p&gt;After forgetting to free/close/destroy C objects all the time, or
         7602 worse, figuring out where code that I didn't write forgot to do those
         7603 things (or did them &lt;em&gt;twice&lt;/em&gt;, incorrectly)... I don't want to do it
         7604 again.&lt;/p&gt;
         7605 &lt;h1&gt;Generics&lt;/h1&gt;
         7606 &lt;p&gt;&lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt; really is a vector of whose elements are the size of &lt;code&gt;T&lt;/code&gt;.
         7607 It's not an array of pointers to individually allocated objects.  It
         7608 gets compiled &lt;em&gt;specifically&lt;/em&gt; to code that can only handle objects of
         7609 type &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;
         7610 &lt;p&gt;After writing many janky macros in C to do similar things... I don't
         7611 want to do it again.&lt;/p&gt;
         7612 &lt;h1&gt;Traits are not just interfaces&lt;/h1&gt;
         7613 &lt;p&gt;&lt;a href="https://doc.rust-lang.org/book/second-edition/ch17-00-oop.html"&gt;Rust is not a Java-like object-oriented language&lt;/a&gt;.  Instead it
         7614 has traits, which at first seem like Java interfaces — an easy way to
         7615 do dynamic dispatch, so that if an object implements &lt;code&gt;Drawable&lt;/code&gt; then
         7616 you can assume it has a &lt;code&gt;draw()&lt;/code&gt; method.&lt;/p&gt;
         7617 &lt;p&gt;However, traits are more powerful than that.&lt;/p&gt;
         7618 &lt;h2&gt;Associated types&lt;/h2&gt;
         7619 &lt;p&gt;&lt;a href="https://doc.rust-lang.org/book/second-edition/ch19-03-advanced-traits.html"&gt;Traits can have associated types&lt;/a&gt;.  As an example, Rust
         7620 provies the &lt;code&gt;Iterator&lt;/code&gt; trait which you can implement:&lt;/p&gt;
         7621 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Iterator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7622 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7623 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7624 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7625 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7626 
         7627 &lt;p&gt;This means that whenever you implement &lt;code&gt;Iterator&lt;/code&gt; for some iterable
         7628 object, you also have to specify an &lt;code&gt;Item&lt;/code&gt; type for the things that
         7629 will be produced.  If you call &lt;code&gt;next()&lt;/code&gt; and there are more elements,
         7630 you'll get back a &lt;code&gt;Some(YourElementType)&lt;/code&gt;.  When your iterator runs
         7631 out of items, it will return &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;
         7632 &lt;p&gt;Associated types can refer to &lt;em&gt;other&lt;/em&gt; traits.&lt;/p&gt;
         7633 &lt;p&gt;For example, in Rust, you can use &lt;code&gt;for&lt;/code&gt; loops on anything that
         7634 implements the &lt;code&gt;IntoIterator&lt;/code&gt; trait:&lt;/p&gt;
         7635 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;IntoIterator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7636 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;/// The type of the elements being iterated over.&lt;/span&gt;
         7637 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7638 
         7639 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;/// Which kind of iterator are we turning this into?&lt;/span&gt;
         7640 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;IntoIter&lt;/span&gt;: &lt;span class="nb"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7641 
         7642 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;into_iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;IntoIter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7643 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7644 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7645 
         7646 &lt;p&gt;When implementing this trait, you must provide both the type of the
         7647 &lt;code&gt;Item&lt;/code&gt; which your iterator will produce, and &lt;code&gt;IntoIter&lt;/code&gt;, the actual
         7648 type that implements &lt;code&gt;Iterator&lt;/code&gt; and that holds your iterator's state.&lt;/p&gt;
         7649 &lt;p&gt;This way you can build webs of types that refer to each other.  You
         7650 can have a trait that says, "I can do foo and bar, but only if you
         7651 give me a type that can do this and that".&lt;/p&gt;
         7652 &lt;h1&gt;Slices&lt;/h1&gt;
         7653 &lt;p&gt;I already posted about &lt;a href="https://people.gnome.org/~federico/blog/rant-on-string-slices.html"&gt;the lack of string slices in C&lt;/a&gt; and
         7654 how this is a pain in the ass once you get used to having them.&lt;/p&gt;
         7655 &lt;h1&gt;Modern tooling for dependency management&lt;/h1&gt;
         7656 &lt;p&gt;Instead of &lt;/p&gt;
         7657 &lt;ul&gt;
         7658 &lt;li&gt;Having to invoke &lt;code&gt;pkg-config&lt;/code&gt; by hand or with Autotools macros&lt;/li&gt;
         7659 &lt;li&gt;Wrangling include paths for header files...&lt;/li&gt;
         7660 &lt;li&gt;... and library files.&lt;/li&gt;
         7661 &lt;li&gt;And basically depending on the user to ensure that the correct
         7662   versions of libraries are installed,&lt;/li&gt;
         7663 &lt;/ul&gt;
         7664 &lt;p&gt;You write a &lt;code&gt;Cargo.toml&lt;/code&gt; file which lists the names and versions of
         7665 your dependencies.  These get downloaded from a well-known location,
         7666 or from elsewhere if you specify.&lt;/p&gt;
         7667 &lt;p&gt;You don't have to fight dependencies.  It just works when you &lt;code&gt;cargo build&lt;/code&gt;.&lt;/p&gt;
         7668 &lt;h1&gt;Tests&lt;/h1&gt;
         7669 &lt;p&gt;C makes it very hard to have unit tests for several reasons:&lt;/p&gt;
         7670 &lt;ul&gt;
         7671 &lt;li&gt;
         7672 &lt;p&gt;Internal functions are often &lt;code&gt;static&lt;/code&gt;.  This means they can't be
         7673   called outside of the source file that defined them.  A test program
         7674   either has to &lt;code&gt;#include&lt;/code&gt; the source file where the static functions
         7675   live, or use &lt;code&gt;#ifdef&lt;/code&gt;s to remove the &lt;code&gt;static&lt;/code&gt;s only during testing.&lt;/p&gt;
         7676 &lt;/li&gt;
         7677 &lt;li&gt;
         7678 &lt;p&gt;You have to write Makefile-related hackery to link the test program
         7679   to only part of your code's dependencies, or to only part of the
         7680   rest of your code.&lt;/p&gt;
         7681 &lt;/li&gt;
         7682 &lt;li&gt;
         7683 &lt;p&gt;You have to pick a testing framework.  You have to register tests
         7684   against the testing framework.  You have to &lt;em&gt;learn&lt;/em&gt; the testing
         7685   framework.&lt;/p&gt;
         7686 &lt;/li&gt;
         7687 &lt;/ul&gt;
         7688 &lt;p&gt;In Rust you write&lt;/p&gt;
         7689 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[test]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7690 &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test_that_foo_works&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7691 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;expected_result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7692 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7693 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7694 
         7695 &lt;p&gt;anywhere in your program or library, and when you type &lt;code&gt;cargo test&lt;/code&gt;,
         7696 IT JUST FUCKING WORKS.  That code only gets linked into the
         7697 test binary.  You don't have to compile anything twice by hand, or
         7698 write Makefile hackery, or figure out how to extract internal
         7699 functions for testing.&lt;/p&gt;
         7700 &lt;p&gt;This is a very killer feature for me.&lt;/p&gt;
         7701 &lt;h1&gt;Documentation, with tests&lt;/h1&gt;
         7702 &lt;p&gt;Rust generates documentation from comments in Markdown syntax.  Code
         7703 in the docs &lt;em&gt;gets run as tests&lt;/em&gt;.  You can illustrate how a function is
         7704 used &lt;em&gt;and&lt;/em&gt; test it at the same time:&lt;/p&gt;
         7705 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="sd"&gt;/// Multiples the specified number by two&lt;/span&gt;
         7706 &lt;span class="sd"&gt;///&lt;/span&gt;
         7707 &lt;span class="sd"&gt;/// ```&lt;/span&gt;
         7708 &lt;span class="sd"&gt;/// assert_eq!(multiply_by_two(5), 10);&lt;/span&gt;
         7709 &lt;span class="sd"&gt;/// ```&lt;/span&gt;
         7710 &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;multiply_by_two&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;: &lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7711 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7712 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7713 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7714 
         7715 &lt;p&gt;Your example code &lt;em&gt;gets run as tests&lt;/em&gt; to ensure that your
         7716 documentation stays up to date with the actual code.&lt;/p&gt;
         7717 &lt;p&gt;&lt;strong&gt;Update 2018/Feb/23:&lt;/strong&gt; QuietMisdreavus has posted &lt;a href="https://quietmisdreavus.net/code/2018/02/23/how-the-doctests-get-made/"&gt;how rustdoc turns
         7718 doctests into runnable code
         7719 internally&lt;/a&gt;.
         7720 This is high-grade magic and thoroughly interesting.&lt;/p&gt;
         7721 &lt;h1&gt;Hygienic macros&lt;/h1&gt;
         7722 &lt;p&gt;Rust has hygienic macros that avoid all of C's problems with things in
         7723 macros that inadvertently shadow identifiers in the code.  You don't
         7724 need to write macros where every symbol has to be in parentheses for
         7725 &lt;code&gt;max(5 + 3, 4)&lt;/code&gt; to work correctly.&lt;/p&gt;
         7726 &lt;h1&gt;No automatic coercions&lt;/h1&gt;
         7727 &lt;p&gt;All the bugs in C that result from inadvertently converting an &lt;code&gt;int&lt;/code&gt;
         7728 to a &lt;code&gt;short&lt;/code&gt; or &lt;code&gt;char&lt;/code&gt; or whatever — Rust doesn't do them.  You have
         7729 to explicitly convert.&lt;/p&gt;
         7730 &lt;h1&gt;No integer overflow&lt;/h1&gt;
         7731 &lt;p&gt;Enough said.&lt;/p&gt;
         7732 &lt;h1&gt;Generally, no undefined behavior in safe Rust&lt;/h1&gt;
         7733 &lt;p&gt;In Rust, it is considered a bug in the language if something written
         7734 in "safe Rust" (what you would be allowed to write outside &lt;code&gt;unsafe {}&lt;/code&gt;
         7735 blocks) results in undefined behavior.  You can shift-right a negative
         7736 integer and it will do exactly what you expect.&lt;/p&gt;
         7737 &lt;h1&gt;Pattern matching&lt;/h1&gt;
         7738 &lt;p&gt;You know how  &lt;code&gt;gcc&lt;/code&gt; warns you if you &lt;code&gt;switch()&lt;/code&gt; on an enum but don't
         7739 handle all values?  That's like a little baby.&lt;/p&gt;
         7740 &lt;p&gt;Rust has &lt;a href="https://doc.rust-lang.org/book/second-edition/ch18-03-pattern-syntax.html"&gt;pattern matching&lt;/a&gt; in various places.  It can do that
         7741 trick for enums inside a &lt;code&gt;match()&lt;/code&gt; expression.  It can do
         7742 destructuring so you can return multiple values from a function:&lt;/p&gt;
         7743 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7744 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;sin_cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7745 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7746 
         7747 &lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;angle&lt;/span&gt;: &lt;span class="kt"&gt;f64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;42.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7748 &lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sin_angle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cos_angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sin_cos&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7749 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7750 
         7751 &lt;p&gt;You can &lt;code&gt;match()&lt;/code&gt; on strings.  YOU CAN MATCH ON FUCKING STRINGS.&lt;/p&gt;
         7752 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;green&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7753 
         7754 &lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7755 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;red&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;it&amp;#39;s red&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7756 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;green&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;it&amp;#39;s green&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7757 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;it&amp;#39;s something else&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7758 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7759 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7760 
         7761 &lt;p&gt;You know how this is illegible?&lt;/p&gt;
         7762 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;my_func(true, false, false)
         7763 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7764 
         7765 &lt;p&gt;How about this instead, with pattern matching on function arguments:&lt;/p&gt;
         7766 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Fubarize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7767 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Frobnify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7768 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Bazificate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7769 
         7770 &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;my_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Fubarize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fub&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;: &lt;span class="nc"&gt;Fubarize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
         7771 &lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="n"&gt;Frobnify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;: &lt;span class="nc"&gt;Frobnify&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
         7772 &lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="n"&gt;Bazificate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;: &lt;span class="nc"&gt;Bazificate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7773 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7774 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7775 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7776 
         7777 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;frob&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7778 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7779 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7780 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7781 
         7782 &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7783 
         7784 &lt;span class="n"&gt;my_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Fubarize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Frobnify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Bazificate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7785 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7786 
         7787 &lt;h1&gt;Standard, useful error handling&lt;/h1&gt;
         7788 &lt;p&gt;I've talked at length about this.  No more returning a boolean with no
         7789 extra explanation for an error, no ignoring errors inadvertently, no
         7790 exception handling with nonlocal jumps.&lt;/p&gt;
         7791 &lt;h1&gt;#[derive(Debug)]&lt;/h1&gt;
         7792 &lt;p&gt;If you write a new type (say, a struct with a ton of fields), you can
         7793 &lt;code&gt;#[derive(Debug)]&lt;/code&gt; and Rust will know how to automatically print that
         7794 type's contents for debug output.  You no longer have to write a
         7795 special function that you must call in gdb by hand just to examine a
         7796 custom type.&lt;/p&gt;
         7797 &lt;h1&gt;Closures&lt;/h1&gt;
         7798 &lt;p&gt;No more passing function pointers and a &lt;code&gt;user_data&lt;/code&gt; by hand.&lt;/p&gt;
         7799 &lt;h1&gt;Conclusion&lt;/h1&gt;
         7800 &lt;p&gt;I haven't done the "&lt;a href="https://doc.rust-lang.org/book/second-edition/ch16-00-concurrency.html"&gt;fearless concurrency&lt;/a&gt;" bit yet, where the
         7801 compiler is able to prevent data races in threaded code.  I imagine it
         7802 being a game-changer for people who write concurrent code on an
         7803 everyday basis.&lt;/p&gt;
         7804 &lt;p&gt;C is an old language with primitive constructs and primitive tooling.
         7805 It was a good language for small uniprocessor Unix kernels that ran in
         7806 trusted, academic environments.  It's no longer a good language for
         7807 the software of today.&lt;/p&gt;
         7808 &lt;p&gt;Rust is not easy to learn, but I think it is completely worth it.
         7809 It's hard because it demands a lot from your understanding of the code
         7810 you want to write.  I think it's one of those languages that make you
         7811 a better programmer and that let you tackle more ambitious problems.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category></entry><entry><title>Writing a command-line program in Rust</title><link href="https://people.gnome.org/~federico/blog/writing-a-command-line-program-in-rust.html" rel="alternate"></link><published>2018-02-03T11:41:20-06:00</published><updated>2018-02-03T11:41:20-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-02-03:/~federico/blog/writing-a-command-line-program-in-rust.html</id><summary type="html">&lt;p&gt;As a library writer, it feels a bit strange, but refreshing, to write
         7812 a program that actually has a &lt;code&gt;main()&lt;/code&gt; function.&lt;/p&gt;
         7813 &lt;p&gt;My experience with Rust so far has been threefold:&lt;/p&gt;
         7814 &lt;ul&gt;
         7815 &lt;li&gt;
         7816 &lt;p&gt;Porting chunks of C to Rust for librsvg - this is all work on
         7817   librsvg's internals and no users are exposed …&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;As a library writer, it feels a bit strange, but refreshing, to write
         7818 a program that actually has a &lt;code&gt;main()&lt;/code&gt; function.&lt;/p&gt;
         7819 &lt;p&gt;My experience with Rust so far has been threefold:&lt;/p&gt;
         7820 &lt;ul&gt;
         7821 &lt;li&gt;
         7822 &lt;p&gt;Porting chunks of C to Rust for librsvg - this is all work on
         7823   librsvg's internals and no users are exposed to it directly.&lt;/p&gt;
         7824 &lt;/li&gt;
         7825 &lt;li&gt;
         7826 &lt;p&gt;Working on &lt;a href="https://github.com/nikomatsakis/gnome-class/"&gt;gnome-class&lt;/a&gt;, the procedural macro ("a little compiler")
         7827   to generate GObject boilerplate from Rust.  This feels like working
         7828   on the edge of the exotic; it is something that runs &lt;em&gt;in&lt;/em&gt; the Rust
         7829   compiler and spits code on behalf of the programmer.&lt;/p&gt;
         7830 &lt;/li&gt;
         7831 &lt;li&gt;
         7832 &lt;p&gt;A few patches to the &lt;a href="http://gtk-rs.org"&gt;gtk-rs&lt;/a&gt; ecosystem.  Again, work on the
         7833   internals, or something that feels library-like.&lt;/p&gt;
         7834 &lt;/li&gt;
         7835 &lt;/ul&gt;
         7836 &lt;p&gt;But other than toy programs to test things, I haven't written a
         7837 stand-alone tool until &lt;a href="https://people.gnome.org/~federico/blog/rsvg-bench.html"&gt;rsvg-bench&lt;/a&gt;.  It's quite a thrill to be able
         7838 to just &lt;em&gt;run the thing&lt;/em&gt; instead of waiting for other people to write
         7839 code to use it!&lt;/p&gt;
         7840 &lt;h1&gt;Parsing command-line arguments&lt;/h1&gt;
         7841 &lt;p&gt;There are quite a few Rust crates ("libraries") to parse command-line
         7842 arguments.  I read about &lt;a href="https://docs.rs/structopt-derive/0.1.5/structopt_derive/"&gt;structopt&lt;/a&gt; via &lt;a href="http://robert.ocallahan.org/2017/11/in-praise-of-rusts-structopt-for.html"&gt;Robert O'Callahan's
         7843 blog&lt;/a&gt;; structopt lets you define a &lt;code&gt;struct&lt;/code&gt; to hold the values of
         7844 your command-line options, and then you annotate the fields in that
         7845 &lt;code&gt;struct&lt;/code&gt; to indicate how they should be parsed from the command line.
         7846 It works via Rust's procedural macros.  Internally it generates stuff
         7847 for the &lt;a href="https://docs.rs/clap/2.29.2/clap/"&gt;clap&lt;/a&gt; crate, a well-established mechanism for dealing with
         7848 command-line options.&lt;/p&gt;
         7849 &lt;p&gt;And it is quite pleasant!  This is basically all I needed to do:&lt;/p&gt;
         7850 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[derive(StructOpt, Debug)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7851 &lt;span class="cp"&gt;#[structopt(name = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rsvg-bench&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;, about = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Benchmarking utility for librsvg.&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7852 &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Opt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7853 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[structopt(short = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;s&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;,&lt;/span&gt;
         7854 &lt;span class="cp"&gt;                long  = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sleep&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;,&lt;/span&gt;
         7855 &lt;span class="cp"&gt;                help  = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Number of seconds to sleep before starting to process SVGs&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;,&lt;/span&gt;
         7856 &lt;span class="cp"&gt;                default_value = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7857 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;sleep_secs&lt;/span&gt;: &lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7858 
         7859 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[structopt(short = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;p&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;,&lt;/span&gt;
         7860 &lt;span class="cp"&gt;                long  = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;num-parse&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;,&lt;/span&gt;
         7861 &lt;span class="cp"&gt;                help  = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Number of times to parse each file&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;,&lt;/span&gt;
         7862 &lt;span class="cp"&gt;                default_value = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;100&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7863 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;num_parse&lt;/span&gt;: &lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7864 
         7865 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[structopt(short = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;r&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;,&lt;/span&gt;
         7866 &lt;span class="cp"&gt;                long  = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;num-render&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;,&lt;/span&gt;
         7867 &lt;span class="cp"&gt;                help  = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Number of times to render each file&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;,&lt;/span&gt;
         7868 &lt;span class="cp"&gt;                default_value = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;100&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7869 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;num_render&lt;/span&gt;: &lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7870 
         7871 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[structopt(long = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pixbuf&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;,&lt;/span&gt;
         7872 &lt;span class="cp"&gt;                help = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Render to a GdkPixbuf instead of a Cairo image surface&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7873 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;render_to_pixbuf&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7874 
         7875 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[structopt(help = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Input files or directories&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;,&lt;/span&gt;
         7876 &lt;span class="cp"&gt;                parse(from_os_str))]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7877 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;: &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PathBuf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7878 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7879 
         7880 &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7881 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Opt&lt;/span&gt;::&lt;span class="n"&gt;from_args&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7882 
         7883 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7884 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;No input files or directories specified&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7885 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7886 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7887 
         7888 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7889 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7890 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7891 
         7892 &lt;p&gt;Each field in the &lt;code&gt;Opt&lt;/code&gt; struct above corresponds to one command-line
         7893 argument; each field has annotations for &lt;code&gt;structopt&lt;/code&gt; to generate the
         7894 appropriate code to parse each option.  For example, the
         7895 &lt;code&gt;render_to_pixbuf&lt;/code&gt; field has a long option name called &lt;code&gt;"pixbuf"&lt;/code&gt;;
         7896 that field will be set to &lt;code&gt;true&lt;/code&gt; if the &lt;code&gt;--pixbuf&lt;/code&gt; option gets passed
         7897 to rsvg-bench.&lt;/p&gt;
         7898 &lt;h1&gt;Handling errors&lt;/h1&gt;
         7899 &lt;p&gt;Command-line programs generally have the luxury of being able to just
         7900 exit as soon as they encounter an error.&lt;/p&gt;
         7901 &lt;p&gt;In C this is a bit cumbersome since you need to deal with &lt;em&gt;every&lt;/em&gt;
         7902 place that may return an error, find out what to print, and call
         7903 &lt;code&gt;exit(1)&lt;/code&gt; by hand or something.  If you miss a single place where an
         7904 error is returned, your program will keep running with an inconsistent
         7905 state.&lt;/p&gt;
         7906 &lt;p&gt;In languages with exception handling, it's a bit easier - a small
         7907 script can just let exceptions be thrown wherever, and if it catches
         7908 them at the toplevel, it can just print the exception and abort
         7909 gracefully.  However, these nonlocal jumps make me uncomfortable; I
         7910 think &lt;a href="http://joeduffyblog.com/2016/02/07/the-error-model/"&gt;exceptions are hard to reason about&lt;/a&gt;.&lt;/p&gt;
         7911 &lt;p&gt;Rust makes this easy: it forces you to handle every call that may
         7912 return an error, but it lets you bubble errors up easily, or handle
         7913 them in-place, or translate them to a higher-level error.&lt;/p&gt;
         7914 &lt;p&gt;In the Rust world the [&lt;code&gt;failure&lt;/code&gt;] crate is getting a lot of traction
         7915 as a convenient, modern way to handle errors.&lt;/p&gt;
         7916 &lt;p&gt;In rsvg-bench, errors can come from several places:&lt;/p&gt;
         7917 &lt;ul&gt;
         7918 &lt;li&gt;
         7919 &lt;p&gt;I/O errors when reading files and directories.&lt;/p&gt;
         7920 &lt;/li&gt;
         7921 &lt;li&gt;
         7922 &lt;p&gt;Errors from librsvg's parsing stage; you get a &lt;a href="https://developer.gnome.org/glib/stable/glib-Error-Reporting.html"&gt;GError&lt;/a&gt;.&lt;/p&gt;
         7923 &lt;/li&gt;
         7924 &lt;li&gt;
         7925 &lt;p&gt;Errors from the rendering stage.  This can be a Cairo error (a
         7926   &lt;a href="https://www.cairographics.org/manual/cairo-Error-handling.html"&gt;cairo_status_t&lt;/a&gt;), or a simple "something bad happened; can't
         7927   render" from librsvg's old convenience api in C.  Don't you hate it
         7928   when C code just gives up and returns NULL or a boolean false,
         7929   without any further details on &lt;em&gt;what&lt;/em&gt; went wrong?&lt;/p&gt;
         7930 &lt;/li&gt;
         7931 &lt;/ul&gt;
         7932 &lt;p&gt;For rsvg-bench, I just needed to be able to represent Cairo errors and
         7933 generic rendering errors.  Everything else, like an &lt;code&gt;io::Error&lt;/code&gt;, is
         7934 automatically wrapped by the &lt;code&gt;failure&lt;/code&gt; crate's mechanism.  I just
         7935 needed to do this:&lt;/p&gt;
         7936 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;failure&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7937 &lt;span class="cp"&gt;#[macro_use]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7938 &lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;failure_derive&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7939 
         7940 &lt;span class="cp"&gt;#[derive(Debug, Fail)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7941 &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;ProcessingError&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7942 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[fail(display = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Cairo error: {:?}&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;, status)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7943 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;CairoError&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7944 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;: &lt;span class="nc"&gt;cairo&lt;/span&gt;::&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7945 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7946 
         7947 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[fail(display = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Rendering error&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7948 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;RenderingError&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7949 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7950 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7951 
         7952 &lt;p&gt;Whenever the code gets a Cairo error, I can translate it to a
         7953 &lt;code&gt;ProcessingError::CairoError&lt;/code&gt; and bubble it up:&lt;/p&gt;
         7954 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;render_to_cairo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;rsvg&lt;/span&gt;::&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7955 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_dimensions&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7956 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;surface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cairo&lt;/span&gt;::&lt;span class="n"&gt;ImageSurface&lt;/span&gt;::&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cairo&lt;/span&gt;::&lt;span class="n"&gt;Format&lt;/span&gt;::&lt;span class="n"&gt;ARgb32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7957 &lt;span class="w"&gt;                                              &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7958 &lt;span class="w"&gt;                                              &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7959 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProcessingError&lt;/span&gt;::&lt;span class="n"&gt;CairoError&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;: &lt;span class="nc"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7960 
         7961 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7962 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7963 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7964 
         7965 &lt;p&gt;And when librsvg returns a "couldn't render" error, I translate that
         7966 to a &lt;code&gt;ProcessingError::RenderingError&lt;/code&gt;:&lt;/p&gt;
         7967 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;render_to_cairo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;rsvg&lt;/span&gt;::&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7968 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7969 
         7970 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cairo&lt;/span&gt;::&lt;span class="n"&gt;Context&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;surface&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7971 
         7972 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;render_cairo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7973 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7974 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7975 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;::&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ProcessingError&lt;/span&gt;::&lt;span class="n"&gt;RenderingError&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7976 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7977 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7978 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7979 
         7980 &lt;p&gt;Here, the &lt;code&gt;Ok()&lt;/code&gt; case of the &lt;code&gt;Result&lt;/code&gt; does not contain any value —
         7981 it's just &lt;code&gt;()&lt;/code&gt;, as the generated images are not stored anywhere: they
         7982 are just rendered to get some timings, not to be saved or anything.&lt;/p&gt;
         7983 &lt;h1&gt;Up to where do errors bubble?&lt;/h1&gt;
         7984 &lt;p&gt;This is the "do everything" function:&lt;/p&gt;
         7985 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;Opt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7986 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7987 
         7988 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7989 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;process_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7990 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7991 
         7992 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7993 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         7994 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         7995 
         7996 &lt;p&gt;For each path passed in the command line, process it.  The program
         7997 sees if the path corresponds to a directory, and it will scan it
         7998 recursively.  Or if the path is an SVG file, the program will load the
         7999 file and render it.&lt;/p&gt;
         8000 &lt;p&gt;Finally, &lt;code&gt;main()&lt;/code&gt; just has this:&lt;/p&gt;
         8001 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8002 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Opt&lt;/span&gt;::&lt;span class="n"&gt;from_args&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8003 
         8004 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8005 
         8006 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8007 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8008 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8009 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="fm"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8010 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;::&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8011 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8012 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8013 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8014 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8015 
         8016 &lt;p&gt;I.e. process command line arguments, run the whole thing, and print an
         8017 error if there was one.&lt;/p&gt;
         8018 &lt;p&gt;I really appreciate that most places that can return an error an just
         8019 put a &lt;code&gt;?&lt;/code&gt; for the error to bubble up.  This is much more legible than
         8020 in C, where every call must have an &lt;code&gt;if (something_bad_happened) {
         8021 deal_with_it; }&lt;/code&gt; after it... and Rust won't let me get away with
         8022 ignoring an error, but it makes it easy to actually deal with it properly.&lt;/p&gt;
         8023 &lt;h1&gt;Reading an SVG file quickly&lt;/h1&gt;
         8024 &lt;p&gt;Why, just &lt;code&gt;mmap()&lt;/code&gt; it and feed it to librsvg, to avoid buffer copies.
         8025 This is easy in Rust:&lt;/p&gt;
         8026 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;process_file&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;: &lt;span class="nb"&gt;AsRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;Opt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;: &lt;span class="nc"&gt;P&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8027 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;::&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8028 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mmap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MmapOptions&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8029 
         8030 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mmap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8031 
         8032 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rsvg&lt;/span&gt;::&lt;span class="n"&gt;Handle&lt;/span&gt;::&lt;span class="n"&gt;new_from_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8033 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8034 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8035 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8036 
         8037 &lt;p&gt;Many things can go wrong here:&lt;/p&gt;
         8038 &lt;ul&gt;
         8039 &lt;li&gt;&lt;code&gt;File::open()&lt;/code&gt; can return an io::Error.&lt;/li&gt;
         8040 &lt;li&gt;&lt;code&gt;MmapOptions::map()&lt;/code&gt; can return an io::Error from the &lt;code&gt;mmap(2)&lt;/code&gt;
         8041   system call, or from the &lt;code&gt;fstat(2)&lt;/code&gt; to read the file's size to map
         8042   it.&lt;/li&gt;
         8043 &lt;li&gt;&lt;code&gt;rsvg::Handle::new_from_data()&lt;/code&gt; can return a GError from parsing the
         8044   file.&lt;/li&gt;
         8045 &lt;/ul&gt;
         8046 &lt;p&gt;The little &lt;code&gt;?&lt;/code&gt; characters after each call that can return an error
         8047 mean, just give me back the result, or convert the error to a
         8048 &lt;code&gt;failure::Error&lt;/code&gt; that can be examined later.  This is beautifully
         8049 legible to me.&lt;/p&gt;
         8050 &lt;h1&gt;Summary&lt;/h1&gt;
         8051 &lt;p&gt;Writing command-line programs in Rust is fun!  It's nice to have
         8052 neurotically-safe scripts that one can trust in the future.&lt;/p&gt;
         8053 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/federico/rsvg-bench"&gt;Rsvg-bench is available here&lt;/a&gt;.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="librsvg"></category><category term="gnome"></category></entry><entry><title>rsvg-bench - a benchmark for librsvg</title><link href="https://people.gnome.org/~federico/blog/rsvg-bench.html" rel="alternate"></link><published>2018-02-02T16:10:34-06:00</published><updated>2018-02-02T16:10:34-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-02-02:/~federico/blog/rsvg-bench.html</id><summary type="html">&lt;p&gt;Librsvg 2.42.0 came out with a rather major performance regression
         8054 compared to 2.40.20: SVGs with many &lt;a href="https://www.w3.org/TR/SVG/coords.html#TransformAttribute"&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/a&gt;
         8055 attributes would slow it down.  It was fixed in 2.42.1.  We changed
         8056 from using a &lt;a href="https://github.com/lalrpop/lalrpop/issues/269"&gt;parser that would recompile regexes&lt;/a&gt; each time it was
         8057 called, to &lt;a href="https://github.com/servo/rust-cssparser"&gt;one …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;Librsvg 2.42.0 came out with a rather major performance regression
         8058 compared to 2.40.20: SVGs with many &lt;a href="https://www.w3.org/TR/SVG/coords.html#TransformAttribute"&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/a&gt;
         8059 attributes would slow it down.  It was fixed in 2.42.1.  We changed
         8060 from using a &lt;a href="https://github.com/lalrpop/lalrpop/issues/269"&gt;parser that would recompile regexes&lt;/a&gt; each time it was
         8061 called, to &lt;a href="https://github.com/servo/rust-cssparser"&gt;one that does simple string-based matching&lt;/a&gt; and
         8062 parsing.&lt;/p&gt;
         8063 &lt;p&gt;When I rewrote librsvg's parser for the &lt;code&gt;transform&lt;/code&gt; attribute from C
         8064 to Rust, I was just &lt;a href="https://people.gnome.org/~federico/news-2017-02.html#24"&gt;learning about writing parsers in Rust&lt;/a&gt;.
         8065 I chose &lt;a href="https://github.com/lalrpop/lalrpop"&gt;lalrpop&lt;/a&gt;, an excellent, Yacc-like parser generator for Rust.
         8066 It generates big, fast parsers, like what you would need for a
         8067 compiler — but it compiles the tokenizer's regexes each time you call
         8068 the parser.  This is not a problem for a compiler, where you basically
         8069 call the parser only once, but in librsvg, we may call it thousands of
         8070 times for an SVG file with thousands of objects with &lt;code&gt;transform&lt;/code&gt;
         8071 attributes.&lt;/p&gt;
         8072 &lt;p&gt;So, for 2.42.1 I rewrote that parser using
         8073 &lt;a href="https://github.com/servo/rust-cssparser"&gt;rust-cssparser&lt;/a&gt;.  This is what &lt;a href="https://servo.org/"&gt;Servo&lt;/a&gt; uses to
         8074 parse CSS data; it's a simple tokenizer with an API that knows about
         8075 CSS's particular constructs.  This is exactly the kind of data that
         8076 librsvg cares about.  Today all of librsvg's internal parsers work
         8077 using rust-cssparser, or they are so simple that they can be done with
         8078 Rust's normal functions to split strings and such.&lt;/p&gt;
         8079 &lt;h1&gt;Getting good timings&lt;/h1&gt;
         8080 &lt;p&gt;Librsvg ships with &lt;code&gt;rsvg-convert&lt;/code&gt;, a command-line utility that can
         8081 render an SVG file and write the output to a PNG.  While it would be
         8082 possible to get timings for SVG rendering by timing how long
         8083 &lt;code&gt;rsvg-convert&lt;/code&gt; takes to run, it's a bit clunky for that.  The process
         8084 startup adds noise to the timings, and it only handles one file at a
         8085 time.&lt;/p&gt;
         8086 &lt;p&gt;So, I've written &lt;a href="https://gitlab.gnome.org/federico/rsvg-bench"&gt;rsvg-bench&lt;/a&gt;, a small utility to get timings out of
         8087 librsvg.  I wanted a tool that:&lt;/p&gt;
         8088 &lt;ul&gt;
         8089 &lt;li&gt;
         8090 &lt;p&gt;Is able to process many SVG images with a single command.  For
         8091   example, this lets us answer a question like, "how long does version
         8092   N of librsvg take to render a directory full of SVG icons?" — which
         8093   is important for the performance of an application chooser.&lt;/p&gt;
         8094 &lt;/li&gt;
         8095 &lt;li&gt;
         8096 &lt;p&gt;Is able to &lt;em&gt;repeatedly&lt;/em&gt; process SVG files, for example, "render this
         8097   SVG 1000 times in a row".  This is useful to get accurate timings,
         8098   as a single render may only take a few microseconds and may be hard
         8099   to measure.  It also helps with running profilers, as they will be
         8100   able to get more useful samples if the SVG rendering process runs
         8101   repeatedly for a long time.&lt;/p&gt;
         8102 &lt;/li&gt;
         8103 &lt;li&gt;
         8104 &lt;p&gt;Exercises librsvg's major code paths for parsing and rendering
         8105   separately.  For example, librsvg uses different parts of the XML
         8106   parser depending on whether it is being pushed data, vs. being asked
         8107   to pull data from a stream.  Also, we may only want to benchmark the
         8108   parser but not the renderer; or we may want to parse SVGs only once
         8109   but render them many times after that.&lt;/p&gt;
         8110 &lt;/li&gt;
         8111 &lt;li&gt;
         8112 &lt;p&gt;Is aware of librsvg's peculiarities, such as the extra pass to
         8113   convert a Cairo image surface to a GdkPixbuf when one uses the
         8114   convenience function &lt;code&gt;rsvg_handle_get_pixbuf()&lt;/code&gt;.&lt;/p&gt;
         8115 &lt;/li&gt;
         8116 &lt;/ul&gt;
         8117 &lt;p&gt;Currently rsvg-bench supports all of that.&lt;/p&gt;
         8118 &lt;h1&gt;An initial benchmark&lt;/h1&gt;
         8119 &lt;p&gt;I ran this&lt;/p&gt;
         8120 &lt;p&gt;&lt;code&gt;/usr/bin/time rsvg-bench -p 1 -r 1 /usr/share/icons&lt;/code&gt;&lt;/p&gt;
         8121 &lt;p&gt;to cause every SVG icon in &lt;code&gt;/usr/share/icons&lt;/code&gt; to be parsed once, and
         8122 rendered once (i.e. just render every file sequentially).  I did this
         8123 for librsvg 2.40.20 (C only), and 2.42.{0, 1, 2} (C and Rust).  There
         8124 are 5522 SVG files in there.  The timings look like this:&lt;/p&gt;
         8125 &lt;table&gt;
         8126 &lt;thead&gt;
         8127 &lt;tr&gt;
         8128 &lt;th&gt;version&lt;/th&gt;
         8129 &lt;th&gt;time (sec)&lt;/th&gt;
         8130 &lt;/tr&gt;
         8131 &lt;/thead&gt;
         8132 &lt;tbody&gt;
         8133 &lt;tr&gt;
         8134 &lt;td&gt;2.40.20&lt;/td&gt;
         8135 &lt;td&gt;95.54&lt;/td&gt;
         8136 &lt;/tr&gt;
         8137 &lt;tr&gt;
         8138 &lt;td&gt;2.42.0&lt;/td&gt;
         8139 &lt;td&gt;209.50&lt;/td&gt;
         8140 &lt;/tr&gt;
         8141 &lt;tr&gt;
         8142 &lt;td&gt;2.42.1&lt;/td&gt;
         8143 &lt;td&gt;97.18&lt;/td&gt;
         8144 &lt;/tr&gt;
         8145 &lt;tr&gt;
         8146 &lt;td&gt;2.42.2&lt;/td&gt;
         8147 &lt;td&gt;95.89&lt;/td&gt;
         8148 &lt;/tr&gt;
         8149 &lt;/tbody&gt;
         8150 &lt;/table&gt;
         8151 &lt;p&gt;&lt;img alt="Bar chart of timings" src="https://people.gnome.org/~federico/blog/images/rsvg-bench-timings.png"&gt;&lt;/p&gt;
         8152 &lt;p&gt;So, 2.42.0 was over twice as slow as the C-only version, due to the
         8153 parsing problems.  But now, 2.42.2 is practically just as fast as the
         8154 C only version.  What made this possible?&lt;/p&gt;
         8155 &lt;ul&gt;
         8156 &lt;li&gt;2.40.20 - the old C-only version&lt;/li&gt;
         8157 &lt;li&gt;2.42.0 - C + Rust, with a lalrpop parser for the &lt;code&gt;transform&lt;/code&gt; attribute&lt;/li&gt;
         8158 &lt;li&gt;2.42.1 - Servo's cssparser for the &lt;code&gt;transform&lt;/code&gt; attribute&lt;/li&gt;
         8159 &lt;li&gt;2.42.2 - removed most C-to-Rust string copies during parsing&lt;/li&gt;
         8160 &lt;/ul&gt;
         8161 &lt;p&gt;I have started taking profiles of rsvg-bench runs with sysprof, and
         8162 there are some improvements worth making.  Expect news soon!&lt;/p&gt;
         8163 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/federico/rsvg-bench"&gt;Rsvg-bench is available in Gnome's gitlab instance&lt;/a&gt;.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category><category term="rust"></category><category term="performance"></category></entry><entry><title>Help needed for librsvg 2.42.1</title><link href="https://people.gnome.org/~federico/blog/help-needed-for-librsvg-2421.html" rel="alternate"></link><published>2018-01-16T11:01:05-06:00</published><updated>2018-01-16T11:01:05-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-01-16:/~federico/blog/help-needed-for-librsvg-2421.html</id><summary type="html">&lt;p&gt;Would you like to help fix a couple of bugs in &lt;a href="https://gitlab.gnome.org/GNOME/librsvg"&gt;librsvg&lt;/a&gt;, in
         8164 preparation for the 2.42.1 release?&lt;/p&gt;
         8165 &lt;p&gt;I have prepared a list of bugs which I'd like to be fixed in the
         8166 &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues?milestone_title=2.42.1"&gt;2.42.1 milestone&lt;/a&gt;.  Two of them are assigned to myself, as
         8167 I'm already working …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Would you like to help fix a couple of bugs in &lt;a href="https://gitlab.gnome.org/GNOME/librsvg"&gt;librsvg&lt;/a&gt;, in
         8168 preparation for the 2.42.1 release?&lt;/p&gt;
         8169 &lt;p&gt;I have prepared a list of bugs which I'd like to be fixed in the
         8170 &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues?milestone_title=2.42.1"&gt;2.42.1 milestone&lt;/a&gt;.  Two of them are assigned to myself, as
         8171 I'm already working on them.&lt;/p&gt;
         8172 &lt;p&gt;There are two other bugs which I'd love someone to look at.  Neither
         8173 of these requires deep knowledge of librsvg, just some debugging and
         8174 code-writing:&lt;/p&gt;
         8175 &lt;ul&gt;
         8176 &lt;li&gt;
         8177 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/141"&gt;Bug 141&lt;/a&gt; - GNOME's thumbnailing machinery creates an icon which has
         8178   the wrong fill:  it's an image of a builder's trowel, and the inside
         8179   is filled black instead of with a nice gradient.  This is the only
         8180   place in librsvg where a &lt;code&gt;cairo_surface_t&lt;/code&gt; is converted to a
         8181   &lt;code&gt;GdkPixbuf&lt;/code&gt;; this involves unpremultiplying the alpha channel.
         8182   Maybe the relevant function is buggy?&lt;/p&gt;
         8183 &lt;/li&gt;
         8184 &lt;li&gt;
         8185 &lt;p&gt;&lt;a href="https://gitlab.gnome.org/GNOME/librsvg/issues/136"&gt;Bug 136&lt;/a&gt;: The &lt;code&gt;stroke-dasharray&lt;/code&gt; attribute in SVG elements is
         8186   parsed incorrectly.  It is a list of CSS length values, separated by
         8187   commas or spaces.  Currently librsvg uses a shitty parser based on
         8188   &lt;code&gt;g_strsplit()&lt;/code&gt; only for commas; it doesn't allow just a
         8189   space-separated list.  Then, it uses &lt;code&gt;g_ascii_strtod()&lt;/code&gt; to parse
         8190   plain numbers; it doesn't support CSS lengths generically.  This
         8191   parser needs to be rewritten in Rust; we already have machinery
         8192   there to parse CSS length values properly.&lt;/p&gt;
         8193 &lt;/li&gt;
         8194 &lt;/ul&gt;
         8195 &lt;p&gt;Feel free to &lt;a href="federico@gnome.org"&gt;contact me&lt;/a&gt; by mail, or write something in the
         8196 bugs themselves, if you would like to work on them.  I'll happily
         8197 guide you through the code :)&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category></entry><entry><title>Librsvg gets Continuous Integration</title><link href="https://people.gnome.org/~federico/blog/librsvg-gets-continuous-integration.html" rel="alternate"></link><published>2018-01-12T14:04:20-06:00</published><updated>2018-01-12T14:04:20-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-01-12:/~federico/blog/librsvg-gets-continuous-integration.html</id><summary type="html">&lt;p&gt;One nice thing about &lt;code&gt;gitlab.gnome.org&lt;/code&gt; is that we can now have
         8198 Continuous Integration (CI) enabled for projects there.  After every
         8199 commit, the CI machinery can build the project, run the tests, and
         8200 tell you if something goes wrong.&lt;/p&gt;
         8201 &lt;p&gt;&lt;a href="https://mail.gnome.org/archives/desktop-devel-list/2018-January/msg00008.html"&gt;Carlos Soriano posted&lt;/a&gt; a "tips of the
         8202 week" mail to …&lt;/p&gt;</summary><content type="html">&lt;p&gt;One nice thing about &lt;code&gt;gitlab.gnome.org&lt;/code&gt; is that we can now have
         8203 Continuous Integration (CI) enabled for projects there.  After every
         8204 commit, the CI machinery can build the project, run the tests, and
         8205 tell you if something goes wrong.&lt;/p&gt;
         8206 &lt;p&gt;&lt;a href="https://mail.gnome.org/archives/desktop-devel-list/2018-January/msg00008.html"&gt;Carlos Soriano posted&lt;/a&gt; a "tips of the
         8207 week" mail to desktop-devel-list, and a link to how Nautilus
         8208 implements CI in Gitlab.  It turns out that it's reasonably easy to
         8209 set up:  you just create a &lt;a href="https://docs.gitlab.com/ce/ci/yaml/README.html"&gt;&lt;code&gt;.gitlab-ci.yml&lt;/code&gt;&lt;/a&gt; file in the
         8210 toplevel of your project, and that has the configuration for what to
         8211 run on every commit.&lt;/p&gt;
         8212 &lt;p&gt;Of course instead of reading the manual, I copied-and-pasted the file
         8213 from Nautilus and just changed some things in it.  &lt;a href="https://gitlab.gnome.org/ci/lint"&gt;There is a .yml
         8214 linter&lt;/a&gt; so you can at least check the syntax before pushing a
         8215 full job.&lt;/p&gt;
         8216 &lt;p&gt;Then I read &lt;a href="https://mail.gnome.org/archives/desktop-devel-list/2018-January/msg00010.html"&gt;Robert Ancell's reply&lt;/a&gt; about how simple-scan
         8217 builds its CI jobs on both Fedora and Ubuntu... and then the
         8218 realization hit me:&lt;/p&gt;
         8219 &lt;p&gt;&lt;em&gt;This lets me CI librsvg on multiple distros at once.&lt;/em&gt;  I've had
         8220 trouble with slight differences in fontconfig/freetype in the past,
         8221 and this would let me catch them early.&lt;/p&gt;
         8222 &lt;p&gt;However, people on IRC advised against this, as &lt;strong&gt;we need more
         8223 hardware&lt;/strong&gt; to run CI on a large scale.&lt;/p&gt;
         8224 &lt;p&gt;Linux distros have a vested interest in getting code out of gnome.org
         8225 that works well.  Surely they can give us some hardware?&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gitlab"></category></entry><entry><title>Loving Gitlab.gnome.org, and getting notifications</title><link href="https://people.gnome.org/~federico/blog/loving-gitlab.html" rel="alternate"></link><published>2018-01-08T11:45:01-06:00</published><updated>2018-01-08T11:45:01-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2018-01-08:/~federico/blog/loving-gitlab.html</id><summary type="html">&lt;p&gt;I'm loving &lt;a href="https://gitlab.gnome.org"&gt;&lt;code&gt;gitlab.gnome.org&lt;/code&gt;&lt;/a&gt;.  It has been only a couple of
         8226 weeks since &lt;a href="https://people.gnome.org/~federico/blog/librsvg-moves-to-gitlab.html"&gt;librsvg moved to gitlab&lt;/a&gt;, and I've
         8227 already received and merged &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/merge_requests?scope=all&amp;amp;utf8=%E2%9C%93&amp;amp;state=merged"&gt;two merge requests&lt;/a&gt;.  (Isn't it a bit
         8228 weird that Github uses "pull request" and Everyone(tm) knows the PR
         8229 acronym, but Gitlab uses "merge request"?)&lt;/p&gt;
         8230 &lt;h1&gt;Notifications …&lt;/h1&gt;</summary><content type="html">&lt;p&gt;I'm loving &lt;a href="https://gitlab.gnome.org"&gt;&lt;code&gt;gitlab.gnome.org&lt;/code&gt;&lt;/a&gt;.  It has been only a couple of
         8231 weeks since &lt;a href="https://people.gnome.org/~federico/blog/librsvg-moves-to-gitlab.html"&gt;librsvg moved to gitlab&lt;/a&gt;, and I've
         8232 already received and merged &lt;a href="https://gitlab.gnome.org/GNOME/librsvg/merge_requests?scope=all&amp;amp;utf8=%E2%9C%93&amp;amp;state=merged"&gt;two merge requests&lt;/a&gt;.  (Isn't it a bit
         8233 weird that Github uses "pull request" and Everyone(tm) knows the PR
         8234 acronym, but Gitlab uses "merge request"?)&lt;/p&gt;
         8235 &lt;h1&gt;Notifications about merge requests&lt;/h1&gt;
         8236 &lt;p&gt;One thing to note if your GNOME project has moved to Gitlab:  &lt;strong&gt;if you
         8237 want to get notified of incoming merge requests&lt;/strong&gt;, you need
         8238 to tell Gitlab that you want to "&lt;strong&gt;Watch&lt;/strong&gt;" that project, instead of
         8239 using one of the default notification settings.  &lt;a href="https://gitlab.gnome.org/GNOMEInfrastructure/GitLab/issues/95"&gt;Thanks to Carlos
         8240 Soriano&lt;/a&gt; for making me aware of this.&lt;/p&gt;
         8241 &lt;h1&gt;Notifications from Github's mirror&lt;/h1&gt;
         8242 &lt;p&gt;The &lt;a href="https://github.com/GNOME/"&gt;github&lt;/a&gt; mirror of git.gnome.org is configured so that pull
         8243 requests are &lt;a href="https://wiki.gnome.org/Sysadmin/GitHub"&gt;automatically closed&lt;/a&gt;, since currently there
         8244 is no way to notify the upstream maintainers when someone creates a
         8245 pull request in the mirror (this is super-unfriendly by default, but
         8246 at least submitters get notified that their PR would not be looked at
         8247 by anyone, by default).&lt;/p&gt;
         8248 &lt;p&gt;If you have a Github account, you can Watch the project in question to
         8249 get notified — the bot will close the pull request, but you will get
         8250 notified, and then you can check it by hand, review it as appropriate,
         8251 or redirect the submitter to gitlab.gnome.org instead.&lt;/p&gt;</content><category term="misc"></category><category term="gnome"></category><category term="gitlab"></category></entry><entry><title>Librsvg 2.40.20 is released</title><link href="https://people.gnome.org/~federico/blog/librsvg-24020-is-released.html" rel="alternate"></link><published>2017-12-15T18:31:50-06:00</published><updated>2017-12-15T18:31:50-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-12-15:/~federico/blog/librsvg-24020-is-released.html</id><summary type="html">&lt;p&gt;Today I released &lt;a href="https://ftp.gnome.org/pub/GNOME/sources/librsvg/2.40/"&gt;librsvg 2.40.20&lt;/a&gt;.  This will be the
         8252 &lt;strong&gt;last release&lt;/strong&gt; in the 2.40.x series, which is deprecated effectively
         8253 immediately.&lt;/p&gt;
         8254 &lt;p&gt;People and distros are &lt;strong&gt;strongly encouraged&lt;/strong&gt; to switch to
         8255 &lt;a href="https://ftp.gnome.org/pub/GNOME/sources/librsvg/2.41/"&gt;librsvg 2.41.x&lt;/a&gt; as soon as possible.  This is the version that is
         8256 implemented in a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today I released &lt;a href="https://ftp.gnome.org/pub/GNOME/sources/librsvg/2.40/"&gt;librsvg 2.40.20&lt;/a&gt;.  This will be the
         8257 &lt;strong&gt;last release&lt;/strong&gt; in the 2.40.x series, which is deprecated effectively
         8258 immediately.&lt;/p&gt;
         8259 &lt;p&gt;People and distros are &lt;strong&gt;strongly encouraged&lt;/strong&gt; to switch to
         8260 &lt;a href="https://ftp.gnome.org/pub/GNOME/sources/librsvg/2.41/"&gt;librsvg 2.41.x&lt;/a&gt; as soon as possible.  This is the version that is
         8261 implemented in a mixture of C and Rust.  It is 100% API and ABI
         8262 compatible with 2.40.x, so it is a drop-in replacement for it.  If you
         8263 or your distro can compile Firefox 57, you can probably build
         8264 librsvg-2.41.x without problems.&lt;/p&gt;
         8265 &lt;h1&gt;Some statistics&lt;/h1&gt;
         8266 &lt;p&gt;Here are a few runs of &lt;a href="https://github.com/cgag/loc"&gt;loc&lt;/a&gt; — a tool to count lines of code —
         8267 when run on librsvg.  The output is trimmed by hand to only include C
         8268 and Rust files.&lt;/p&gt;
         8269 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c"&gt;This is 2&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;40&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;20:&lt;/span&gt;
         8270 &lt;span class="nb"&gt;-------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         8271 &lt;span class="c"&gt; Language      Files   Lines   Blank   Comment    Code&lt;/span&gt;
         8272 &lt;span class="nb"&gt;-------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         8273 &lt;span class="c"&gt; C                41   20972    3438      2100   15434&lt;/span&gt;
         8274 &lt;span class="c"&gt; C/C&lt;/span&gt;&lt;span class="nb"&gt;++&lt;/span&gt;&lt;span class="c"&gt; Header     27    2377     452       625    1300&lt;/span&gt;
         8275 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8276 
         8277 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c"&gt;This is 2&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;41&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;latest (the master branch):&lt;/span&gt;
         8278 &lt;span class="nb"&gt;-------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         8279 &lt;span class="c"&gt; Language      Files   Lines   Blank   Comment    Code&lt;/span&gt;
         8280 &lt;span class="nb"&gt;-------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         8281 &lt;span class="c"&gt; C                34   17253    3024      1892   12337&lt;/span&gt;
         8282 &lt;span class="c"&gt; C/C&lt;/span&gt;&lt;span class="nb"&gt;++&lt;/span&gt;&lt;span class="c"&gt; Header     23    2327     501       624    1202&lt;/span&gt;
         8283 &lt;span class="c"&gt; Rust             38   11254    1873       675    8706&lt;/span&gt;
         8284 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8285 
         8286 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c"&gt;And this is 2&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;41&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;latest *without unit tests*&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt; &lt;/span&gt;
         8287 &lt;span class="c"&gt;just &amp;quot;real source code&amp;quot;:&lt;/span&gt;
         8288 &lt;span class="nb"&gt;-------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         8289 &lt;span class="c"&gt; Language      Files   Lines   Blank   Comment    Code&lt;/span&gt;
         8290 &lt;span class="nb"&gt;-------------------------------------------------------&lt;/span&gt;&lt;span class="c"&gt;&lt;/span&gt;
         8291 &lt;span class="c"&gt; C                34   17253    3024      1892   12337&lt;/span&gt;
         8292 &lt;span class="c"&gt; C/C&lt;/span&gt;&lt;span class="nb"&gt;++&lt;/span&gt;&lt;span class="c"&gt; Header     23    2327     501       624    1202&lt;/span&gt;
         8293 &lt;span class="c"&gt; Rust             38    9340    1513       610    7217&lt;/span&gt;
         8294 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8295 
         8296 &lt;h2&gt;Summary&lt;/h2&gt;
         8297 &lt;p&gt;Not counting blank lines nor comments:&lt;/p&gt;
         8298 &lt;ul&gt;
         8299 &lt;li&gt;
         8300 &lt;p&gt;The C-only version has 16734 lines of C code.&lt;/p&gt;
         8301 &lt;/li&gt;
         8302 &lt;li&gt;
         8303 &lt;p&gt;The C-only version has &lt;strong&gt;no unit tests&lt;/strong&gt;, just some integration tests.&lt;/p&gt;
         8304 &lt;/li&gt;
         8305 &lt;li&gt;
         8306 &lt;p&gt;The Rust-and-C version has 13539 lines of C code, 7217 lines of Rust
         8307   code, and 1489 lines of unit tests in Rust.&lt;/p&gt;
         8308 &lt;/li&gt;
         8309 &lt;/ul&gt;
         8310 &lt;p&gt;As for the integration tests:&lt;/p&gt;
         8311 &lt;ul&gt;
         8312 &lt;li&gt;
         8313 &lt;p&gt;The C-only version has 64 integration tests.&lt;/p&gt;
         8314 &lt;/li&gt;
         8315 &lt;li&gt;
         8316 &lt;p&gt;The Rust-and-C version has 130 integration tests.&lt;/p&gt;
         8317 &lt;/li&gt;
         8318 &lt;/ul&gt;
         8319 &lt;p&gt;The Rust-and-C version supports a few more SVG features, and it is A
         8320 LOT more robust and spec-compliant with the SVG features that were
         8321 supported in the C-only version.&lt;/p&gt;
         8322 &lt;p&gt;The C sources in librsvg are shrinking steadily.  It would be
         8323 incredibly awesome if someone could run some &lt;code&gt;git filter-branch&lt;/code&gt; magic
         8324 with the &lt;a href="https://github.com/cgag/loc"&gt;&lt;code&gt;loc&lt;/code&gt;&lt;/a&gt; tool and generate some pretty graphs of source
         8325 lines vs. commits over time.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category><category term="rust"></category></entry><entry><title>Librsvg moves to Gitlab</title><link href="https://people.gnome.org/~federico/blog/librsvg-moves-to-gitlab.html" rel="alternate"></link><published>2017-12-13T14:09:32-06:00</published><updated>2017-12-13T14:09:32-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-12-13:/~federico/blog/librsvg-moves-to-gitlab.html</id><summary type="html">&lt;p&gt;Librsvg now lives in GNOME's &lt;a href="https://gitlab.gnome.org/"&gt;Gitlab&lt;/a&gt; instance.  You can
         8326 access it &lt;a href="https://gitlab.gnome.org/GNOME/librsvg"&gt;here&lt;/a&gt;.&lt;/p&gt;
         8327 &lt;p&gt;Gitlab allows workflows similar to Github:  you can create an account
         8328 there, fork the librsvg repository, file bug reports, create merge
         8329 requests...  Hopefully this will make it nicer for contributors.&lt;/p&gt;
         8330 &lt;p&gt;In the meantime, feel free to &lt;a href="https://gitlab.gnome.org/GNOME/librsvg"&gt;take a …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;Librsvg now lives in GNOME's &lt;a href="https://gitlab.gnome.org/"&gt;Gitlab&lt;/a&gt; instance.  You can
         8331 access it &lt;a href="https://gitlab.gnome.org/GNOME/librsvg"&gt;here&lt;/a&gt;.&lt;/p&gt;
         8332 &lt;p&gt;Gitlab allows workflows similar to Github:  you can create an account
         8333 there, fork the librsvg repository, file bug reports, create merge
         8334 requests...  Hopefully this will make it nicer for contributors.&lt;/p&gt;
         8335 &lt;p&gt;In the meantime, feel free to &lt;a href="https://gitlab.gnome.org/GNOME/librsvg"&gt;take a look&lt;/a&gt;!&lt;/p&gt;
         8336 &lt;p&gt;This is a huge improvement for GNOME's development infrastructure.
         8337 Thanks to Carlos Soriano, Andrea Veri, Philip Chimento, Alberto Ruiz,
         8338 and all the people that made the move to Gitlab possible.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="gnome"></category></entry><entry><title>A mini-rant on the lack of string slices in C</title><link href="https://people.gnome.org/~federico/blog/rant-on-string-slices.html" rel="alternate"></link><published>2017-12-07T09:54:14-06:00</published><updated>2017-12-07T09:54:14-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-12-07:/~federico/blog/rant-on-string-slices.html</id><summary type="html">&lt;p&gt;Porting of librsvg to Rust goes on.  Yesterday I started porting the
         8339 C code that implements SVG's &lt;code&gt;&amp;lt;text&amp;gt;&lt;/code&gt; family of elements.  I have also
         8340 been replacing the little parsers in librsvg with Rust code.&lt;/p&gt;
         8341 &lt;p&gt;And these days, the lack of string slices in C is bothering me &lt;em&gt;a
         8342 lot&lt;/em&gt;.&lt;/p&gt;
         8343 &lt;h1&gt;What …&lt;/h1&gt;</summary><content type="html">&lt;p&gt;Porting of librsvg to Rust goes on.  Yesterday I started porting the
         8344 C code that implements SVG's &lt;code&gt;&amp;lt;text&amp;gt;&lt;/code&gt; family of elements.  I have also
         8345 been replacing the little parsers in librsvg with Rust code.&lt;/p&gt;
         8346 &lt;p&gt;And these days, the lack of string slices in C is bothering me &lt;em&gt;a
         8347 lot&lt;/em&gt;.&lt;/p&gt;
         8348 &lt;h1&gt;What if...&lt;/h1&gt;
         8349 &lt;p&gt;It feels like it should be easy to just write something like&lt;/p&gt;
         8350 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         8351     &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8352     &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8353 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;StringSlice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8354 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8355 
         8356 &lt;p&gt;And then a whole family of functions.  The starting point, where you
         8357 slice a whole string:&lt;/p&gt;
         8358 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;StringSlice&lt;/span&gt;
         8359 &lt;span class="nf"&gt;make_slice_from_string&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         8360 &lt;span class="p"&gt;{&lt;/span&gt;
         8361     &lt;span class="n"&gt;StringSlice&lt;/span&gt; &lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8362 
         8363     &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         8364 
         8365     &lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8366     &lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         8367     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8368 &lt;span class="p"&gt;}&lt;/span&gt;
         8369 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8370 
         8371 &lt;p&gt;But that wouldn't keep track of the lifetime of the original string.
         8372 Okay, this is C, so you are used to keeping track of that yourself.&lt;/p&gt;
         8373 &lt;p&gt;Onwards.  Substrings?&lt;/p&gt;
         8374 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;StringSlice&lt;/span&gt;
         8375 &lt;span class="nf"&gt;make_sub_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StringSlice&lt;/span&gt; &lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         8376 &lt;span class="p"&gt;{&lt;/span&gt;
         8377     &lt;span class="n"&gt;StringSlice&lt;/span&gt; &lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8378 
         8379     &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         8380     &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="cm"&gt;/* Not &amp;quot;start + len &amp;lt;= slice.len&amp;quot; or it can overflow. */&lt;/span&gt;
         8381                                         &lt;span class="cm"&gt;/* The subtraction can&amp;#39;t underflow because of the previous assert */&lt;/span&gt;
         8382     &lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8383     &lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8384     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8385 &lt;span class="p"&gt;}&lt;/span&gt;
         8386 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8387 
         8388 &lt;p&gt;Then you could write a million wrappers for &lt;code&gt;g_strsplit()&lt;/code&gt; and
         8389 friends, or equivalents to them, to give you slices instead of C
         8390 strings.  But then:&lt;/p&gt;
         8391 &lt;ul&gt;
         8392 &lt;li&gt;
         8393 &lt;p&gt;You have to keep track of lifetimes yourself.&lt;/p&gt;
         8394 &lt;/li&gt;
         8395 &lt;li&gt;
         8396 &lt;p&gt;You have to wrap every function that returns a plain "&lt;code&gt;char *&lt;/code&gt;"...&lt;/p&gt;
         8397 &lt;/li&gt;
         8398 &lt;li&gt;
         8399 &lt;p&gt;... and every function that takes a plain "&lt;code&gt;char *&lt;/code&gt;" as an argument,
         8400   without a length parameter, because...&lt;/p&gt;
         8401 &lt;/li&gt;
         8402 &lt;li&gt;
         8403 &lt;p&gt;You &lt;strong&gt;CANNOT&lt;/strong&gt; take &lt;code&gt;slice.ptr&lt;/code&gt; and pass it to a function that just
         8404   expects a plain "&lt;code&gt;char *&lt;/code&gt;", because your slice does not include a
         8405   nul terminator (the &lt;code&gt;'\0&lt;/code&gt; byte at the end of a C string).  This is
         8406   what kills the whole plan.&lt;/p&gt;
         8407 &lt;/li&gt;
         8408 &lt;/ul&gt;
         8409 &lt;p&gt;Even if you had a helper library that implements C string slices
         8410 like that, you would have a mismatch every time you needed to call a C
         8411 function that expects a conventional C string in the form of a
         8412 "&lt;code&gt;char *&lt;/code&gt;".  &lt;em&gt;You need to put a nul terminator somewhere&lt;/em&gt;, and if you
         8413 only have a slice, you need to &lt;em&gt;allocate memory&lt;/em&gt;, copy the slice into
         8414 it, and slap a 0 byte at the end.  &lt;em&gt;Then&lt;/em&gt; you can pass that to a
         8415 function that expects a normal C string.&lt;/p&gt;
         8416 &lt;p&gt;There is hacky C code that needs to pass a substring to another
         8417 function, so it &lt;em&gt;overwrites the byte after the substring with a 0&lt;/em&gt;,
         8418 passes the substring, and &lt;em&gt;overwrites the byte back&lt;/em&gt;.  This is
         8419 horrible, and doesn't work with strings that live in read-only
         8420 memory.  But that's the best that C lets you do.&lt;/p&gt;
         8421 &lt;p&gt;I'm very happy with string slices in Rust, which work exactly like the
         8422 &lt;code&gt;StringSlice&lt;/code&gt; above, but &lt;code&gt;&amp;amp;str&lt;/code&gt; is actually at the language level and
         8423 everything knows how to handle it.&lt;/p&gt;
         8424 &lt;p&gt;The &lt;code&gt;glib-rs&lt;/code&gt; crate has conversion traits to go from Rust strings or
         8425 slices into C, and vice-versa.  We alredy saw some of those in the
         8426 blog post about &lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html#pointer-types"&gt;conversions in Glib-rs&lt;/a&gt;.&lt;/p&gt;
         8427 &lt;h1&gt;Sizes of things&lt;/h1&gt;
         8428 &lt;p&gt;Rust uses &lt;code&gt;usize&lt;/code&gt; to specify the size of things; it's an unsigned
         8429 integer; 32 bits on 32-bit machines, and 64 bits on 64-bit machines;
         8430 it's like C's &lt;code&gt;size_t&lt;/code&gt;.&lt;/p&gt;
         8431 &lt;p&gt;In the Glib/C world, we have an assortment of types to represent the
         8432 sizes of things:&lt;/p&gt;
         8433 &lt;ul&gt;
         8434 &lt;li&gt;
         8435 &lt;p&gt;&lt;code&gt;gsize&lt;/code&gt;, the same as &lt;code&gt;size_t&lt;/code&gt;.  This is an unsigned integer; it's okay.&lt;/p&gt;
         8436 &lt;/li&gt;
         8437 &lt;li&gt;
         8438 &lt;p&gt;&lt;code&gt;gssize&lt;/code&gt;, a signed integer of the same size as &lt;code&gt;gsize&lt;/code&gt;.  This is
         8439   okay if used to represent a negative offset, and &lt;em&gt;really funky&lt;/em&gt; in
         8440   the Glib functions like
         8441   &lt;code&gt;g_string_new_len (const char *str, gssize len)&lt;/code&gt;, where &lt;code&gt;len == -1&lt;/code&gt;
         8442   means "call &lt;code&gt;strlen(str)&lt;/code&gt; for me because I'm too lazy to compute the
         8443   length myself".&lt;/p&gt;
         8444 &lt;/li&gt;
         8445 &lt;li&gt;
         8446 &lt;p&gt;&lt;code&gt;int&lt;/code&gt; - broken, as in libxml2, but we can't change the API.  On
         8447   64-bit machines, an &lt;code&gt;int&lt;/code&gt; to specify a length means you can't pass
         8448   objects bigger than 2 GB.&lt;/p&gt;
         8449 &lt;/li&gt;
         8450 &lt;li&gt;
         8451 &lt;p&gt;&lt;code&gt;long&lt;/code&gt; - marginally better than &lt;code&gt;int&lt;/code&gt;, since it has a better chance
         8452   of actually being the same size as &lt;code&gt;size_t&lt;/code&gt;, but still funky.
         8453   Probably okay for negative offsets; problematic for sizes which
         8454   should really be unsigned.&lt;/p&gt;
         8455 &lt;/li&gt;
         8456 &lt;li&gt;
         8457 &lt;p&gt;etc.&lt;/p&gt;
         8458 &lt;/li&gt;
         8459 &lt;/ul&gt;
         8460 &lt;p&gt;I'm not sure how old &lt;code&gt;size_t&lt;/code&gt; is in the C standard library, but it
         8461 can't have been there since the beginning of time &amp;mdash; otherwise
         8462 people wouldn't have been using &lt;code&gt;int&lt;/code&gt; to specify the sizes of things.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="librsvg"></category></entry><entry><title>Code Hospitality</title><link href="https://people.gnome.org/~federico/blog/code-hospitality.html" rel="alternate"></link><published>2017-11-17T14:21:04-06:00</published><updated>2017-11-17T14:21:06-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-11-17:/~federico/blog/code-hospitality.html</id><summary type="html">&lt;p&gt;Recently on the &lt;a href="http://www.greaterthancode.com/"&gt;Greater than Code podcast&lt;/a&gt; there was an episode
         8463 called "&lt;a href="http://www.greaterthancode.com/podcast/054-code-hospitality-with-nadia-odunayo/"&gt;Code Hospitality&lt;/a&gt;", by
         8464 &lt;a href="http://www.nadiaodunayo.com/"&gt;Nadia Odunayo&lt;/a&gt;.  &lt;/p&gt;
         8465 &lt;p&gt;Nadia talks about thinking of how to make people comfortable in your
         8466 code and in your team/organization/etc., and does it in terms of
         8467 thinking about host/guest relationships.  Have you ever …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Recently on the &lt;a href="http://www.greaterthancode.com/"&gt;Greater than Code podcast&lt;/a&gt; there was an episode
         8468 called "&lt;a href="http://www.greaterthancode.com/podcast/054-code-hospitality-with-nadia-odunayo/"&gt;Code Hospitality&lt;/a&gt;", by
         8469 &lt;a href="http://www.nadiaodunayo.com/"&gt;Nadia Odunayo&lt;/a&gt;.  &lt;/p&gt;
         8470 &lt;p&gt;Nadia talks about thinking of how to make people comfortable in your
         8471 code and in your team/organization/etc., and does it in terms of
         8472 thinking about host/guest relationships.  Have you ever stayed in an
         8473 AirBnB where the host carefully prepares some "welcome instructions"
         8474 for you, or puts little notes in their apartment to orient/guide you,
         8475 or gives you basic guidance around their city's transportation system?
         8476 We can think in similar ways of how to make people comfortable with
         8477 code bases.&lt;/p&gt;
         8478 &lt;p&gt;This of course hit me on so many levels, because in the past I've
         8479 written about analogies between software and urbanism/architecture.
         8480 &lt;a href="https://people.gnome.org/~federico/docs/software-with-qwan/index.html"&gt;Software that has the Quality Without A Name&lt;/a&gt;
         8481 talks about Christopher Alexander's architecture/urbanism patterns in
         8482 the context of software, based on &lt;a href="http://dreamsongs.com/"&gt;Richard Gabriel&lt;/a&gt;'s ideas,
         8483 and &lt;a href="http://zeta.math.utsa.edu/~yxk833/"&gt;Nikos Salingaros&lt;/a&gt;'s formalization of the design
         8484 process.  &lt;a href="https://people.gnome.org/~federico/blog/legacy-systems-as-old-cities.html"&gt;Legacy Systems as Old Cities&lt;/a&gt; talks about
         8485 how GNOME evolved parts of its user-visible software, and makes an
         8486 analogy with cities that evolve over time instead of being torn down
         8487 and rebuilt, based on urbanism ideas by Jane Jacobs, and
         8488 architecture/construction ideas by Stewart Brand.&lt;/p&gt;
         8489 &lt;p&gt;I definitely intend to do some thinking on Nadia's ideas for Code
         8490 Hospitality and try to connect them with this.&lt;/p&gt;
         8491 &lt;p&gt;In the meantime, I've just rewritten the &lt;a href="https://github.com/federicomenaquintero/gnome-class/blob/master/README.md"&gt;README in
         8492 gnome-class&lt;/a&gt; to make it suitable as an
         8493 introduction to hacking there.&lt;/p&gt;</content><category term="misc"></category><category term="software with living structure"></category></entry><entry><title>Rust+GNOME Hackfest in Berlin, 2017</title><link href="https://people.gnome.org/~federico/blog/rust-gnome-hackfest-berlin.html" rel="alternate"></link><published>2017-11-16T18:33:58-06:00</published><updated>2017-11-16T18:34:01-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-11-16:/~federico/blog/rust-gnome-hackfest-berlin.html</id><summary type="html">&lt;p&gt;Last weekend I was in Berlin for the &lt;a href="https://wiki.gnome.org/Hackfests/Rust2017-2"&gt;second Rust+GNOME
         8494 Hackfest&lt;/a&gt;, kindly hosted at the &lt;a href="https://kinvolk.io/"&gt;Kinvolk&lt;/a&gt; office.
         8495 This is in a &lt;em&gt;great&lt;/em&gt; location, half a block away from the &lt;a href="https://www.openstreetmap.org/node/3900136339"&gt;Kottbusser
         8496 Tor&lt;/a&gt; station, right at the entrance of the trendy Kreuzberg
         8497 neighborhood — full of interesting people, incredible graffitti, and
         8498 good …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Last weekend I was in Berlin for the &lt;a href="https://wiki.gnome.org/Hackfests/Rust2017-2"&gt;second Rust+GNOME
         8499 Hackfest&lt;/a&gt;, kindly hosted at the &lt;a href="https://kinvolk.io/"&gt;Kinvolk&lt;/a&gt; office.
         8500 This is in a &lt;em&gt;great&lt;/em&gt; location, half a block away from the &lt;a href="https://www.openstreetmap.org/node/3900136339"&gt;Kottbusser
         8501 Tor&lt;/a&gt; station, right at the entrance of the trendy Kreuzberg
         8502 neighborhood — full of interesting people, incredible graffitti, and
         8503 good, diverse food.&lt;/p&gt;
         8504 &lt;p&gt;&lt;a href="https://people.gnome.org/~federico/blog/images/kottbusser.jpg"&gt;&lt;img alt="Rug of Kottbusser Tor" src="https://people.gnome.org/~federico/blog/images/kottbusser-thumb.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
         8505 &lt;h1&gt;My goals for the hackfest&lt;/h1&gt;
         8506 &lt;p&gt;Over the past weeks I had been converting &lt;a href="https://github.com/federicomenaquintero/gnome-class"&gt;gnome-class&lt;/a&gt;
         8507 from the old &lt;a href="https://github.com/nikomatsakis/lalrpop/"&gt;lalrpop&lt;/a&gt;-based parser into the new Procedural
         8508 Macros framework for Rust, or &lt;code&gt;proc-macro2&lt;/code&gt; for short.  To do this the
         8509 parser for the gnome-class mini-language needs to be rewritten from
         8510 being specified in a lalrpop grammar, to using Rust's &lt;a href="https://github.com/dtolnay/syn/"&gt;syn&lt;/a&gt;
         8511 crate.&lt;/p&gt;
         8512 &lt;p&gt;Syn is a parser for Rust source code, written as a set of &lt;a href="https://github.com/geal/nom"&gt;nom&lt;/a&gt;
         8513 combinator parser macros.  For gnome-class we want to extend the Rust
         8514 language with a few conveniences to be able to specify GObject
         8515 classes/subclasses, methods, signals, properties, interfaces, and all
         8516 the goodies that GObject Introspection would expect.&lt;/p&gt;
         8517 &lt;p&gt;During the hackfest, &lt;a href="https://github.com/alexcrichton/"&gt;Alex Crichton&lt;/a&gt;, from the Rust core team,
         8518 kindly took over my baby steps in compiler writing and made everything
         8519 much more functional.  It was invaluable to have him there to reason
         8520 about macro hygiene (we &lt;em&gt;are&lt;/em&gt; generating an unhygienic macro!), bugs
         8521 in the quoting system, and general Rust-iness of the whole thing.&lt;/p&gt;
         8522 &lt;p&gt;I was also able to talk to &lt;a href="https://coaxion.net/blog/"&gt;Sebastian Dröge&lt;/a&gt; about his work in
         8523 writing GObjects in Rust by hand, for GStreamer, and what sort of
         8524 things gnome-class could make easier.  Sebastian knows GObject very
         8525 well, and has been doing awesome work in making it easy to derive
         8526 GObjects by hand in Rust, without lots of boilerplate — something with
         8527 which gnome-class can certainly help.&lt;/p&gt;
         8528 &lt;p&gt;I was also looking forward to talking again with &lt;a href="https://github.com/GuillaumeGomez"&gt;Guillaume
         8529 Gomez&lt;/a&gt;, one of the maintainers of &lt;a href="http://gtk-rs.org/"&gt;gtk-rs&lt;/a&gt;, and who
         8530 does so much work in the Rust ecosystem that I can't believe he has
         8531 time for it all.&lt;/p&gt;
         8532 &lt;p&gt;&lt;img alt="Graffitti heads" src="https://people.gnome.org/~federico/blog/images/graffitti-heads.jpg"&gt;&lt;/p&gt;
         8533 &lt;h1&gt;Extend the Rust language for GObject?  Like Vala?&lt;/h1&gt;
         8534 &lt;p&gt;Yeah, pretty much.&lt;/p&gt;
         8535 &lt;p&gt;Except that instead of a wholly new language, we use Rust as-is, and
         8536 we just add syntactic constructs that make it easy to write GObjects
         8537 without boilerplate.  For example, this works right now:&lt;/p&gt;
         8538 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#![feature(proc_macro)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8539 
         8540 &lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8541 
         8542 &lt;span class="cp"&gt;#[macro_use]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8543 &lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8544 &lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gobject_gen&lt;/span&gt;::&lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8545 
         8546 &lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8547 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Derives from GObject&lt;/span&gt;
         8548 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;One&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8549 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8550 
         8551 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;One&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8552 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// non-virtual method&lt;/span&gt;
         8553 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8554 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8555 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8556 
         8557 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kr"&gt;virtual&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8558 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8559 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8560 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8561 
         8562 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Inherits from our other class&lt;/span&gt;
         8563 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Two&lt;/span&gt;: &lt;span class="nc"&gt;One&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8564 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8565 
         8566 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;One&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Two&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8567 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// overrides the virtual method&lt;/span&gt;
         8568 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// maybe we should use &amp;quot;override&amp;quot; instead of &amp;quot;virtual&amp;quot; here?&lt;/span&gt;
         8569 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kr"&gt;virtual&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8570 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8571 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8572 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8573 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8574 
         8575 &lt;span class="cp"&gt;#[test]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8576 &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8577 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;One&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8578 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;two&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Two&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8579 
         8580 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8581 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8582 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;two&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8583 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;two&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8584 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8585 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8586 
         8587 &lt;p&gt;This generates a little boatload of &lt;a href="https://people.gnome.org/~federico/blog/docs/generated.rs"&gt;generated code&lt;/a&gt;,
         8588 including a good number of &lt;code&gt;unsafe&lt;/code&gt; calls to GObject functions
         8589 like &lt;code&gt;g_type_register_static_simple()&lt;/code&gt;.  It also creates all the
         8590 traits and paraphernalia that Glib-rs would create for the Rust
         8591 binding of a normal GObject written in C.&lt;/p&gt;
         8592 &lt;p&gt;The idea is that from the outside world, your generated GObject
         8593 classes are indistinguishable from GObjects implemented in C.&lt;/p&gt;
         8594 &lt;p&gt;&lt;em&gt;The idea is to write GObject libraries in a better language than C,
         8595 which can then be consumed from language bindings.&lt;/em&gt;&lt;/p&gt;
         8596 &lt;h2&gt;Current status of gnome-class&lt;/h2&gt;
         8597 &lt;p&gt;Up to about two weeks before the hackfest, the syntax for this
         8598 mini-language was totally ad-hoc and limited.  After a very productive
         8599 &lt;a href="https://mail.gnome.org/archives/rust-list/2017-October/msg00000.html"&gt;discussion on the mailing list&lt;/a&gt;, we came up with a better
         8600 syntax that definitely looks more Rust-like.  It is also easier to
         8601 implement, since the Rust parser in syn can be mostly reused as-is, or
         8602 pruned down for the parts where we only support GObject-like methods,
         8603 and not all the Rust bells and whistles (generics, lifetimes, trait
         8604 bounds).&lt;/p&gt;
         8605 &lt;p&gt;Gnome-class supports deriving classes directly from the basic GObject,
         8606 or from other GObject subclasses in the style of &lt;a href="https://github.com/gtk-rs/glib"&gt;glib-rs&lt;/a&gt;.&lt;/p&gt;
         8607 &lt;p&gt;You can define virtual and non-virtual methods.  You can override
         8608 virtual methods from your superclasses.&lt;/p&gt;
         8609 &lt;p&gt;Not all argument types are supported.  In the end we should support
         8610 argument types which are convertible from Rust to C types.  We need to
         8611 finish figuring out the annotations for ownership transfer of
         8612 references.&lt;/p&gt;
         8613 &lt;p&gt;We don't support GObject signals yet; I think that's my next task.&lt;/p&gt;
         8614 &lt;p&gt;We don't support GObject properties yet.&lt;/p&gt;
         8615 &lt;p&gt;We don't support defining new GType interfaces yet, but it is planned.
         8616 It should be easy to support implementing existing interfaces, as it
         8617 is pretty much the same as implementing a subclass.&lt;/p&gt;
         8618 &lt;p&gt;The best way to see what works right now is probably to &lt;a href="https://github.com/federicomenaquintero/gnome-class/tree/master/tests"&gt;look at the
         8619 examples&lt;/a&gt;, which also work as tests.&lt;/p&gt;
         8620 &lt;h1&gt;Digression on macro hygiene&lt;/h1&gt;
         8621 &lt;p&gt;Rust macros are &lt;em&gt;hygienic&lt;/em&gt;, unlike C macros which work just through
         8622 textual substitution.  That is, names declared inside Rust macros will
         8623 not clash with names in the calling code.&lt;/p&gt;
         8624 &lt;p&gt;One peculiar thing about gnome-class is that the user gives us a few
         8625 names, like a class name &lt;code&gt;Foo&lt;/code&gt; and some things inside it, say, a
         8626 method name &lt;code&gt;bar&lt;/code&gt;, and a signal &lt;code&gt;baz&lt;/code&gt; and a property &lt;code&gt;qux&lt;/code&gt;.
         8627 From there we want to generate a bunch of boilerplate for GObject
         8628 registration and implementaiton.  Some of the generated names in that
         8629 boilerplate would be&lt;/p&gt;
         8630 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Foo&lt;/span&gt;              &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
         8631 &lt;span class="n"&gt;FooClass&lt;/span&gt;         &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;generated&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;
         8632 &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;       &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;
         8633 &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;emit_baz&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Generated&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="k"&gt;signal&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
         8634 &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;set_qux&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;   &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Generated&lt;/span&gt; &lt;span class="n"&gt;property&lt;/span&gt; &lt;span class="n"&gt;setter&lt;/span&gt;
         8635 &lt;span class="n"&gt;foo_bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;        &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Generated&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;
         8636 &lt;span class="n"&gt;foo_get_type&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;   &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Generated&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;GObjects&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt;
         8637 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8638 
         8639 &lt;p&gt;However, if we want to actually generate those names inside our
         8640 gnome-class macro &lt;em&gt;and make them visible to the caller&lt;/em&gt;, we need to do
         8641 so &lt;em&gt;unhygienically&lt;/em&gt;.  Alex started started a &lt;a href="https://github.com/rust-lang/rust/issues/45934"&gt;very interesting discussion
         8642 on macro hygiene&lt;/a&gt;, so expect some news in the Rust world
         8643 soon.&lt;/p&gt;
         8644 &lt;p&gt;TL;DR: there is a difference between a &lt;em&gt;code generator&lt;/em&gt;, which
         8645 gnome-class mostly intends to be, and a &lt;em&gt;macro system&lt;/em&gt; which is just
         8646 an aid in typing repetitive code.&lt;/p&gt;
         8647 &lt;p&gt;&lt;img alt="Fuck wars" src="https://people.gnome.org/~federico/blog/images/fuck-wars.jpg"&gt;&lt;/p&gt;
         8648 &lt;h1&gt;People for whom to to be thankful&lt;/h1&gt;
         8649 &lt;p&gt;During the hackfest, &lt;a href="http://blog.nirbheek.in/"&gt;Nirbheek&lt;/a&gt; has been porting librsvg
         8650 from Autotools to the Meson build system, and dealing with Rust
         8651 peculiarities along the way.  This is exactly what I needed!  Thanks,
         8652 Nirbheek!&lt;/p&gt;
         8653 &lt;p&gt;&lt;a href="https://coaxion.net/blog/"&gt;Sebastian&lt;/a&gt; answered many of my questions about GObject
         8654 internals and how to use them from the Rust side.&lt;/p&gt;
         8655 &lt;p&gt;&lt;a href="http://zee-nix.blogspot.com/"&gt;Zeeshan&lt;/a&gt; took us to a bunch of good restaurants.  Korean,
         8656 ramen, Greek, excellent pizza... My stomach is definitely thankful.&lt;/p&gt;
         8657 &lt;h1&gt;Berlin&lt;/h1&gt;
         8658 &lt;p&gt;I love Berlin.  It is a cosmopolitan, progressive, LGBTQ-friendly
         8659 city, with lots of things to do, vast distances to be traveled, with
         8660 good public transport and bike lanes, diverse food to be eaten along
         8661 the way...&lt;/p&gt;
         8662 &lt;p&gt;But damnit, it's also cold at this time of the year.  I don't think
         8663 the weather was ever above 10°C while we were there, and mostly in a
         8664 constant state of not-quite-rain.  This is much different from the Berlin
         8665 in the summer that I knew!&lt;/p&gt;
         8666 &lt;p&gt;&lt;a href="https://people.gnome.org/~federico/blog/images/kimchi.jpg"&gt;&lt;img alt="Hackers at Kimchi Princess" src="https://people.gnome.org/~federico/blog/images/kimchi-thumb.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
         8667 &lt;p&gt;This is my third time visiting Berlin.  The first one was during the
         8668 Desktop Summit in 2011, and the second one was when my family and I
         8669 visited the city two years ago.  It is a city that I would definitely
         8670 like to know better.&lt;/p&gt;
         8671 &lt;h1&gt;Thanks to the GNOME Foundation...&lt;/h1&gt;
         8672 &lt;p&gt;... for sponsoring my travel and accomodation during the hackfest.&lt;/p&gt;
         8673 &lt;p&gt;&lt;img alt="Sponsored by the GNOME Foundation" src="https://people.gnome.org/~federico/blog/images/sponsored-badge-shadow.png"&gt;&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="gnome"></category><category term="Berlin"></category><category term="hackfests"></category></entry><entry><title>Compilation notifications in Emacs</title><link href="https://people.gnome.org/~federico/blog/compilation-notifications-in-emacs.html" rel="alternate"></link><published>2017-11-07T10:47:52-06:00</published><updated>2017-11-07T10:47:52-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-11-07:/~federico/blog/compilation-notifications-in-emacs.html</id><summary type="html">&lt;p&gt;Here is a little Emacs Lisp snippet that I've started using.  It makes
         8674 Emacs pop up a desktop-wide notification when a compilation finishes,
         8675 i.e. after "&lt;code&gt;M-x compile&lt;/code&gt;" is done.  Let's see if that keeps me from
         8676 wasting time in the web when I launch a compilation.&lt;/p&gt;
         8677 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;compilation-finish-functions&lt;/span&gt;
         8678       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;append …&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;Here is a little Emacs Lisp snippet that I've started using.  It makes
         8679 Emacs pop up a desktop-wide notification when a compilation finishes,
         8680 i.e. after "&lt;code&gt;M-x compile&lt;/code&gt;" is done.  Let's see if that keeps me from
         8681 wasting time in the web when I launch a compilation.&lt;/p&gt;
         8682 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;compilation-finish-functions&lt;/span&gt;
         8683       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;append&lt;/span&gt; &lt;span class="nv"&gt;compilation-finish-functions&lt;/span&gt;
         8684           &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;fmq-compilation-finish&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
         8685 
         8686 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;fmq-compilation-finish&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;buffer&lt;/span&gt; &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         8687   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;call-process&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;notify-send&amp;quot;&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
         8688         &lt;span class="s"&gt;&amp;quot;-t&amp;quot;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;
         8689         &lt;span class="s"&gt;&amp;quot;-i&amp;quot;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;emacs&amp;quot;&lt;/span&gt;
         8690         &lt;span class="s"&gt;&amp;quot;Compilation finished in Emacs&amp;quot;&lt;/span&gt;
         8691         &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         8692 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="misc"></category><category term="emacs"></category></entry><entry><title>How glib-rs works, part 3: Boxed types</title><link href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-3.html" rel="alternate"></link><published>2017-09-08T19:28:11-05:00</published><updated>2017-09-08T19:28:11-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-09-08:/~federico/blog/how-glib-rs-works-part-3.html</id><summary type="html">&lt;p&gt;(&lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html"&gt;First part&lt;/a&gt; of the series, with index to all the articles)&lt;/p&gt;
         8693 &lt;p&gt;Now let's get on and see how glib-rs handles boxed types.&lt;/p&gt;
         8694 &lt;h1&gt;Boxed types?&lt;/h1&gt;
         8695 &lt;p&gt;Let's say you are given a sealed cardboard box with &lt;em&gt;something&lt;/em&gt;, but you
         8696 can't know what's inside.  You can just pass it on to someone else …&lt;/p&gt;</summary><content type="html">&lt;p&gt;(&lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html"&gt;First part&lt;/a&gt; of the series, with index to all the articles)&lt;/p&gt;
         8697 &lt;p&gt;Now let's get on and see how glib-rs handles boxed types.&lt;/p&gt;
         8698 &lt;h1&gt;Boxed types?&lt;/h1&gt;
         8699 &lt;p&gt;Let's say you are given a sealed cardboard box with &lt;em&gt;something&lt;/em&gt;, but you
         8700 can't know what's inside.  You can just pass it on to someone else, or
         8701 burn it.  And since computers are magic duplication machines, you may
         8702 want to copy the box and its contents... and maybe some day you will
         8703 get around to opening it.&lt;/p&gt;
         8704 &lt;p&gt;That's a boxed type.  You get a pointer to &lt;em&gt;something&lt;/em&gt;, who knows
         8705 what's inside.  You can just pass it on to someone else, burn it — I
         8706 mean, free it — or since computers are magic, copy the pointer and
         8707 whatever it points to.&lt;/p&gt;
         8708 &lt;p&gt;That's exactly the API for boxed types.&lt;/p&gt;
         8709 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="n"&gt;gpointer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;GBoxedCopyFunc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpointer&lt;/span&gt; &lt;span class="n"&gt;boxed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         8710 &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;GBoxedFreeFunc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpointer&lt;/span&gt; &lt;span class="n"&gt;boxed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         8711 
         8712 &lt;span class="n"&gt;GType&lt;/span&gt; &lt;span class="nf"&gt;g_boxed_type_register_static&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;gchar&lt;/span&gt;   &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         8713                                     &lt;span class="n"&gt;GBoxedCopyFunc&lt;/span&gt; &lt;span class="n"&gt;boxed_copy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         8714                                     &lt;span class="n"&gt;GBoxedFreeFunc&lt;/span&gt; &lt;span class="n"&gt;boxed_free&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         8715 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8716 
         8717 &lt;h2&gt;Simple copying, simple freeing&lt;/h2&gt;
         8718 &lt;p&gt;Imagine you have a color...&lt;/p&gt;
         8719 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         8720     &lt;span class="n"&gt;guchar&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8721     &lt;span class="n"&gt;guchar&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8722     &lt;span class="n"&gt;guchar&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8723 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8724 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8725 
         8726 &lt;p&gt;If you had a pointer to a Color, how would you copy it?  Easy:&lt;/p&gt;
         8727 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Color&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;copy_color&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         8728 &lt;span class="p"&gt;{&lt;/span&gt;
         8729     &lt;span class="n"&gt;Color&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g_new&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         8730     &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8731     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8732 &lt;span class="p"&gt;}&lt;/span&gt;
         8733 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8734 
         8735 &lt;p&gt;That is, allocate a new &lt;code&gt;Color&lt;/code&gt;, and essentially &lt;code&gt;memcpy()&lt;/code&gt; the
         8736 contents.&lt;/p&gt;
         8737 &lt;p&gt;And to free it?  A simple &lt;code&gt;g_free()&lt;/code&gt; works — there are no internal
         8738 things that need to be freed individually.&lt;/p&gt;
         8739 &lt;h2&gt;Complex copying, complex freeing&lt;/h2&gt;
         8740 &lt;p&gt;And if we had a color with a name?&lt;/p&gt;
         8741 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         8742     &lt;span class="n"&gt;guchar&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8743     &lt;span class="n"&gt;guchar&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8744     &lt;span class="n"&gt;guchar&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8745     &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8746 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;ColorWithName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8747 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8748 
         8749 &lt;p&gt;We can't just &lt;code&gt;*a = *b&lt;/code&gt; here, as we actually need to copy the string
         8750 &lt;code&gt;name&lt;/code&gt;.  Okay:&lt;/p&gt;
         8751 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;ColorWithName&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;copy_color_with_name&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ColorWithName&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         8752 &lt;span class="p"&gt;{&lt;/span&gt;
         8753     &lt;span class="n"&gt;ColorWithName&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g_new&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ColorWithName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         8754     &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8755     &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8756     &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8757     &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g_strdup&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         8758     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         8759 &lt;span class="p"&gt;}&lt;/span&gt;
         8760 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8761 
         8762 &lt;p&gt;The corresponding &lt;code&gt;free_color_with_name()&lt;/code&gt; would &lt;code&gt;g_free(b-&amp;gt;name)&lt;/code&gt; and then
         8763 &lt;code&gt;g_free(b)&lt;/code&gt;, of course.&lt;/p&gt;
         8764 &lt;h1&gt;Glib-rs and boxed types&lt;/h1&gt;
         8765 &lt;p&gt;Let's look at this by parts.  First, a &lt;a href="https://github.com/gtk-rs/glib/blob/f0a2aae96162fd628fb0e3eedd3d3e042c25e2c4/src/boxed.rs#L265"&gt;&lt;code&gt;BoxedMemoryManager&lt;/code&gt;
         8766 trait&lt;/a&gt; to define the basic API to manage the
         8767 memory of boxed types.  This is what defines the &lt;code&gt;copy&lt;/code&gt; and &lt;code&gt;free&lt;/code&gt;
         8768 functions, like above.&lt;/p&gt;
         8769 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BoxedMemoryManager&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;: &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nb"&gt;static&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8770 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8771 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8772 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8773 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8774 
         8775 &lt;p&gt;Second, the &lt;a href="https://github.com/gtk-rs/glib/blob/f0a2aae96162fd628fb0e3eedd3d3e042c25e2c4/src/boxed.rs#L273"&gt;actual representation&lt;/a&gt; of a &lt;code&gt;Boxed&lt;/code&gt; type:&lt;/p&gt;
         8776 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Boxed&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;: &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nb"&gt;static&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MM&lt;/span&gt;: &lt;span class="nc"&gt;BoxedMemoryManager&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8777 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt;: &lt;span class="nc"&gt;AnyBox&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8778 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_dummy&lt;/span&gt;: &lt;span class="nc"&gt;PhantomData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MM&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8779 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8780 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8781 
         8782 &lt;p&gt;This struct is generic over &lt;code&gt;T&lt;/code&gt;, the actual type that we will be
         8783 wrapping, and &lt;code&gt;MM&lt;/code&gt;, something which must implement the
         8784 &lt;code&gt;BoxedMemoryManager&lt;/code&gt; trait.&lt;/p&gt;
         8785 &lt;p&gt;Inside, it stores &lt;code&gt;inner&lt;/code&gt;, an &lt;code&gt;AnyBox&lt;/code&gt;, which we will see shortly.
         8786 The &lt;code&gt;_dummy: PhantomData&amp;lt;MM&amp;gt;&lt;/code&gt; is a &lt;a href="https://doc.rust-lang.org/std/marker/struct.PhantomData.html"&gt;Rust-ism&lt;/a&gt; to indicate that although this
         8787 struct doesn't actually store a memory manager, it acts as if it does
         8788 — it does not concern us here.&lt;/p&gt;
         8789 &lt;h2&gt;The &lt;em&gt;actual&lt;/em&gt; representation of boxed data&lt;/h2&gt;
         8790 &lt;p&gt;Let's look at that &lt;a href="https://github.com/gtk-rs/glib/blob/f0a2aae96162fd628fb0e3eedd3d3e042c25e2c4/src/boxed.rs#L247"&gt;&lt;code&gt;AnyBox&lt;/code&gt;&lt;/a&gt; that is stored inside a &lt;code&gt;Boxed&lt;/code&gt;:&lt;/p&gt;
         8791 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;AnyBox&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8792 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Native&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8793 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ForeignOwned&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8794 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ForeignBorrowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8795 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8796 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8797 
         8798 &lt;p&gt;We have three cases:&lt;/p&gt;
         8799 &lt;ul&gt;
         8800 &lt;li&gt;
         8801 &lt;p&gt;&lt;code&gt;Native(Box&amp;lt;T&amp;gt;)&lt;/code&gt; - this boxed value &lt;code&gt;T&lt;/code&gt; comes from Rust itself, so we
         8802   know everything about it!&lt;/p&gt;
         8803 &lt;/li&gt;
         8804 &lt;li&gt;
         8805 &lt;p&gt;&lt;code&gt;ForeignOwned(*mut T)&lt;/code&gt; - this boxed value &lt;code&gt;T&lt;/code&gt; came from the outside, but
         8806   we own it now.  We will have to free it when we are done with it.&lt;/p&gt;
         8807 &lt;/li&gt;
         8808 &lt;li&gt;
         8809 &lt;p&gt;&lt;code&gt;ForeignBorrowed(*mut T)&lt;/code&gt; - this boxed value &lt;code&gt;T&lt;/code&gt; came from the
         8810   outside, but we are just borrowing it temporarily: we &lt;strong&gt;don't&lt;/strong&gt; want to
         8811   free it when we are done with it.&lt;/p&gt;
         8812 &lt;/li&gt;
         8813 &lt;/ul&gt;
         8814 &lt;p&gt;For example, if we look at the &lt;a href="https://github.com/gtk-rs/glib/blob/f0a2aae96162fd628fb0e3eedd3d3e042c25e2c4/src/boxed.rs#L367"&gt;implementation of the &lt;code&gt;Drop&lt;/code&gt;
         8815 trait&lt;/a&gt; for the &lt;code&gt;Boxed&lt;/code&gt; struct, we will indeed see that it
         8816 calls the &lt;code&gt;BoxedMemoryManager::free()&lt;/code&gt; &lt;strong&gt;only&lt;/strong&gt; if we have a
         8817 &lt;code&gt;ForeignOwned&lt;/code&gt; value:&lt;/p&gt;
         8818 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;: &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nb"&gt;static&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MM&lt;/span&gt;: &lt;span class="nc"&gt;BoxedMemoryManager&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Drop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Boxed&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MM&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8819 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8820 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8821 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AnyBox&lt;/span&gt;::&lt;span class="n"&gt;ForeignOwned&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8822 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;MM&lt;/span&gt;::&lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8823 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8824 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8825 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8826 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8827 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8828 
         8829 &lt;p&gt;If we had a &lt;code&gt;Native(Box&amp;lt;T&amp;gt;)&lt;/code&gt; value, it means it came from Rust itself,
         8830 and Rust knows how to &lt;code&gt;Drop&lt;/code&gt; its own &lt;code&gt;Box&amp;lt;T&amp;gt;&lt;/code&gt; (i.e. a chunk of memory
         8831 allocated in the heap).&lt;/p&gt;
         8832 &lt;p&gt;But for external resources, we must tell Rust how to manage them.
         8833 Again: in the case where the Rust side owns the reference to the
         8834 external boxed data, we have a &lt;code&gt;ForeignOwned&lt;/code&gt; and &lt;code&gt;Drop&lt;/code&gt; it by
         8835 &lt;code&gt;free()&lt;/code&gt;ing it; in the case where the Rust side is just borrowing the
         8836 data temporarily, we have a &lt;code&gt;ForeignBorrowed&lt;/code&gt; and don't touch it when
         8837 we are done.&lt;/p&gt;
         8838 &lt;h2&gt;Copying&lt;/h2&gt;
         8839 &lt;p&gt;When do we have to copy a boxed value?  For example, when we transfer
         8840 from Rust to Glib with full transfer of ownership, i.e. the
         8841 &lt;a href="https://github.com/gtk-rs/glib/blob/f0a2aae96162fd628fb0e3eedd3d3e042c25e2c4/src/boxed.rs#L312"&gt;&lt;code&gt;to_glib_full()&lt;/code&gt;&lt;/a&gt; pattern &lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html#ptr-transfer-full"&gt;that we saw
         8842 before&lt;/a&gt;.  This is how that trait method is
         8843 implemented for &lt;code&gt;Boxed&lt;/code&gt;:&lt;/p&gt;
         8844 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;: &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nb"&gt;static&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MM&lt;/span&gt;: &lt;span class="nc"&gt;BoxedMemoryManager&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ToGlibPtr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Boxed&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MM&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8845 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;to_glib_full&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8846 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;::&lt;span class="n"&gt;AnyBox&lt;/span&gt;::&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8847 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8848 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Native&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;**&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8849 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;ForeignOwned&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ForeignBorrowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8850 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8851 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MM&lt;/span&gt;::&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8852 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8853 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8854 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8855 
         8856 &lt;p&gt;See the &lt;code&gt;MM:copy(ptr)&lt;/code&gt; in the last line?  That's where the copy
         8857 happens.  The lines above just get the appropriate pointer to the data
         8858 data from the &lt;code&gt;AnyBox&lt;/code&gt; and cast it.&lt;/p&gt;
         8859 &lt;p&gt;There is extra boilerplate in &lt;code&gt;boxed.rs&lt;/code&gt; which you can look at; it's
         8860 mostly a bunch of trait implementations to copy the boxed data at the
         8861 appropriate times (e.g. the &lt;code&gt;FromGlibPtrNone&lt;/code&gt; trait), also an
         8862 implementation of the &lt;code&gt;Deref&lt;/code&gt; trait to get to the contents of a &lt;code&gt;Boxed
         8863 / AnyBox&lt;/code&gt; easily, etc.  The trait implementations are there just to
         8864 make it as convenient as possible to handle &lt;code&gt;Boxed&lt;/code&gt; types.&lt;/p&gt;
         8865 &lt;h2&gt;Who implements BoxedMemoryManager?&lt;/h2&gt;
         8866 &lt;p&gt;Up to now, we have seen things like the implementation of &lt;code&gt;Drop&lt;/code&gt; for
         8867 &lt;code&gt;Boxed&lt;/code&gt;, which uses &lt;code&gt;BoxedMemoryManager::free()&lt;/code&gt;, and the
         8868 implementation of &lt;code&gt;ToGlibPtr&lt;/code&gt; which uses &lt;code&gt;::copy()&lt;/code&gt;.&lt;/p&gt;
         8869 &lt;p&gt;But those are just the trait's "abstract" methods, so to speak.  What
         8870 actually implements them?&lt;/p&gt;
         8871 &lt;p&gt;Glib-rs has a general-purpose macro to wrap Glib types.  It can wrap
         8872 boxed types, shared pointer types, and GObjects.  For now we will just
         8873 look at boxed types.&lt;/p&gt;
         8874 &lt;p&gt;Glib-rs comes with a macro, &lt;a href="http://gtk-rs.org/docs/glib/macro.glib_wrapper.html#boxed"&gt;&lt;code&gt;glib_wrapper!()&lt;/code&gt;&lt;/a&gt;, that can be used in
         8875 different ways.  You can use it to automatically write the boilerplate
         8876 for a boxed type like this:&lt;/p&gt;
         8877 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;glib_wrapper&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8878 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Boxed&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ffi&lt;/span&gt;::&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8879 
         8880 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8881 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ffi&lt;/span&gt;::&lt;span class="n"&gt;color_copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mut_override&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8882 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ffi&lt;/span&gt;::&lt;span class="n"&gt;color_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8883 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;get_type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ffi&lt;/span&gt;::&lt;span class="n"&gt;color_get_type&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8884 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8885 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8886 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8887 
         8888 &lt;p&gt;This expands to an internal
         8889 &lt;a href="https://github.com/gtk-rs/glib/blob/f0a2aae96162fd628fb0e3eedd3d3e042c25e2c4/src/boxed.rs#L15"&gt;&lt;code&gt;glib_boxed_wrapper!()&lt;/code&gt;&lt;/a&gt; macro that does a few
         8890 things.  We will only look at particularly interesting bits.&lt;/p&gt;
         8891 &lt;p&gt;First, the macro creates a newtype around a tuple with 1) the actual
         8892 data type you want to box, and 2) a memory manager.  In the example
         8893 above, the newtype would be called &lt;code&gt;Color&lt;/code&gt;, and it would wrap an
         8894 &lt;code&gt;ffi:Color&lt;/code&gt; (say, a C struct).&lt;/p&gt;
         8895 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="cp"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Boxed&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cp"&gt;$ffi_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MemoryManager&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8896 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8897 
         8898 &lt;p&gt;Aha!  And that &lt;code&gt;MemoryManager&lt;/code&gt;?  The macro defines it as a zero-sized
         8899 type:&lt;/p&gt;
         8900 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;MemoryManager&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8901 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8902 
         8903 &lt;p&gt;Then it &lt;a href="https://github.com/gtk-rs/glib/blob/f0a2aae96162fd628fb0e3eedd3d3e042c25e2c4/src/boxed.rs#L59"&gt;implements&lt;/a&gt; the &lt;code&gt;BoxedMemoryManager&lt;/code&gt; trait for that
         8904 &lt;code&gt;MemoryManager&lt;/code&gt; struct:&lt;/p&gt;
         8905 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BoxedMemoryManager&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cp"&gt;$ffi_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MemoryManager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8906 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="cp"&gt;#[inline]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8907 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$copy_arg&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$ffi_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$ffi_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8908 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="cp"&gt;$copy_expr&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8909 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8910 
         8911 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="cp"&gt;#[inline]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8912 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$free_arg&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$ffi_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8913 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="cp"&gt;$free_expr&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8914 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8915 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8916 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8917 
         8918 &lt;p&gt;There!  &lt;em&gt;This&lt;/em&gt; is where the &lt;code&gt;copy/free&lt;/code&gt; methods are implemented, based
         8919 on the bits of code with which you invoked the macro.  In the call to
         8920 &lt;code&gt;glib_wrapper!()&lt;/code&gt; we had this:&lt;/p&gt;
         8921 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ffi&lt;/span&gt;::&lt;span class="n"&gt;color_copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mut_override&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8922 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ffi&lt;/span&gt;::&lt;span class="n"&gt;color_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8923 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8924 
         8925 &lt;p&gt;In the impl aboe, the &lt;code&gt;$copy_expr&lt;/code&gt; will expand to
         8926 &lt;code&gt;ffi::color_copy(mut_override(ptr))&lt;/code&gt; and &lt;code&gt;$free_expr&lt;/code&gt; will expand to
         8927 &lt;code&gt;ffi::color_free(ptr)&lt;/code&gt;, which defines our implementation of a memory
         8928 manager for our &lt;code&gt;Color&lt;/code&gt; boxed type.&lt;/p&gt;
         8929 &lt;h2&gt;Zero-sized what?&lt;/h2&gt;
         8930 &lt;p&gt;Within the macro's definition, let's look again at the definitions of
         8931 our boxed type and the memory manager object that actually implements
         8932 the &lt;code&gt;BoxedMemoryManager&lt;/code&gt; trait.  Here is what the macro would expand
         8933 to with our &lt;code&gt;Color&lt;/code&gt; example:&lt;/p&gt;
         8934 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Boxed&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ffi&lt;/span&gt;::&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MemoryManager&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8935 
         8936 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;MemoryManager&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8937 
         8938 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BoxedMemoryManager&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ffi&lt;/span&gt;::&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MemoryManager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8939 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ffi&lt;/span&gt;::&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8940 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8941 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         8942 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         8943 
         8944 &lt;p&gt;Here, &lt;code&gt;MemoryManager&lt;/code&gt; is a zero-sized type.  This means &lt;strong&gt;it doesn't
         8945 take up any space&lt;/strong&gt; in the &lt;code&gt;Color&lt;/code&gt; tuple!  When a &lt;code&gt;Color&lt;/code&gt; is allocated
         8946 in the heap, it is really as if it contained an &lt;code&gt;ffi::Color&lt;/code&gt; (the
         8947 C struct we are wrapping) &lt;em&gt;and nothing else&lt;/em&gt;.&lt;/p&gt;
         8948 &lt;p&gt;All the knowledge about how to copy/free &lt;code&gt;ffi::Color&lt;/code&gt; &lt;strong&gt;lives only in
         8949 the compiler&lt;/strong&gt; thanks to the trait implementation.  When the compiler
         8950 expands all the macros and monomorphizes all the generic functions,
         8951 the calls to &lt;code&gt;ffi::color_copy()&lt;/code&gt; and &lt;code&gt;ffi::color_free()&lt;/code&gt; &lt;strong&gt;will be
         8952 inlined at the appropriate spots&lt;/strong&gt;.  There is no need to have
         8953 auxiliary structures taking up space in the heap, just to store
         8954 function pointers to the copy/free functions, or anything like that.&lt;/p&gt;
         8955 &lt;h1&gt;Next up&lt;/h1&gt;
         8956 &lt;p&gt;You may have seen that our example call to &lt;code&gt;glib_wrapper!()&lt;/code&gt; also
         8957 passed in a &lt;code&gt;ffi::color_get_type()&lt;/code&gt; function.  We haven't talked about
         8958 how glib-rs wraps Glib's &lt;code&gt;GType&lt;/code&gt;, &lt;code&gt;GValue&lt;/code&gt;, and all of that.  We are
         8959 getting closer and closer to being able to wrap &lt;code&gt;GObject&lt;/code&gt;.&lt;/p&gt;
         8960 &lt;p&gt;Stay tuned!&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="gnome"></category></entry><entry><title>Initial posts about librsvg's C to Rust conversion</title><link href="https://people.gnome.org/~federico/blog/librsvg-posts.html" rel="alternate"></link><published>2017-09-07T15:50:46-05:00</published><updated>2017-09-07T15:50:46-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-09-07:/~federico/blog/librsvg-posts.html</id><summary type="html">&lt;p&gt;The initial articles about librsvg's conversion to Rust are in my &lt;a href="https://people.gnome.org/~federico/news.html"&gt;old
         8961 blog&lt;/a&gt;, so they may be a bit hard to find from this new blog.
         8962 Here is a list of those posts, just so they are easier to find:&lt;/p&gt;
         8963 &lt;ul&gt;
         8964 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2016-10.html#25"&gt;Librsvg gets Rusty&lt;/a&gt;&lt;/li&gt;
         8965 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2016-10.html#28"&gt;Porting a few C functions to Rust …&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;The initial articles about librsvg's conversion to Rust are in my &lt;a href="https://people.gnome.org/~federico/news.html"&gt;old
         8966 blog&lt;/a&gt;, so they may be a bit hard to find from this new blog.
         8967 Here is a list of those posts, just so they are easier to find:&lt;/p&gt;
         8968 &lt;ul&gt;
         8969 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2016-10.html#25"&gt;Librsvg gets Rusty&lt;/a&gt;&lt;/li&gt;
         8970 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2016-10.html#28"&gt;Porting a few C functions to Rust&lt;/a&gt;&lt;/li&gt;
         8971 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2016-11.html#01"&gt;Bézier curves, markers, and SVG's concept of directionality&lt;/a&gt;&lt;/li&gt;
         8972 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2016-11.html#03"&gt;Refactoring C to make Rustification easier&lt;/a&gt;&lt;/li&gt;
         8973 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2016-11.html#14"&gt;Exposing Rust objects to C code&lt;/a&gt;&lt;/li&gt;
         8974 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2016-11.html#16"&gt;Debugging Rust code inside a C library&lt;/a&gt;&lt;/li&gt;
         8975 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2017-01.html#11"&gt;Reproducible font rendering for librsvg's tests&lt;/a&gt;&lt;/li&gt;
         8976 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2017-02.html#03"&gt;Algebraic data types in Rust, and basic parsing&lt;/a&gt;&lt;/li&gt;
         8977 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2017-02.html#17"&gt;How librsvg exports reference-counted objects from Rust to C&lt;/a&gt;&lt;/li&gt;
         8978 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2017-02.html#24"&gt;Griping about parsers and shitty specifications&lt;/a&gt;&lt;/li&gt;
         8979 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2017-02.html#28"&gt;Porting librsvg's tree of nodes to Rust&lt;/a&gt;&lt;/li&gt;
         8980 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/news-2017-04.html#28"&gt;gboolean is not Rust bool&lt;/a&gt;&lt;/li&gt;
         8981 &lt;/ul&gt;
         8982 &lt;p&gt;Within this new blog, you can look for articles with the &lt;a href="https://people.gnome.org/~federico/blog/tag/librsvg.html"&gt;librsvg tag&lt;/a&gt;.&lt;/p&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category></entry><entry><title>The Magic of GObject Introspection</title><link href="https://people.gnome.org/~federico/blog/magic-of-gobject-introspection.html" rel="alternate"></link><published>2017-09-07T11:46:03-05:00</published><updated>2017-09-07T11:46:03-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-09-07:/~federico/blog/magic-of-gobject-introspection.html</id><summary type="html">&lt;p&gt;Before continuing with the &lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html"&gt;glib-rs architecture&lt;/a&gt;, let's take
         8983 a detour and look at &lt;a href="https://wiki.gnome.org/Projects/GObjectIntrospection"&gt;GObject Introspection&lt;/a&gt;.  Although it can
         8984 seem like an obscure part of the GNOME platform, it is an absolutely
         8985 vital part of it:  it is what lets people write GNOME applications in
         8986 any language.&lt;/p&gt;
         8987 &lt;p&gt;Let's start with a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Before continuing with the &lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html"&gt;glib-rs architecture&lt;/a&gt;, let's take
         8988 a detour and look at &lt;a href="https://wiki.gnome.org/Projects/GObjectIntrospection"&gt;GObject Introspection&lt;/a&gt;.  Although it can
         8989 seem like an obscure part of the GNOME platform, it is an absolutely
         8990 vital part of it:  it is what lets people write GNOME applications in
         8991 any language.&lt;/p&gt;
         8992 &lt;p&gt;Let's start with a bit of history.&lt;/p&gt;
         8993 &lt;h1&gt;Brief history of language bindings in GNOME&lt;/h1&gt;
         8994 &lt;p&gt;When we started GNOME in 1997, we didn't want to write &lt;em&gt;all&lt;/em&gt; of it in
         8995 C.  We had some inspiration from elsewhere.&lt;/p&gt;
         8996 &lt;h2&gt;Prehistory: GIMP and the Procedural Database&lt;/h2&gt;
         8997 &lt;p&gt;There was already good precedent for software written in a combination of
         8998 programming languages.  Emacs, the flagship text editor of the
         8999 GNU project, was written with a relatively small core in C, and the
         9000 majority of the program in Emacs Lisp.&lt;/p&gt;
         9001 &lt;p&gt;In similar fashion, we were very influenced by the design of the GIMP,
         9002 which was very innovative at that time.  The GIMP has a large core
         9003 written in C.  However, it supports plug-ins or &lt;em&gt;scripts&lt;/em&gt; written in a
         9004 variety of languages.  Initially the only scripting language available
         9005 for the GIMP was Scheme.&lt;/p&gt;
         9006 &lt;p&gt;The GIMP's plug-ins and scripts run as separate processes, so
         9007 they don't have immediate access to the data of the image being
         9008 edited, or to the core functions of the program like "paint with a
         9009 brush at this location".  To let plug-ins and scripts access these
         9010 data and these functions, the GIMP has what it calls a
         9011 Procedural Database (PDB).  This is a
         9012 list of functions that the core program or plug-ins wish to export.
         9013 For example, there are functions like &lt;code&gt;gimp-scale-image&lt;/code&gt; and
         9014 &lt;code&gt;gimp-move-layer&lt;/code&gt;.  Once these functions are registered in the
         9015 PDB, any part of the program or plug-ins can call them.  Scripts are
         9016 often written to automate common tasks — for example, when one wants
         9017 to adjust the contrast of photos and scale them in bulk.  Scripts can
         9018 call functions in the PDB easily, irrespective of the programming
         9019 language they are written in.&lt;/p&gt;
         9020 &lt;p&gt;We wanted to write GNOME's core libraries in C, and write a similar
         9021 Procedural Database to allow those libraries to be called from any
         9022 programming language.  Eventually it turned out that a PDB was not
         9023 necessary, and there were better ways to go about enabling different
         9024 programming languages.&lt;/p&gt;
         9025 &lt;h2&gt;Enabling sane memory management&lt;/h2&gt;
         9026 &lt;p&gt;GTK+ started out with a very simple scheme for memory management:  a
         9027 container owned its child widgets, and so on recursively.  When you
         9028 freed a container, it would be responsible for freeing its children.&lt;/p&gt;
         9029 &lt;p&gt;However, consider what happens when a widget needs to hold a reference
         9030 to another widget that is not one of its children.  For example, a
         9031 GtkLabel with an underlined mnemonic ("_N_ame:") needs to have a
         9032 reference to the GtkEntry that should be focused when you press
         9033 Alt-N.  In the very earliest versions of GTK+, how to do this was
         9034 undefined:  C programmers were already used to having shared pointers
         9035 everywhere, and they were used to being responsible for managing their
         9036 memory.&lt;/p&gt;
         9037 &lt;p&gt;Of course, this was prone to bugs.  If you have something like&lt;/p&gt;
         9038 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         9039     &lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9040 
         9041     &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;label_string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9042     &lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;widget_to_focus&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9043 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;GtkLabel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9044 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9045 
         9046 &lt;p&gt;then if you are writing the destructor, you may simply want to&lt;/p&gt;
         9047 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
         9048 &lt;span class="nf"&gt;gtk_label_free&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GtkLabel&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         9049 &lt;span class="p"&gt;{&lt;/span&gt;
         9050     &lt;span class="n"&gt;g_free&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label_string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9051     &lt;span class="n"&gt;gtk_widget_free&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget_to_focus&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="cm"&gt;/* oops, we don&amp;#39;t own this */&lt;/span&gt;
         9052 
         9053     &lt;span class="n"&gt;free_parent_instance&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9054 &lt;span class="p"&gt;}&lt;/span&gt;
         9055 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9056 
         9057 &lt;p&gt;Say you have a GtkBox with the label and its associated GtkEntry.
         9058 Then, freeing the GtkBox would recursively free the label with that
         9059 &lt;code&gt;gtk_label_free()&lt;/code&gt;, and then the entry with its own function.  But by
         9060 the time the entry gets freed, the line
         9061 &lt;code&gt;gtk_widget_free (widget_to_focus)&lt;/code&gt; has already freed the entry, and
         9062 we get a double-free bug!&lt;/p&gt;
         9063 &lt;p&gt;Madness!&lt;/p&gt;
         9064 &lt;p&gt;That is, we had no idea what we were doing.  Or rather, our
         9065 understanding of widgets had not evolved to the point of acknowledging
         9066 that a widget tree is not a simply tree, but rather a
         9067 directed graph of container-child relationships, plus
         9068 random-widget-to-random-widget relationships.  And of course, other
         9069 parts of the program &lt;em&gt;which are not even widget implementations&lt;/em&gt; may
         9070 need to keep references to widgets and free them or not as
         9071 appropriate.&lt;/p&gt;
         9072 &lt;p&gt;I think Marius Vollmer was the first person to start formalizing
         9073 this.  He came from the world of GNU Guile, a Scheme interpreter, and
         9074 so he already knew how garbage collection and seas of shared
         9075 references ought to work.&lt;/p&gt;
         9076 &lt;p&gt;Marius implemented reference-counting for GTK+ — that's where
         9077 &lt;code&gt;gtk_object_ref()&lt;/code&gt; and &lt;code&gt;gtk_object_unref()&lt;/code&gt; come from; they eventually
         9078 got moved to the base &lt;code&gt;GObject&lt;/code&gt; class, so we now have &lt;code&gt;g_object_ref()&lt;/code&gt;
         9079 and &lt;code&gt;g_object_unref()&lt;/code&gt; and a host of functions to have weak
         9080 references, notification of destruction, and all the things required
         9081 to keep garbage collectors happy.&lt;/p&gt;
         9082 &lt;h2&gt;The first language bindings&lt;/h2&gt;
         9083 &lt;p&gt;The very first language bindings were written by hand.  The GTK+ API
         9084 was small, and it seemed feasible to take&lt;/p&gt;
         9085 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;gtk_widget_show&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9086 &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;gtk_widget_hide&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9087 
         9088 &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;gtk_container_add&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GtkContainer&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9089 &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;gtk_container_remove&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GtkContainer&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9090 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9091 
         9092 &lt;p&gt;and just wrap those functions in various languages, by hand, on an
         9093 as-needed basis.&lt;/p&gt;
         9094 &lt;p&gt;Of course, there is a lot of duplication when doing things that way.
         9095 As the C API grows, one needs to do more and more manual work to
         9096 keep up with it.&lt;/p&gt;
         9097 &lt;p&gt;Also, C structs with public fields are problematic.  If we had&lt;/p&gt;
         9098 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         9099     &lt;span class="n"&gt;guchar&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9100     &lt;span class="n"&gt;guchar&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9101     &lt;span class="n"&gt;guchar&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9102 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;GdkColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9103 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9104 
         9105 &lt;p&gt;and we &lt;em&gt;expect&lt;/em&gt; program code to fill in a &lt;code&gt;GdkColor&lt;/code&gt; by hand and
         9106 pass it to a drawing function like&lt;/p&gt;
         9107 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;gdk_set_foreground_color&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GdkDrawingContext&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GdkColor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9108 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9109 
         9110 &lt;p&gt;then it is no problem to do that in C:&lt;/p&gt;
         9111 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;GdkColor&lt;/span&gt; &lt;span class="n"&gt;magenta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
         9112 
         9113 &lt;span class="n"&gt;gdk_set_foreground_color&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;magenta&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9114 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9115 
         9116 &lt;p&gt;But to do that in a high level language?  You don't have access to C
         9117 struct fields!  And back then, libffi wasn't generally available.&lt;/p&gt;
         9118 &lt;p&gt;Authors of language bindings had to write some glue code, in C, by
         9119 hand, to let people access a C struct and then pass it on to GTK+.
         9120 For example, for Python, they would need to write something like&lt;/p&gt;
         9121 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
         9122 &lt;span class="nf"&gt;make_wrapped_gdk_color&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         9123 &lt;span class="p"&gt;{&lt;/span&gt;
         9124     &lt;span class="n"&gt;GdkColor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;g_color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9125     &lt;span class="n"&gt;PyObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;py_color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9126 
         9127     &lt;span class="n"&gt;g_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g_new&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GdkColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9128     &lt;span class="cm"&gt;/* ... fill in g_color-&amp;gt;r, g, b from the Python args */&lt;/span&gt;
         9129 
         9130     &lt;span class="n"&gt;py_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wrap_g_color&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g_color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9131     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;py_color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9132 &lt;span class="p"&gt;}&lt;/span&gt;
         9133 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9134 
         9135 &lt;p&gt;Writing that by hand is an incredible amount of drudgery.&lt;/p&gt;
         9136 &lt;p&gt;What language bindings needed was a &lt;em&gt;description&lt;/em&gt; of the API in a
         9137 machine-readable format, so that the glue code could be written by a
         9138 code generator.&lt;/p&gt;
         9139 &lt;h2&gt;The first API descriptions&lt;/h2&gt;
         9140 &lt;p&gt;I don't remember if it was the GNU Guile people, or the PyGTK people,
         9141 who started to write descriptions of the GNOME API by hand.  For ease
         9142 of parsing, it was done in a Scheme-like dialect.  A description may
         9143 look like&lt;/p&gt;
         9144 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt; &lt;span class="nv"&gt;GtkWidget&lt;/span&gt;
         9145        &lt;span class="c1"&gt;;;; void gtk_widget_show (GtkWidget *widget);&lt;/span&gt;
         9146        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt; &lt;span class="nv"&gt;show&lt;/span&gt;
         9147                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;args&lt;/span&gt; &lt;span class="nv"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         9148                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;retval&lt;/span&gt; &lt;span class="nv"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         9149 
         9150        &lt;span class="c1"&gt;;;; void gtk_widget_hide (GtkWidget *widget);&lt;/span&gt;
         9151        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt; &lt;span class="nv"&gt;hide&lt;/span&gt;
         9152                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;args&lt;/span&gt; &lt;span class="nv"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         9153                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;retval&lt;/span&gt; &lt;span class="nv"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
         9154 
         9155 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt; &lt;span class="nv"&gt;GtkContainer&lt;/span&gt;
         9156        &lt;span class="c1"&gt;;;; void gtk_container_add (GtkContainer *container, GtkWidget *child);&lt;/span&gt;
         9157        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt; &lt;span class="nv"&gt;add&lt;/span&gt;
         9158                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;args&lt;/span&gt; &lt;span class="nv"&gt;GtkWidget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         9159                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;retval&lt;/span&gt; &lt;span class="nv"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
         9160 
         9161 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;GdkColor&lt;/span&gt;
         9162         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;field&lt;/span&gt; &lt;span class="nv"&gt;r&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;guchar&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         9163         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;field&lt;/span&gt; &lt;span class="nv"&gt;g&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;guchar&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
         9164         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;field&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;guchar&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; 
         9165 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9166 
         9167 &lt;p&gt;Again, writing those descriptions by hand (and keeping up with the C
         9168 API) was a lot of work, but the glue code to implement the binding
         9169 could be done mostly automatically.  The generated code may need
         9170 subsequent tweaks by hand to deal with details that the Scheme-like
         9171 descriptions didn't contemplate, but it was better than writing
         9172 &lt;em&gt;everything&lt;/em&gt; by hand.&lt;/p&gt;
         9173 &lt;h2 id="type-system"&gt;Glib gets a real type system&lt;/h2&gt;
         9174 &lt;p&gt;Tim Janik took over the parts of Glib that implement
         9175 objects/signals/types, and added a lot of things to create a good type
         9176 system for C.  This is where things like &lt;code&gt;GType&lt;/code&gt;, &lt;code&gt;GValue&lt;/code&gt;, &lt;code&gt;GParamSpec&lt;/code&gt;, and
         9177 fundamental types come from.&lt;/p&gt;
         9178 &lt;p&gt;For example, a &lt;code&gt;GType&lt;/code&gt; is an identifier for a type, and a &lt;code&gt;GValue&lt;/code&gt; is a
         9179 type plus, well, a value of that type.  You can ask a &lt;code&gt;GValue&lt;/code&gt;, "are
         9180 you an int?  are you a GObject?".&lt;/p&gt;
         9181 &lt;p&gt;You can register new types:  for example, there would be code in Gdk
         9182 that registers a new &lt;code&gt;GType&lt;/code&gt; for &lt;code&gt;GdkColor&lt;/code&gt;, so you can ask a value,
         9183 "are you a color?".&lt;/p&gt;
         9184 &lt;p&gt;Registering a type involves telling the GObject system things like how
         9185 to copy values of that type, and how to free them.  For &lt;code&gt;GdkColor&lt;/code&gt;
         9186 this may be just &lt;code&gt;g_new() / g_free()&lt;/code&gt;; for reference-counted objects
         9187 it may be &lt;code&gt;g_object_ref() / g_object_unref()&lt;/code&gt;.&lt;/p&gt;
         9188 &lt;h3&gt;Objects can be queried about some of their properties&lt;/h3&gt;
         9189 &lt;p&gt;A widget can tell you when you press a mouse button mouse on it:  it
         9190 will emit the &lt;code&gt;button-press-event&lt;/code&gt; signal.  When &lt;code&gt;GtkWidget&lt;/code&gt;'s
         9191 implementation registers this signal, it calls something like&lt;/p&gt;
         9192 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="n"&gt;g_signal_new&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;button-press-event&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         9193         &lt;span class="n"&gt;gtk_widget_get_type&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="cm"&gt;/* type of object for which this signal is being created */&lt;/span&gt;
         9194         &lt;span class="p"&gt;...&lt;/span&gt;
         9195         &lt;span class="n"&gt;G_TYPE_BOOLEAN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="cm"&gt;/* type of return value */&lt;/span&gt;
         9196         &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;               &lt;span class="cm"&gt;/* number of arguments */&lt;/span&gt;
         9197         &lt;span class="n"&gt;GDK_TYPE_EVENT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="cm"&gt;/* type of first and only argument */&lt;/span&gt;
         9198 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9199 
         9200 &lt;p&gt;This tells GObject that &lt;code&gt;GtkWidget&lt;/code&gt; will have a signal called
         9201 &lt;code&gt;button-press-event&lt;/code&gt;, with a return type of &lt;code&gt;G_TYPE_BOOLEAN&lt;/code&gt;, and with
         9202 a single argument of type &lt;code&gt;GDK_TYPE_EVENT&lt;/code&gt;.  This lets GObject do the
         9203 appropriate marshalling of arguments when the signal is emitted.&lt;/p&gt;
         9204 &lt;p&gt;But also!  &lt;em&gt;You can query the signal for its argument types!&lt;/em&gt;  You can
         9205 run &lt;code&gt;g_signal_query()&lt;/code&gt;, which will then tell you all the details of
         9206 the signal: its name, return type, argument types, etc.  A language
         9207 binding could run &lt;code&gt;g_signal_query()&lt;/code&gt; &lt;em&gt;and generate a description of the
         9208 signal automatically&lt;/em&gt; to the Scheme-like description language.  And
         9209 then generate the binding from &lt;em&gt;that&lt;/em&gt;.&lt;/p&gt;
         9210 &lt;h2&gt;Not all of an object's properties can be queried&lt;/h2&gt;
         9211 &lt;p&gt;Unfortunately, although GObject signals and properties &lt;em&gt;can&lt;/em&gt; be
         9212 queried, methods can't be.  C doesn't have classes with methods, and GObject does
         9213 not really have any provisions to implement them.  &lt;/p&gt;
         9214 &lt;p&gt;Conventionally, for a static method one would just do&lt;/p&gt;
         9215 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;
         9216 &lt;span class="nf"&gt;gtk_widget_set_flags&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GtkWidgetFlags&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         9217 &lt;span class="p"&gt;{&lt;/span&gt;
         9218     &lt;span class="cm"&gt;/* modify a struct field within &amp;quot;widget&amp;quot; or whatever */&lt;/span&gt;
         9219     &lt;span class="cm"&gt;/* repaint or something */&lt;/span&gt;
         9220 &lt;span class="p"&gt;}&lt;/span&gt;
         9221 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9222 
         9223 &lt;p&gt;And for a virtual method one would put a function pointer in the class
         9224 structure, and provide a convenient way to call it:&lt;/p&gt;
         9225 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         9226     &lt;span class="n"&gt;GtkObjectClass&lt;/span&gt; &lt;span class="n"&gt;parent_class&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9227 
         9228     &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cairo_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9229 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;GtkWidgetClass&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9230 
         9231 &lt;span class="kt"&gt;void&lt;/span&gt;
         9232 &lt;span class="nf"&gt;gtk_widget_draw&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cairo_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         9233 &lt;span class="p"&gt;{&lt;/span&gt;
         9234     &lt;span class="n"&gt;GtkWidgetClass&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;klass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;find_widget_class&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9235 
         9236     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;klass&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9237 &lt;span class="p"&gt;}&lt;/span&gt;
         9238 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9239 
         9240 &lt;p&gt;And GObject has no idea about this method — there is no way to query
         9241 it; it just exists in C-space.&lt;/p&gt;
         9242 &lt;p&gt;Now, historically, GTK+'s header files have been written in a &lt;em&gt;very&lt;/em&gt;
         9243 consistent style.  It is quite possible to write a tool that will take
         9244 a header file like&lt;/p&gt;
         9245 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cm"&gt;/* gtkwidget.h */&lt;/span&gt;
         9246 &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         9247     &lt;span class="n"&gt;GtkObject&lt;/span&gt; &lt;span class="n"&gt;parent_class&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9248 
         9249     &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cairo_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9250 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;GtkWidgetClass&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         9251 
         9252 &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;gtk_widget_set_flags&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GtkWidgetFlags&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9253 &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;gtk_widget_draw&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cairo_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9254 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9255 
         9256 &lt;p&gt;and parse it, even if it is with a simple parser that does not
         9257 completely understand the C language, and have heuristics like&lt;/p&gt;
         9258 &lt;ul&gt;
         9259 &lt;li&gt;
         9260 &lt;p&gt;Is there a &lt;code&gt;class_name_foo()&lt;/code&gt; function prototype with no
         9261   corresponding &lt;code&gt;foo&lt;/code&gt; field in the &lt;code&gt;Class&lt;/code&gt; structure?  It's probably a
         9262   static method.&lt;/p&gt;
         9263 &lt;/li&gt;
         9264 &lt;li&gt;
         9265 &lt;p&gt;Is there a &lt;code&gt;class_name_bar()&lt;/code&gt; function with a &lt;code&gt;bar&lt;/code&gt; field in the
         9266   &lt;code&gt;Class&lt;/code&gt; structure?  It's probably a virtual method.&lt;/p&gt;
         9267 &lt;/li&gt;
         9268 &lt;li&gt;
         9269 &lt;p&gt;Etc.&lt;/p&gt;
         9270 &lt;/li&gt;
         9271 &lt;/ul&gt;
         9272 &lt;p&gt;And in fact, that's what we had.  C header files would get parsed
         9273 with those heuristics, and the Scheme-like description files would get
         9274 generated.&lt;/p&gt;
         9275 &lt;h2&gt;Scheme-like descriptions get reused, kind of&lt;/h2&gt;
         9276 &lt;p&gt;Language binding authors started reusing the Scheme-like
         9277 descriptions.  Sometimes they would cannibalize the descriptions from
         9278 PyGTK, or Guile (again, I don't remember where the canonical version
         9279 was maintained) and use them as they were.&lt;/p&gt;
         9280 &lt;p&gt;Other times they would copy the files, modify them by hand some more,
         9281 and &lt;em&gt;then&lt;/em&gt; use them to generate their language binding.&lt;/p&gt;
         9282 &lt;h2&gt;C being hostile&lt;/h2&gt;
         9283 &lt;p&gt;From just reading/parsing a C function prototype, you cannot know
         9284 certain things.  If one function argument is of type &lt;code&gt;Foo *&lt;/code&gt;, does it mean:&lt;/p&gt;
         9285 &lt;ul&gt;
         9286 &lt;li&gt;
         9287 &lt;p&gt;the function gets a pointer to something which it should not modify
         9288   ("in" parameter)&lt;/p&gt;
         9289 &lt;/li&gt;
         9290 &lt;li&gt;
         9291 &lt;p&gt;the function gets a pointer to uninitialized data which it will set
         9292   ("out" parameter)&lt;/p&gt;
         9293 &lt;/li&gt;
         9294 &lt;li&gt;
         9295 &lt;p&gt;the function gets a pointer to initialized data which it will use
         9296   and modify ("inout" parameter)&lt;/p&gt;
         9297 &lt;/li&gt;
         9298 &lt;li&gt;
         9299 &lt;p&gt;the function will copy that pointer and hold a reference to the
         9300   pointed data, and not free it when it's done&lt;/p&gt;
         9301 &lt;/li&gt;
         9302 &lt;li&gt;
         9303 &lt;p&gt;the function will take over the ownership of the pointed data, and
         9304   free it when it's done&lt;/p&gt;
         9305 &lt;/li&gt;
         9306 &lt;li&gt;
         9307 &lt;p&gt;etc.&lt;/p&gt;
         9308 &lt;/li&gt;
         9309 &lt;/ul&gt;
         9310 &lt;p&gt;Sometimes people would include these annotations in the Scheme-like
         9311 description language.  But wouldn't it be better if those annotations
         9312 came &lt;em&gt;from the C code itself&lt;/em&gt;?&lt;/p&gt;
         9313 &lt;h1&gt;GObject Introspection appears&lt;/h1&gt;
         9314 &lt;p&gt;For GNOME 3, we wanted a unified solution for language bindings:&lt;/p&gt;
         9315 &lt;ul&gt;
         9316 &lt;li&gt;
         9317 &lt;p&gt;Have a single way to extract the machine-readable descriptions of
         9318   the C API.&lt;/p&gt;
         9319 &lt;/li&gt;
         9320 &lt;li&gt;
         9321 &lt;p&gt;Have every language binding be automatically generated from those
         9322   descriptions.&lt;/p&gt;
         9323 &lt;/li&gt;
         9324 &lt;li&gt;
         9325 &lt;p&gt;In the descriptions, have &lt;em&gt;all&lt;/em&gt; the information necessary to
         9326   generate a correct language binding...&lt;/p&gt;
         9327 &lt;/li&gt;
         9328 &lt;li&gt;
         9329 &lt;p&gt;... including documentation.&lt;/p&gt;
         9330 &lt;/li&gt;
         9331 &lt;/ul&gt;
         9332 &lt;p&gt;We had to do a lot of work to accomplish this.  For example:&lt;/p&gt;
         9333 &lt;ul&gt;
         9334 &lt;li&gt;
         9335 &lt;p&gt;Remove C-isms from the public API.  Varargs functions, those that
         9336   have &lt;code&gt;foo (int x, ...)&lt;/code&gt;, can't be easily described and called from
         9337   other languages.  Instead, have something like
         9338   &lt;code&gt;foov (int x, int num_args, GValue *args_array)&lt;/code&gt; that can be easily
         9339   consumed by other languages.&lt;/p&gt;
         9340 &lt;/li&gt;
         9341 &lt;li&gt;
         9342 &lt;p&gt;Add &lt;em&gt;annotations&lt;/em&gt; throughout the code so that the ad-hoc C parser
         9343   can know about in/out/inout arguments, and whether pointer arguments
         9344   are borrowed references or a full transfership of ownership.&lt;/p&gt;
         9345 &lt;/li&gt;
         9346 &lt;li&gt;
         9347 &lt;p&gt;Take the in-line documentation comments and store them as part of
         9348   the machine-readable description of the API.&lt;/p&gt;
         9349 &lt;/li&gt;
         9350 &lt;li&gt;
         9351 &lt;p&gt;When compiling a library, automatically do all the things like
         9352   &lt;code&gt;g_signal_query()&lt;/code&gt; and spit out machine-readable descriptions of
         9353   those parts of the API.&lt;/p&gt;
         9354 &lt;/li&gt;
         9355 &lt;/ul&gt;
         9356 &lt;p&gt;So, GObject Introspection is all of those things.&lt;/p&gt;
         9357 &lt;h2&gt;Annotations&lt;/h2&gt;
         9358 &lt;p&gt;If you have looked at the C code for a GNOME library, you may have
         9359 seen something like this:&lt;/p&gt;
         9360 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cm"&gt;/**&lt;/span&gt;
         9361 &lt;span class="cm"&gt; * gtk_widget_get_parent:&lt;/span&gt;
         9362 &lt;span class="cm"&gt; * @widget: a #GtkWidget&lt;/span&gt;
         9363 &lt;span class="cm"&gt; *&lt;/span&gt;
         9364 &lt;span class="cm"&gt; * Returns the parent container of @widget.&lt;/span&gt;
         9365 &lt;span class="cm"&gt; *&lt;/span&gt;
         9366 &lt;span class="cm"&gt; * Returns: (transfer none) (nullable): the parent container of @widget, or %NULL&lt;/span&gt;
         9367 &lt;span class="cm"&gt; **/&lt;/span&gt;
         9368 &lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
         9369 &lt;span class="nf"&gt;gtk_widget_get_parent&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GtkWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         9370 &lt;span class="p"&gt;{&lt;/span&gt;
         9371     &lt;span class="p"&gt;...&lt;/span&gt;
         9372 &lt;span class="p"&gt;}&lt;/span&gt;
         9373 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9374 
         9375 &lt;p&gt;See that "&lt;code&gt;(transfer none) (nullable)&lt;/code&gt;" in the documentation comments?
         9376 The &lt;code&gt;(transfer none)&lt;/code&gt; means that the return value is a pointer whose
         9377 ownership does &lt;em&gt;not&lt;/em&gt; get transferred to the caller, i.e. the widget
         9378 retains ownership.  Finally, the &lt;code&gt;(nullable)&lt;/code&gt; indicates that the
         9379 function can return &lt;code&gt;NULL&lt;/code&gt;, when the widget has no parent.&lt;/p&gt;
         9380 &lt;p&gt;A language binding will then use this information as follows:&lt;/p&gt;
         9381 &lt;ul&gt;
         9382 &lt;li&gt;
         9383 &lt;p&gt;It will not &lt;code&gt;unref()&lt;/code&gt; the parent widget when it is done with it.&lt;/p&gt;
         9384 &lt;/li&gt;
         9385 &lt;li&gt;
         9386 &lt;p&gt;It will deal with a &lt;code&gt;NULL&lt;/code&gt; pointer in a special way, instead of
         9387   assuming that references are not null.&lt;/p&gt;
         9388 &lt;/li&gt;
         9389 &lt;/ul&gt;
         9390 &lt;p&gt;Every now and then someone discovers a public function which is
         9391 lacking an annotation of that sort — for GNOME's purposes this is a
         9392 bug; fortunately, it is easy to add that annotation to the C sources
         9393 and regenerate the machine-readable descriptions.&lt;/p&gt;
         9394 &lt;h2&gt;Machine-readable descriptions, or repository files&lt;/h2&gt;
         9395 &lt;p&gt;So, what do those machine-readable descriptions actually look like?
         9396 They moved away from a Scheme-like language and got turned into XML,
         9397 because early XXIst century.&lt;/p&gt;
         9398 &lt;p&gt;The machine-readable descriptions are called &lt;em&gt;GObject Introspection
         9399 Repository files&lt;/em&gt;, or GIR for short.&lt;/p&gt;
         9400 &lt;p&gt;Let's look at some parts of &lt;code&gt;Gtk-3.0.gir&lt;/code&gt;, which your distro may put in
         9401 &lt;code&gt;/usr/share/gir-1.0/Gtk-3.0.gir&lt;/code&gt;.&lt;/p&gt;
         9402 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;repository&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1.2&amp;quot;&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9403 
         9404   &lt;span class="nt"&gt;&amp;lt;namespace&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Gtk&amp;quot;&lt;/span&gt;
         9405              &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.0&amp;quot;&lt;/span&gt;
         9406              &lt;span class="na"&gt;shared-library=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;libgtk-3.so.0,libgdk-3.so.0&amp;quot;&lt;/span&gt;
         9407              &lt;span class="na"&gt;c:identifier-prefixes=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Gtk&amp;quot;&lt;/span&gt;
         9408              &lt;span class="na"&gt;c:symbol-prefixes=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gtk&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9409 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9410 
         9411 &lt;p&gt;For the toplevel "&lt;code&gt;Gtk&lt;/code&gt;" namespace, this is what the &lt;code&gt;.so&lt;/code&gt; library is
         9412 called.  All identifiers have "&lt;code&gt;Gtk&lt;/code&gt;" or "&lt;code&gt;gtk&lt;/code&gt;" prefixes.&lt;/p&gt;
         9413 &lt;h3&gt;A class with methods and a signal&lt;/h3&gt;
         9414 &lt;p&gt;Let's look at the description for &lt;code&gt;GtkEntry&lt;/code&gt;...&lt;/p&gt;
         9415 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;class&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Entry&amp;quot;&lt;/span&gt;
         9416            &lt;span class="na"&gt;c:symbol-prefix=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;entry&amp;quot;&lt;/span&gt;
         9417            &lt;span class="na"&gt;c:type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;GtkEntry&amp;quot;&lt;/span&gt;
         9418            &lt;span class="na"&gt;parent=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Widget&amp;quot;&lt;/span&gt;
         9419            &lt;span class="na"&gt;glib:type-name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;GtkEntry&amp;quot;&lt;/span&gt;
         9420            &lt;span class="na"&gt;glib:get-type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gtk_entry_get_type&amp;quot;&lt;/span&gt;
         9421            &lt;span class="na"&gt;glib:type-struct=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;EntryClass&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9422 
         9423       &lt;span class="nt"&gt;&amp;lt;doc&lt;/span&gt; &lt;span class="na"&gt;xml:space=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;preserve&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;The #GtkEntry widget is a single line text entry
         9424 widget. A fairly large set of key bindings are supported
         9425 by default. If the entered text is longer than the allocation
         9426 ...
         9427        &lt;span class="nt"&gt;&amp;lt;/doc&amp;gt;&lt;/span&gt;
         9428 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9429 
         9430 &lt;p&gt;This is the start of the description for &lt;code&gt;GtkEntry&lt;/code&gt;.  We already know
         9431 that everything is prefixed with "&lt;code&gt;Gtk&lt;/code&gt;", so the name is just given as
         9432 "&lt;code&gt;Entry&lt;/code&gt;".  Its parent class is &lt;code&gt;Widget&lt;/code&gt; and the function which
         9433 registers it against the GObject type system is &lt;code&gt;gtk_entry_get_type&lt;/code&gt;.&lt;/p&gt;
         9434 &lt;p&gt;Also, there are the toplevel documentation comments for the &lt;code&gt;Entry&lt;/code&gt;
         9435 class.&lt;/p&gt;
         9436 &lt;p&gt;Onwards!&lt;/p&gt;
         9437 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;      &lt;span class="nt"&gt;&amp;lt;implements&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Atk.ImplementorIface&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         9438       &lt;span class="nt"&gt;&amp;lt;implements&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Buildable&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         9439       &lt;span class="nt"&gt;&amp;lt;implements&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CellEditable&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         9440       &lt;span class="nt"&gt;&amp;lt;implements&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Editable&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         9441 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9442 
         9443 &lt;p&gt;GObject classes can implement various interfaces; this is the list
         9444 that &lt;code&gt;GtkEntry&lt;/code&gt; supports.&lt;/p&gt;
         9445 &lt;p&gt;Next, let's look at a single method:&lt;/p&gt;
         9446 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;      &lt;span class="nt"&gt;&amp;lt;method&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;get_text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;c:identifier=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gtk_entry_get_text&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9447         &lt;span class="nt"&gt;&amp;lt;doc&lt;/span&gt; &lt;span class="na"&gt;xml:space=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;preserve&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Retrieves the contents of the entry widget. ... &lt;span class="nt"&gt;&amp;lt;/doc&amp;gt;&lt;/span&gt;
         9448 
         9449         &lt;span class="nt"&gt;&amp;lt;return-value&lt;/span&gt; &lt;span class="na"&gt;transfer-ownership=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9450           &lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;utf8&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;c:type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;const gchar*&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         9451         &lt;span class="nt"&gt;&amp;lt;/return-value&amp;gt;&lt;/span&gt;
         9452 
         9453         &lt;span class="nt"&gt;&amp;lt;parameters&amp;gt;&lt;/span&gt;
         9454           &lt;span class="nt"&gt;&amp;lt;instance-parameter&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;entry&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;transfer-ownership=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9455             &lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Entry&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;c:type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;GtkEntry*&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         9456           &lt;span class="nt"&gt;&amp;lt;/instance-parameter&amp;gt;&lt;/span&gt;
         9457         &lt;span class="nt"&gt;&amp;lt;/parameters&amp;gt;&lt;/span&gt;
         9458       &lt;span class="nt"&gt;&amp;lt;/method&amp;gt;&lt;/span&gt;
         9459 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9460 
         9461 &lt;p&gt;The method &lt;code&gt;get_text&lt;/code&gt; and its corresponding C symbol.  Its return
         9462 value is an UTF-8 encoded string, and ownership of the memory for that
         9463 string is not transferred to the caller.&lt;/p&gt;
         9464 &lt;p&gt;The method takes a single parameter which is the &lt;code&gt;entry&lt;/code&gt; instance itself.&lt;/p&gt;
         9465 &lt;p&gt;Now, let's look at a signal:&lt;/p&gt;
         9466 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;      &lt;span class="nt"&gt;&amp;lt;glib:signal&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;activate&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;when=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;last&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9467         &lt;span class="nt"&gt;&amp;lt;doc&lt;/span&gt; &lt;span class="na"&gt;xml:space=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;preserve&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;The ::activate signal is emitted when the user hits
         9468 the Enter key. ...&lt;span class="nt"&gt;&amp;lt;/doc&amp;gt;&lt;/span&gt;
         9469 
         9470         &lt;span class="nt"&gt;&amp;lt;return-value&lt;/span&gt; &lt;span class="na"&gt;transfer-ownership=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9471           &lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;none&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;c:type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;void&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         9472         &lt;span class="nt"&gt;&amp;lt;/return-value&amp;gt;&lt;/span&gt;
         9473       &lt;span class="nt"&gt;&amp;lt;/glib:signal&amp;gt;&lt;/span&gt;
         9474 
         9475     &lt;span class="nt"&gt;&amp;lt;/class&amp;gt;&lt;/span&gt;
         9476 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9477 
         9478 &lt;p&gt;The "&lt;code&gt;activate&lt;/code&gt;" signal takes no arguments, and has a return value of
         9479 type &lt;code&gt;void&lt;/code&gt;, i.e. no return value.&lt;/p&gt;
         9480 &lt;h3&gt;A struct with public fields&lt;/h3&gt;
         9481 &lt;p&gt;The following comes from &lt;code&gt;Gdk-3.0.gir&lt;/code&gt;; it's the description for
         9482 &lt;code&gt;GdkRectangle&lt;/code&gt;.&lt;/p&gt;
         9483 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;record&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Rectangle&amp;quot;&lt;/span&gt;
         9484             &lt;span class="na"&gt;c:type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;GdkRectangle&amp;quot;&lt;/span&gt;
         9485             &lt;span class="na"&gt;glib:type-name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;GdkRectangle&amp;quot;&lt;/span&gt;
         9486             &lt;span class="na"&gt;glib:get-type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gdk_rectangle_get_type&amp;quot;&lt;/span&gt;
         9487             &lt;span class="na"&gt;c:symbol-prefix=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rectangle&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9488 
         9489       &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;writable=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9490         &lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gint&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;c:type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;int&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         9491       &lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
         9492       &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;y&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;writable=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9493         &lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gint&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;c:type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;int&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         9494       &lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
         9495       &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;width&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;writable=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9496         &lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gint&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;c:type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;int&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         9497       &lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
         9498       &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;height&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;writable=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9499         &lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gint&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;c:type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;int&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         9500       &lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
         9501 
         9502     &lt;span class="nt"&gt;&amp;lt;/record&amp;gt;&lt;/span&gt;
         9503 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9504 
         9505 &lt;p&gt;So that's the &lt;code&gt;x/y/width/height&lt;/code&gt; fields in the struct, in the same
         9506 order as they are defined in the C code.&lt;/p&gt;
         9507 &lt;p&gt;And so on.  The idea is for the whole API exported by a GObject
         9508 library to be describable by that format.  If something can't be
         9509 described, it's a bug in the library, or a bug in the format.&lt;/p&gt;
         9510 &lt;h1&gt;Making language bindings start up quickly: typelib files&lt;/h1&gt;
         9511 &lt;p&gt;As we saw, the GIR files are the XML descriptions of GObject APIs.
         9512 Dynamic languages like Python would prefer to generate the language
         9513 binding on the fly, as needed, instead of pre-generating a huge
         9514 binding.&lt;/p&gt;
         9515 &lt;p&gt;However, GTK+ is a big API: &lt;code&gt;Gtk-3.0.gir&lt;/code&gt; is 7 MB of XML.  Parsing
         9516 all of that just to be able to generate &lt;code&gt;gtk_widget_show()&lt;/code&gt; on the fly
         9517 would be too slow.  Also, there are GTK+'s dependencies: Atk, Gdk,
         9518 Cairo, etc.  You don't want to parse &lt;em&gt;everything&lt;/em&gt; just to start up!&lt;/p&gt;
         9519 &lt;p&gt;So, we have an extra step that compiles the GIR files down to binary
         9520 &lt;code&gt;.typelib&lt;/code&gt; files.  For example,
         9521 &lt;code&gt;/usr/lib64/girepository-1.0/Gtk-3.0.typelib&lt;/code&gt; is about 600 KB on my
         9522 machine.  Those files get &lt;code&gt;mmap()&lt;/code&gt;ed for fast access, and can be
         9523 shared between processes.&lt;/p&gt;
         9524 &lt;h2&gt;How dynamic language bindings use typelib files&lt;/h2&gt;
         9525 &lt;p&gt;GObject Introspection comes with a library that language binding
         9526 implementors can use to consume those &lt;code&gt;.typelib&lt;/code&gt; files.  The
         9527 &lt;code&gt;libgirepository&lt;/code&gt; library has functions like "list all the classes
         9528 available in this namespace", or "call this function with these
         9529 values for arguments, and give me back the return value here".&lt;/p&gt;
         9530 &lt;p&gt;Internally, &lt;code&gt;libgirepository&lt;/code&gt; uses &lt;code&gt;libffi&lt;/code&gt; to actually call the C
         9531 functions in the dynamically-linked libraries.&lt;/p&gt;
         9532 &lt;p&gt;So, when you write &lt;code&gt;foo.py&lt;/code&gt; and do&lt;/p&gt;
         9533 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gi&lt;/span&gt;
         9534 &lt;span class="n"&gt;gi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;require_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Gtk&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;3.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         9535 &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;gi.repository&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Gtk&lt;/span&gt;
         9536 &lt;span class="n"&gt;win&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Gtk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Window&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         9537 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9538 
         9539 &lt;p&gt;what happens is that &lt;code&gt;pygobject&lt;/code&gt; calls &lt;code&gt;libgirepository&lt;/code&gt; to &lt;code&gt;mmap()&lt;/code&gt;
         9540 the &lt;code&gt;.typelib&lt;/code&gt;, and sees that the constructor for &lt;code&gt;Gtk.Window&lt;/code&gt; is a C
         9541 function called &lt;code&gt;gtk_window_new()&lt;/code&gt;.  After seeing how that function
         9542 wants to be called, it calls the function using &lt;code&gt;libffi&lt;/code&gt;, wraps the
         9543 result with a &lt;code&gt;PyObject&lt;/code&gt;, and that's what you get on the Python side.&lt;/p&gt;
         9544 &lt;h1&gt;Static languages&lt;/h1&gt;
         9545 &lt;p&gt;A static language like Rust prefers to have the whole language binding
         9546 pre-generated.  This is what the various crates in &lt;a href="https://github.com/gtk-rs/"&gt;gtk-rs&lt;/a&gt;
         9547 do.&lt;/p&gt;
         9548 &lt;p&gt;&lt;a href="https://github.com/gtk-rs/gir/tree/master/src"&gt;The gir crate&lt;/a&gt; takes a &lt;code&gt;.gir&lt;/code&gt; file (i.e. the XML descriptions)
         9549 and does two things:&lt;/p&gt;
         9550 &lt;ul&gt;
         9551 &lt;li&gt;
         9552 &lt;p&gt;Reconstructs the C function prototypes and C struct declarations,
         9553 but in a way Rust can understand them.  This gets output to the &lt;a href="https://github.com/gtk-rs/sys"&gt;sys
         9554 crate&lt;/a&gt;.&lt;/p&gt;
         9555 &lt;/li&gt;
         9556 &lt;li&gt;
         9557 &lt;p&gt;Creates idiomatic Rust code for the language binding.  This gets
         9558 output to the various crates; for example, &lt;a href="https://github.com/gtk-rs/gtk"&gt;the gtk one&lt;/a&gt;.&lt;/p&gt;
         9559 &lt;/li&gt;
         9560 &lt;/ul&gt;
         9561 &lt;p&gt;When reconstructing the C structs and prototypes, we get stuff like&lt;/p&gt;
         9562 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[repr(C)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9563 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;GtkWidget&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9564 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parent_instance&lt;/span&gt;: &lt;span class="nc"&gt;gobject&lt;/span&gt;::&lt;span class="n"&gt;GInitiallyUnowned&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9565 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;priv_&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GtkWidgetPrivate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9566 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9567 
         9568 &lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9569 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;gtk_entry_new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GtkWidget&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9570 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9571 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9572 
         9573 &lt;p&gt;And the idiomatic bindings?  Stay tuned!&lt;/p&gt;</content><category term="misc"></category><category term="gnome"></category><category term="gobject-introspection"></category><category term="rust"></category></entry><entry><title>Librsvg's build infrastructure: Autotools and Rust</title><link href="https://people.gnome.org/~federico/blog/librsvg-build-infrastructure.html" rel="alternate"></link><published>2017-09-01T18:15:29-05:00</published><updated>2017-11-11T09:37:08-06:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-09-01:/~federico/blog/librsvg-build-infrastructure.html</id><summary type="html">&lt;p&gt;Today I released &lt;a href="https://mail.gnome.org/archives/desktop-devel-list/2017-September/msg00008.html"&gt;librsvg 2.41.1&lt;/a&gt;, and it's a big release!
         9574 Apart from all the Rust goodness, and the large number of bug fixes, I
         9575 am very happy with the way the build system works these days.  I've
         9576 found it invaluable to have good examples of Autotools incantations to …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today I released &lt;a href="https://mail.gnome.org/archives/desktop-devel-list/2017-September/msg00008.html"&gt;librsvg 2.41.1&lt;/a&gt;, and it's a big release!
         9577 Apart from all the Rust goodness, and the large number of bug fixes, I
         9578 am very happy with the way the build system works these days.  I've
         9579 found it invaluable to have good examples of Autotools incantations to
         9580 copy&amp;amp;paste, so hopefully this will be useful to someone else.&lt;/p&gt;
         9581 &lt;p&gt;There are some subtleties that a "good" autotools setup demands, and
         9582 so far I think librsvg is doing well:&lt;/p&gt;
         9583 &lt;ul&gt;
         9584 &lt;li&gt;
         9585 &lt;p&gt;The &lt;code&gt;configure&lt;/code&gt; script checks for &lt;code&gt;cargo&lt;/code&gt; and &lt;code&gt;rustc&lt;/code&gt;.&lt;/p&gt;
         9586 &lt;/li&gt;
         9587 &lt;li&gt;
         9588 &lt;p&gt;"&lt;code&gt;make distcheck&lt;/code&gt;" works.  This means that the build can be
         9589   performed with &lt;code&gt;builddir != srcdir&lt;/code&gt;, and also that &lt;code&gt;make check&lt;/code&gt; runs
         9590   the available tests and they all pass.&lt;/p&gt;
         9591 &lt;/li&gt;
         9592 &lt;li&gt;
         9593 &lt;p&gt;The &lt;code&gt;rsvg_internals&lt;/code&gt; library is built with Rust, and our
         9594   &lt;code&gt;Makefile.am&lt;/code&gt; calls &lt;code&gt;cargo build&lt;/code&gt; with the correct options.  It is
         9595   able to handle debug and release builds.&lt;/p&gt;
         9596 &lt;/li&gt;
         9597 &lt;li&gt;
         9598 &lt;p&gt;"&lt;code&gt;make clean&lt;/code&gt;" cleans up the Rust build directories as well.&lt;/p&gt;
         9599 &lt;/li&gt;
         9600 &lt;li&gt;
         9601 &lt;p&gt;If you change a &lt;code&gt;.rs&lt;/code&gt; file and type &lt;code&gt;make&lt;/code&gt;, only the necessary stuff
         9602   gets rebuilt.&lt;/p&gt;
         9603 &lt;/li&gt;
         9604 &lt;li&gt;
         9605 &lt;p&gt;Etcetera.  I think librsvg feels like a normal autotool'ed library.
         9606   Let's see how this is done.&lt;/p&gt;
         9607 &lt;/li&gt;
         9608 &lt;/ul&gt;
         9609 &lt;h1&gt;Librsvg's basic autotools setup&lt;/h1&gt;
         9610 &lt;p&gt;Librsvg started out with a fairly traditional autotools setup with a
         9611 &lt;a href="https://git.gnome.org/browse/librsvg/tree/configure.ac?h=2.41.1"&gt;&lt;code&gt;configure.ac&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://git.gnome.org/browse/librsvg/tree/Makefile.am?h=2.41.1"&gt;&lt;code&gt;Makefile.am&lt;/code&gt;&lt;/a&gt;.  For
         9612 historical reasons the &lt;code&gt;.[ch]&lt;/code&gt; source files live in the toplevel
         9613 &lt;code&gt;librsvg/&lt;/code&gt; directory, not in a &lt;code&gt;src&lt;/code&gt; subdirectory or something like
         9614 that.&lt;/p&gt;
         9615 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;librsvg
         9616 ├ configure.ac
         9617 ├ Makefile.am
         9618 ├ *.[ch]
         9619 ├ src/
         9620 ├ doc/
         9621 ├ tests/
         9622 └ win32/
         9623 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9624 
         9625 &lt;h1&gt;Adding Rust to the build&lt;/h1&gt;
         9626 &lt;p&gt;The Rust source code lives in &lt;a href="https://git.gnome.org/browse/librsvg/tree/rust?h=2.41.1"&gt;&lt;code&gt;librsvg/rust&lt;/code&gt;&lt;/a&gt;; that's
         9627 where &lt;a href="https://git.gnome.org/browse/librsvg/tree/rust/Cargo.toml?h=2.41.1"&gt;&lt;code&gt;Cargo.toml&lt;/code&gt;&lt;/a&gt; lives, and of course there is the conventional
         9628 &lt;code&gt;src&lt;/code&gt; subdirectory with the &lt;code&gt;*.rs&lt;/code&gt; files.&lt;/p&gt;
         9629 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;librsvg
         9630 ├ configure.ac
         9631 ├ Makefile.am
         9632 ├ *.[ch]
         9633 ├ src/
         9634 ├ rust/         &amp;lt;--- this is new!
         9635 │ ├ Cargo.toml
         9636 │ └ src/
         9637 ├ doc/
         9638 ├ tests/
         9639 └ win32/
         9640 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9641 
         9642 &lt;h2&gt;Detecting the presence of &lt;code&gt;cargo&lt;/code&gt; and &lt;code&gt;rustc&lt;/code&gt; in &lt;code&gt;configure.ac&lt;/code&gt;&lt;/h2&gt;
         9643 &lt;p&gt;This goes in &lt;code&gt;configure.ac&lt;/code&gt;:&lt;/p&gt;
         9644 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;AC_CHECK_PROG&lt;span class="o"&gt;(&lt;/span&gt;CARGO, &lt;span class="o"&gt;[&lt;/span&gt;cargo&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="o"&gt;[&lt;/span&gt;yes&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="o"&gt;[&lt;/span&gt;no&lt;span class="o"&gt;])&lt;/span&gt;
         9645 AS_IF&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt; x&lt;span class="nv"&gt;$CARGO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; xno,
         9646     AC_MSG_ERROR&lt;span class="o"&gt;([&lt;/span&gt;cargo is required.  Please install the Rust toolchain from https://www.rust-lang.org/&lt;span class="o"&gt;])&lt;/span&gt;
         9647 &lt;span class="o"&gt;)&lt;/span&gt;
         9648 AC_CHECK_PROG&lt;span class="o"&gt;(&lt;/span&gt;RUSTC, &lt;span class="o"&gt;[&lt;/span&gt;rustc&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="o"&gt;[&lt;/span&gt;yes&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="o"&gt;[&lt;/span&gt;no&lt;span class="o"&gt;])&lt;/span&gt;
         9649 AS_IF&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt; x&lt;span class="nv"&gt;$RUSTC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; xno,
         9650     AC_MSG_ERROR&lt;span class="o"&gt;([&lt;/span&gt;rustc is required.  Please install the Rust toolchain from https://www.rust-lang.org/&lt;span class="o"&gt;])&lt;/span&gt;
         9651 &lt;span class="o"&gt;)&lt;/span&gt;
         9652 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9653 
         9654 &lt;p&gt;These two try to execute &lt;code&gt;cargo&lt;/code&gt; and &lt;code&gt;rustc&lt;/code&gt;, respectively, and abort
         9655 with an error message if they are not present.&lt;/p&gt;
         9656 &lt;h2&gt;Supporting debug or release mode for the Rust build&lt;/h2&gt;
         9657 &lt;p&gt;One can call cargo like "&lt;code&gt;cargo build --release&lt;/code&gt;" to turn on expensive
         9658 optimizations, or normally like just "&lt;code&gt;cargo build&lt;/code&gt;" to build with
         9659 debug information.  That is, the latter is the default:  if you don't
         9660 pass any options, cargo does a debug build.&lt;/p&gt;
         9661 &lt;p&gt;Autotools and C compilers normally work a bit differently; one must
         9662 call the configure script like "&lt;code&gt;CFLAGS='-g -O0' ./configure&lt;/code&gt;" for a
         9663 debug build, or "&lt;code&gt;CFLAGS='-O2 -fomit-frame-pointer' ./configure&lt;/code&gt;" for
         9664 a release build.&lt;/p&gt;
         9665 &lt;p&gt;Linux distros already have all the infrastructure to pass the
         9666 appropriate &lt;code&gt;CFLAGS&lt;/code&gt; to &lt;code&gt;configure&lt;/code&gt;.  We need to be able to pass the
         9667 appropriate flag to Cargo.  My main requirement for this was:&lt;/p&gt;
         9668 &lt;ul&gt;
         9669 &lt;li&gt;Distros shouldn't have to substantially change their RPM specfiles
         9670   (or whatever) to accomodate the Rust build.&lt;/li&gt;
         9671 &lt;li&gt;I assume that distros will want to make release builds by default.&lt;/li&gt;
         9672 &lt;li&gt;I as a developer am comfortable with passing extra options to make
         9673   debug builds on my machine.&lt;/li&gt;
         9674 &lt;/ul&gt;
         9675 &lt;p&gt;The scheme in librsvg lets you run "&lt;code&gt;configure --enable-debug&lt;/code&gt;" to
         9676 make it call a plain &lt;code&gt;cargo build&lt;/code&gt;, or a plain "&lt;code&gt;configure&lt;/code&gt;" to make
         9677 it use &lt;code&gt;cargo build --release&lt;/code&gt; instead.  The &lt;code&gt;CFLAGS&lt;/code&gt; are passed as
         9678 usual through an environment variable.  This way, distros don't have
         9679 to change their packaging to keep on making release builds as usual.&lt;/p&gt;
         9680 &lt;p&gt;This goes in &lt;code&gt;configure.ac&lt;/code&gt;:&lt;/p&gt;
         9681 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;dnl Specify --enable-debug to make a development release.  By default,
         9682 dnl we build &lt;span class="k"&gt;in&lt;/span&gt; public release mode.
         9683 
         9684 AC_ARG_ENABLE&lt;span class="o"&gt;(&lt;/span&gt;debug,
         9685               AC_HELP_STRING&lt;span class="o"&gt;([&lt;/span&gt;--enable-debug&lt;span class="o"&gt;]&lt;/span&gt;,
         9686                              &lt;span class="o"&gt;[&lt;/span&gt;Build Rust code with debugging information &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;no&lt;span class="o"&gt;]])&lt;/span&gt;,
         9687               &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;debug_release&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$enableval&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
         9688               &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;debug_release&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;no&lt;span class="o"&gt;])&lt;/span&gt;
         9689 
         9690 AC_MSG_CHECKING&lt;span class="o"&gt;(&lt;/span&gt;whether to build Rust code with debugging information&lt;span class="o"&gt;)&lt;/span&gt;
         9691 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;x&lt;/span&gt;&lt;span class="nv"&gt;$debug_release&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;xyes&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
         9692     AC_MSG_RESULT&lt;span class="o"&gt;(&lt;/span&gt;yes&lt;span class="o"&gt;)&lt;/span&gt;
         9693     &lt;span class="nv"&gt;RUST_TARGET_SUBDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;debug
         9694 &lt;span class="k"&gt;else&lt;/span&gt;
         9695     AC_MSG_RESULT&lt;span class="o"&gt;(&lt;/span&gt;no&lt;span class="o"&gt;)&lt;/span&gt;
         9696     &lt;span class="nv"&gt;RUST_TARGET_SUBDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;release
         9697 &lt;span class="k"&gt;fi&lt;/span&gt;
         9698 AM_CONDITIONAL&lt;span class="o"&gt;([&lt;/span&gt;DEBUG_RELEASE&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;x&lt;/span&gt;&lt;span class="nv"&gt;$debug_release&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;xyes&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
         9699 
         9700 AC_SUBST&lt;span class="o"&gt;([&lt;/span&gt;RUST_TARGET_SUBDIR&lt;span class="o"&gt;])&lt;/span&gt;
         9701 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9702 
         9703 &lt;p&gt;This defines an Automake conditional called &lt;code&gt;DEBUG_RELEASE&lt;/code&gt;, which we
         9704 will use in &lt;code&gt;Makefile.am&lt;/code&gt; later.&lt;/p&gt;
         9705 &lt;p&gt;It also causes &lt;code&gt;@RUST_TARGET_SUBDIR@&lt;/code&gt; to be substituted in Makefile.am
         9706 with either &lt;code&gt;debug&lt;/code&gt; or &lt;code&gt;release&lt;/code&gt;; we will see what these are about.&lt;/p&gt;
         9707 &lt;h2&gt;Adding Rust source files&lt;/h2&gt;
         9708 &lt;p&gt;The &lt;code&gt;librsvg/rust/src&lt;/code&gt; directory has all the &lt;code&gt;*.rs&lt;/code&gt; files, and cargo
         9709 tracks their dependencies and whether they need to be rebuilt if one changes.
         9710 However, since that directory is not tracked by &lt;code&gt;make&lt;/code&gt;, it won't
         9711 rebuild things if a Rust source file changes!  So, we need to tell our
         9712 &lt;code&gt;Makefile.am&lt;/code&gt; about those files:&lt;/p&gt;
         9713 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;RUST_SOURCES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;                   &lt;span class="se"&gt;\&lt;/span&gt;
         9714         rust/build.rs            &lt;span class="se"&gt;\&lt;/span&gt;
         9715         rust/Cargo.toml          &lt;span class="se"&gt;\&lt;/span&gt;
         9716         rust/src/aspect_ratio.rs &lt;span class="se"&gt;\&lt;/span&gt;
         9717         rust/src/bbox.rs         &lt;span class="se"&gt;\&lt;/span&gt;
         9718         rust/src/cnode.rs        &lt;span class="se"&gt;\&lt;/span&gt;
         9719         rust/src/color.rs        &lt;span class="se"&gt;\&lt;/span&gt;
         9720         ...
         9721 
         9722 &lt;span class="nv"&gt;RUST_EXTRA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;                     &lt;span class="se"&gt;\&lt;/span&gt;
         9723         rust/Cargo.lock
         9724 
         9725 &lt;span class="nv"&gt;EXTRA_DIST&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;RUST_SOURCES&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;RUST_EXTRA&lt;span class="k"&gt;)&lt;/span&gt;
         9726 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9727 
         9728 &lt;p&gt;It's a bit unfortunate that the change tracking is duplicated in the
         9729 &lt;code&gt;Makefile&lt;/code&gt;, but we are already used to listing all the C source files
         9730 in there, anyway.&lt;/p&gt;
         9731 &lt;p&gt;Most notably, the &lt;code&gt;rust&lt;/code&gt; subdirectory is &lt;em&gt;not&lt;/em&gt; listed in the &lt;code&gt;SUBDIRS&lt;/code&gt;
         9732 in &lt;code&gt;Makefile.am&lt;/code&gt;, since there is no &lt;code&gt;rust/Makefile&lt;/code&gt; at all!&lt;/p&gt;
         9733 &lt;h2&gt;Cargo release or debug build?&lt;/h2&gt;
         9734 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;if DEBUG_RELEASE&lt;/span&gt;
         9735 &lt;span class="nv"&gt;CARGO_RELEASE_ARGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
         9736 &lt;span class="cp"&gt;else&lt;/span&gt;
         9737 &lt;span class="nv"&gt;CARGO_RELEASE_ARGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;--release
         9738 &lt;span class="cp"&gt;endif&lt;/span&gt;
         9739 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9740 
         9741 &lt;p&gt;We will call &lt;code&gt;cargo build&lt;/code&gt; with that argument later.&lt;/p&gt;
         9742 &lt;h2&gt;Verbose or quiet build?&lt;/h2&gt;
         9743 &lt;p&gt;Librsvg uses &lt;code&gt;AM_SILENT_RULES([yes])&lt;/code&gt; in &lt;code&gt;configure.ac&lt;/code&gt;.  This lets
         9744 you just run "&lt;code&gt;make&lt;/code&gt;" for a quiet build, or "&lt;code&gt;make V=1&lt;/code&gt;" to get the
         9745 full command lines passed to the compiler.  Cargo supports something
         9746 similar, so let's add it to &lt;code&gt;Makefile.am&lt;/code&gt;:&lt;/p&gt;
         9747 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;CARGO_VERBOSE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;cargo_verbose_&lt;span class="k"&gt;$(&lt;/span&gt;V&lt;span class="k"&gt;))&lt;/span&gt;
         9748 &lt;span class="nv"&gt;cargo_verbose_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;cargo_verbose_&lt;span class="k"&gt;$(&lt;/span&gt;AM_DEFAULT_VERBOSITY&lt;span class="k"&gt;))&lt;/span&gt;
         9749 &lt;span class="nv"&gt;cargo_verbose_0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
         9750 &lt;span class="nv"&gt;cargo_verbose_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; --verbose
         9751 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9752 
         9753 &lt;p&gt;This expands the &lt;code&gt;V&lt;/code&gt; variable to empty, &lt;code&gt;0&lt;/code&gt;, or &lt;code&gt;1&lt;/code&gt;.  The result of
         9754 expanding &lt;em&gt;that&lt;/em&gt; gives us the final command-line argument in the
         9755 &lt;code&gt;CARGO_VERBOSE&lt;/code&gt; variable.&lt;/p&gt;
         9756 &lt;h2&gt;What's the filename of the library we are building?&lt;/h2&gt;
         9757 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;RUST_LIB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;@abs_top_builddir@/rust/target/@RUST_TARGET_SUBDIR@/librsvg_internals.a
         9758 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9759 
         9760 &lt;p&gt;Remember our &lt;code&gt;@RUST_TARGET_SUBDIR@&lt;/code&gt; from &lt;code&gt;configure.ac&lt;/code&gt;?  If you call
         9761 plain "&lt;code&gt;cargo build&lt;/code&gt;", it will put the binaries in
         9762 &lt;code&gt;rust/target/debug&lt;/code&gt;.  But if you call "&lt;code&gt;cargo build --release&lt;/code&gt;", it
         9763 will put the binaries in &lt;code&gt;rust/target/release&lt;/code&gt;.&lt;/p&gt;
         9764 &lt;p&gt;With the bit above, the &lt;code&gt;RUST_LIB&lt;/code&gt; variable now has the correct path
         9765 for the built library.  The &lt;code&gt;@abs_top_builddir@&lt;/code&gt; makes it work when
         9766 the build directory is not the same as the source directory.&lt;/p&gt;
         9767 &lt;h2&gt;Okay, so how do we call &lt;code&gt;cargo&lt;/code&gt;?&lt;/h2&gt;
         9768 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;@abs_top_builddir@/rust/target/@RUST_TARGET_SUBDIR@/librsvg_internals.a&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;RUST_SOURCES&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
         9769     &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;top_srcdir&lt;span class="k"&gt;)&lt;/span&gt;/rust &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         9770     &lt;span class="nv"&gt;CARGO_TARGET_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;@abs_top_builddir@/rust/target cargo build &lt;span class="k"&gt;$(&lt;/span&gt;CARGO_VERBOSE&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;CARGO_RELEASE_ARGS&lt;span class="k"&gt;)&lt;/span&gt;
         9771 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9772 
         9773 &lt;p&gt;We make the funky library filename depend on &lt;code&gt;$(RUST_SOURCES)&lt;/code&gt;.
         9774 That's what will cause &lt;code&gt;make&lt;/code&gt; to rebuild the Rust library if one of
         9775 the Rust source files changes.&lt;/p&gt;
         9776 &lt;p&gt;We override the &lt;code&gt;CARGO_TARGET_DIR&lt;/code&gt; with Automake's preference, and
         9777 call &lt;code&gt;cargo build&lt;/code&gt; with the correct arguments.&lt;/p&gt;
         9778 &lt;h2&gt;Linking into the main C library&lt;/h2&gt;
         9779 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;librsvg_@RSVG_API_MAJOR_VERSION@&lt;/span&gt;&lt;span class="nv"&gt;_la_LIBADD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         9780         &lt;span class="k"&gt;$(&lt;/span&gt;LIBRSVG_LIBS&lt;span class="k"&gt;)&lt;/span&gt;                      &lt;span class="se"&gt;\&lt;/span&gt;
         9781         &lt;span class="k"&gt;$(&lt;/span&gt;LIBM&lt;span class="k"&gt;)&lt;/span&gt;                              &lt;span class="se"&gt;\&lt;/span&gt;
         9782         &lt;span class="k"&gt;$(&lt;/span&gt;RUST_LIB&lt;span class="k"&gt;)&lt;/span&gt;
         9783 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9784 
         9785 &lt;p&gt;This expands our &lt;code&gt;$(RUST_LIB)&lt;/code&gt; from above into our linker line, along
         9786 with librsvg's other dependencies.&lt;/p&gt;
         9787 &lt;h2&gt;&lt;code&gt;make check&lt;/code&gt;&lt;/h2&gt;
         9788 &lt;p&gt;This is our hook so that &lt;code&gt;make check&lt;/code&gt; will cause &lt;code&gt;cargo test&lt;/code&gt; to run:&lt;/p&gt;
         9789 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;check-local&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
         9790         &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;srcdir&lt;span class="k"&gt;)&lt;/span&gt;/rust &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         9791         &lt;span class="nv"&gt;CARGO_TARGET_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;@abs_top_builddir@/rust/target cargo &lt;span class="nb"&gt;test&lt;/span&gt;
         9792 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9793 
         9794 &lt;h2&gt;&lt;code&gt;make clean&lt;/code&gt;&lt;/h2&gt;
         9795 &lt;p&gt;Same thing for &lt;code&gt;make clean&lt;/code&gt; and &lt;code&gt;cargo clean&lt;/code&gt;:&lt;/p&gt;
         9796 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;clean-local&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
         9797         &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;top_srcdir&lt;span class="k"&gt;)&lt;/span&gt;/rust &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         9798         &lt;span class="nv"&gt;CARGO_TARGET_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;@abs_top_builddir@/rust/target cargo clean
         9799 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9800 
         9801 &lt;h1&gt;Vendoring dependencies&lt;/h1&gt;
         9802 &lt;p&gt;Linux distros probably want Rust packages to come bundled with their
         9803 dependencies, so that they can replace them later with newer/patched
         9804 versions.&lt;/p&gt;
         9805 &lt;p&gt;Here is a hook so that &lt;code&gt;make dist&lt;/code&gt; will cause &lt;code&gt;cargo vendor&lt;/code&gt; to be
         9806 run before making the tarball.  That command will creates a
         9807 &lt;code&gt;rust/vendor&lt;/code&gt; directory with a copy of all the Rust crates that
         9808 librsvg depends on.&lt;/p&gt;
         9809 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;RUST_EXTRA&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; rust/cargo-vendor-config
         9810 
         9811 &lt;span class="nf"&gt;dist-hook&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
         9812     &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;distdir&lt;span class="k"&gt;)&lt;/span&gt;/rust &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         9813     cargo vendor -q &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         9814     mkdir .cargo &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         9815     cp cargo-vendor-config .cargo/config&lt;span class="o"&gt;)&lt;/span&gt;
         9816 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9817 
         9818 &lt;p&gt;The tarball needs to have a &lt;code&gt;rust/.cargo/config&lt;/code&gt; to know where to find
         9819 the vendored sources (i.e. the embedded dependencies), but we don't
         9820 want &lt;em&gt;that&lt;/em&gt; in our development source tree.  Instead, we generate it
         9821 from a &lt;a href="https://git.gnome.org/browse/librsvg/tree/rust/cargo-vendor-config?h=2.41.1"&gt;&lt;code&gt;rust/cargo-vendor-config&lt;/code&gt;&lt;/a&gt; file in our
         9822 source tree:&lt;/p&gt;
         9823 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# This is used after `cargo vendor` is run from `make dist`.&lt;/span&gt;
         9824 &lt;span class="c1"&gt;#&lt;/span&gt;
         9825 &lt;span class="c1"&gt;# In the distributed tarball, this file should end up in&lt;/span&gt;
         9826 &lt;span class="c1"&gt;# rust/.cargo/config&lt;/span&gt;
         9827 
         9828 &lt;span class="k"&gt;[source.crates-io]&lt;/span&gt;
         9829 &lt;span class="n"&gt;registry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;https://github.com/rust-lang/crates.io-index&amp;#39;&lt;/span&gt;
         9830 &lt;span class="n"&gt;replace-with&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;vendored-sources&amp;#39;&lt;/span&gt;
         9831 
         9832 &lt;span class="k"&gt;[source.vendored-sources]&lt;/span&gt;
         9833 &lt;span class="n"&gt;directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;./vendor&amp;#39;&lt;/span&gt;
         9834 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9835 
         9836 &lt;h1&gt;One last thing&lt;/h1&gt;
         9837 &lt;p&gt;If you put this in your &lt;code&gt;Cargo.toml&lt;/code&gt;, release binaries will be a lot
         9838 smaller.  This turns on link-time optimizations (LTO), which removes
         9839 unused functions from the binary.&lt;/p&gt;
         9840 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[profile.release]&lt;/span&gt;
         9841 &lt;span class="n"&gt;lto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
         9842 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9843 
         9844 &lt;h1&gt;Summary and thanks&lt;/h1&gt;
         9845 &lt;p&gt;I think the above is some good boilerplate that you can put in your
         9846 &lt;code&gt;configure.ac&lt;/code&gt; / &lt;code&gt;Makefile.am&lt;/code&gt; to integrate a Rust sub-library into
         9847 your C code.  It handles &lt;code&gt;make&lt;/code&gt;-y things like &lt;code&gt;make clean&lt;/code&gt; and &lt;code&gt;make
         9848 check&lt;/code&gt;; debug and release builds; verbose and quiet builds;
         9849 &lt;code&gt;builddir != srcdir&lt;/code&gt;; all the goodies.&lt;/p&gt;
         9850 &lt;p&gt;I think the only thing I'm missing is to check for the &lt;code&gt;cargo-vendor&lt;/code&gt;
         9851 binary.  I'm not sure how to only check for that if I'm the one making
         9852 tarballs... maybe an &lt;code&gt;--enable-maintainer-mode&lt;/code&gt; flag?&lt;/p&gt;
         9853 &lt;p&gt;This would definitely not have been possible without prior work.
         9854 Thanks to everyone who figured out Autotools before me, so I could
         9855 cut&amp;amp;paste your goodies:&lt;/p&gt;
         9856 &lt;p&gt;&lt;em&gt;Update 2017/Nov/11:&lt;/em&gt; Fixed the initialization of &lt;code&gt;RUST_EXTRA&lt;/code&gt;; thanks
         9857 to Tobias Mueller for catching this.&lt;/p&gt;
         9858 &lt;ul&gt;
         9859 &lt;li&gt;&lt;a href="https://www.figuiere.net/hub/blog/?2016/10/07/862-rust-and-automake"&gt;Hubert Figuière's "Rust and Automake"&lt;/a&gt;&lt;/li&gt;
         9860 &lt;li&gt;&lt;a href="http://lukenukem.co.nz/gsoc/2017/05/17/gso_2.html"&gt;Luke Nukem's "Autotools and Rust"&lt;/a&gt;&lt;/li&gt;
         9861 &lt;li&gt;&lt;a href="https://github.com/endlessm/ostree/commit/9169268c31df31cc09495e2a04c30cd251f22b5d"&gt;OStree's incantation for &lt;code&gt;cargo vendor&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
         9862 &lt;li&gt;&lt;a href="https://blog.ometer.com/2017/01/10/dear-package-managers-dependency-resolution-results-should-be-in-version-control/"&gt;Havoc's "Cargo.lock should be in version control"&lt;/a&gt;&lt;/li&gt;
         9863 &lt;/ul&gt;</content><category term="misc"></category><category term="librsvg"></category><category term="rust"></category><category term="gnome"></category><category term="autotools"></category></entry><entry><title>How Glib-rs works, part 2: Transferring lists and arrays</title><link href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-2.html" rel="alternate"></link><published>2017-08-28T20:26:47-05:00</published><updated>2017-08-28T20:26:47-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-08-28:/~federico/blog/how-glib-rs-works-part-2.html</id><summary type="html">&lt;p&gt;(&lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html"&gt;First part&lt;/a&gt; of the series, with index to all the articles)&lt;/p&gt;
         9864 &lt;p&gt;In the &lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html"&gt;first part&lt;/a&gt;, we saw how &lt;a href="http://gtk-rs.org/docs/glib/"&gt;glib-rs&lt;/a&gt; provides
         9865 the &lt;a href="http://gtk-rs.org/docs/glib/translate/trait.FromGlib.html"&gt;&lt;code&gt;FromGlib&lt;/code&gt;&lt;/a&gt; and &lt;a href="http://gtk-rs.org/docs/glib/translate/trait.ToGlib.html"&gt;&lt;code&gt;ToGlib&lt;/code&gt;&lt;/a&gt; traits to let Rust
         9866 code convert from/to Glib's simple types, like to convert from a Glib
         9867 &lt;code&gt;gboolean&lt;/code&gt; to a Rust &lt;code&gt;bool&lt;/code&gt; and vice-versa.  We also …&lt;/p&gt;</summary><content type="html">&lt;p&gt;(&lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html"&gt;First part&lt;/a&gt; of the series, with index to all the articles)&lt;/p&gt;
         9868 &lt;p&gt;In the &lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html"&gt;first part&lt;/a&gt;, we saw how &lt;a href="http://gtk-rs.org/docs/glib/"&gt;glib-rs&lt;/a&gt; provides
         9869 the &lt;a href="http://gtk-rs.org/docs/glib/translate/trait.FromGlib.html"&gt;&lt;code&gt;FromGlib&lt;/code&gt;&lt;/a&gt; and &lt;a href="http://gtk-rs.org/docs/glib/translate/trait.ToGlib.html"&gt;&lt;code&gt;ToGlib&lt;/code&gt;&lt;/a&gt; traits to let Rust
         9870 code convert from/to Glib's simple types, like to convert from a Glib
         9871 &lt;code&gt;gboolean&lt;/code&gt; to a Rust &lt;code&gt;bool&lt;/code&gt; and vice-versa.  We also saw the special
         9872 needs of strings; since they are passed by reference and are not
         9873 copied as simple values, we can use
         9874 &lt;a href="http://gtk-rs.org/docs/glib/translate/trait.FromGlibPtrNone.html"&gt;&lt;code&gt;FromGlibPtrNone&lt;/code&gt;&lt;/a&gt; and
         9875 &lt;a href="http://gtk-rs.org/docs/glib/translate/trait.FromGlibPtrFull.html"&gt;&lt;code&gt;FromGlibPtrFull&lt;/code&gt;&lt;/a&gt; depending on what kind of
         9876 &lt;em&gt;ownership transfer&lt;/em&gt; we want, none for "just make it look like we are
         9877 using a borrowed reference", or full for "I'll take over the data and
         9878 free it when I'm done".  Going the other way around, we can use
         9879 &lt;a href="http://gtk-rs.org/docs/glib/translate/trait.ToGlibPtr.html"&gt;&lt;code&gt;ToGlibPtr&lt;/code&gt;&lt;/a&gt; and its methods to pass things from Rust &lt;em&gt;to&lt;/em&gt;
         9880 Glib.&lt;/p&gt;
         9881 &lt;p&gt;In this part, we'll see the tools that glib-rs provides to do
         9882 conversions of more complex data types.  We'll look at two cases:&lt;/p&gt;
         9883 &lt;ul&gt;
         9884 &lt;li&gt;
         9885 &lt;p&gt;&lt;a href="#null-term-string-array"&gt;Passing null-terminated arrays of strings&lt;/a&gt;
         9886   from Glib to Rust&lt;/p&gt;
         9887 &lt;/li&gt;
         9888 &lt;li&gt;
         9889 &lt;p&gt;&lt;a href="#passing-glists"&gt;Passing &lt;code&gt;GList&lt;/code&gt;s to Rust&lt;/a&gt;&lt;/p&gt;
         9890 &lt;/li&gt;
         9891 &lt;/ul&gt;
         9892 &lt;p&gt;And one final case just in passing:&lt;/p&gt;
         9893 &lt;ul&gt;
         9894 &lt;li&gt;&lt;a href="#passing-containers-to-glib"&gt;Passing containers from Rust to Glib&lt;/a&gt;&lt;/li&gt;
         9895 &lt;/ul&gt;
         9896 &lt;h1&gt;Passing arrays from Glib to Rust&lt;/h1&gt;
         9897 &lt;p&gt;We'll look at the case for transferring null-terminated arrays of
         9898 strings, since it's an interesting one.  There are other traits to
         9899 convert from Glib arrays whose length is known, not implied with a
         9900 NULL element, but for now we'll only look at arrays of strings.&lt;/p&gt;
         9901 &lt;h2 id="null-term-string-array"&gt;Null-terminated arrays of strings&lt;/h2&gt;
         9902 &lt;p&gt;Look at this function for &lt;code&gt;GtkAboutDialog&lt;/code&gt;:&lt;/p&gt;
         9903 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cm"&gt;/**&lt;/span&gt;
         9904 &lt;span class="cm"&gt; * gtk_about_dialog_add_credit_section:&lt;/span&gt;
         9905 &lt;span class="cm"&gt; * @about: A #GtkAboutDialog&lt;/span&gt;
         9906 &lt;span class="cm"&gt; * @section_name: The name of the section&lt;/span&gt;
         9907 &lt;span class="cm"&gt; * @people: (array zero-terminated=1): The people who belong to that section&lt;/span&gt;
         9908 &lt;span class="cm"&gt; * ...&lt;/span&gt;
         9909 &lt;span class="cm"&gt; */&lt;/span&gt;
         9910 &lt;span class="kt"&gt;void&lt;/span&gt;
         9911 &lt;span class="n"&gt;gtk_about_dialog_add_credit_section&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GtkAboutDialog&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;about&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         9912                                      &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;gchar&lt;/span&gt;     &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;section_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         9913                                      &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;gchar&lt;/span&gt;    &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         9914 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9915 
         9916 &lt;p&gt;You would use this like&lt;/p&gt;
         9917 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;gchar&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;translators&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         9918     &lt;span class="s"&gt;&amp;quot;Alice &amp;lt;alice@example.com&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         9919     &lt;span class="s"&gt;&amp;quot;Bob &amp;lt;bob@example.com&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         9920     &lt;span class="s"&gt;&amp;quot;Clara &amp;lt;clara@example.com&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         9921     &lt;span class="nb"&gt;NULL&lt;/span&gt;
         9922 &lt;span class="p"&gt;};&lt;/span&gt;
         9923 
         9924 &lt;span class="n"&gt;gtk_about_dialog_add_credit_section&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_about_dialog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Translators&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;translators&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         9925 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9926 
         9927 &lt;p&gt;The function expects an array of &lt;code&gt;gchar *&lt;/code&gt;, where the last element is
         9928 a NULL.  Instead of passing an explicit length for the array, it's
         9929 done implicitly by requiring a NULL pointer after the last element.
         9930 The gtk-doc annotation says &lt;code&gt;(array zero-terminated=1)&lt;/code&gt;.  When we
         9931 generate information for the GObject-Introspection Repository (GIR),
         9932 this is what comes out:&lt;/p&gt;
         9933 &lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
         9934 &lt;span class="normal"&gt; 2&lt;/span&gt;
         9935 &lt;span class="normal"&gt; 3&lt;/span&gt;
         9936 &lt;span class="normal"&gt; 4&lt;/span&gt;
         9937 &lt;span class="normal"&gt; 5&lt;/span&gt;
         9938 &lt;span class="normal"&gt; 6&lt;/span&gt;
         9939 &lt;span class="normal"&gt; 7&lt;/span&gt;
         9940 &lt;span class="normal"&gt; 8&lt;/span&gt;
         9941 &lt;span class="normal"&gt; 9&lt;/span&gt;
         9942 &lt;span class="normal"&gt;10&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;method&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;add_credit_section&amp;quot;&lt;/span&gt;
         9943         &lt;span class="na"&gt;c:identifier=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gtk_about_dialog_add_credit_section&amp;quot;&lt;/span&gt;
         9944         &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.4&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9945   ..
         9946     &lt;span class="nt"&gt;&amp;lt;parameter&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;people&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;transfer-ownership=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9947       &lt;span class="nt"&gt;&amp;lt;doc&lt;/span&gt; &lt;span class="na"&gt;xml:space=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;preserve&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;The people who belong to that section&lt;span class="nt"&gt;&amp;lt;/doc&amp;gt;&lt;/span&gt;
         9948       &lt;span class="nt"&gt;&amp;lt;array&lt;/span&gt; &lt;span class="na"&gt;c:type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gchar**&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         9949         &lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;utf8&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;c:type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gchar*&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         9950       &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
         9951     &lt;span class="nt"&gt;&amp;lt;/parameter&amp;gt;&lt;/span&gt;
         9952 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9953 &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
         9954 &lt;p&gt;You can see the &lt;code&gt;transfer-ownership="none"&lt;/code&gt; in line 5.  This means
         9955 that the function will not take ownership of the passed array; it will
         9956 make its own copy instead.  By convention, GIR assumes that arrays of
         9957 strings are NULL-terminated, so there is no special annotation for
         9958 that here.  If we were implementing this function in Rust, how would we
         9959 read that C array of UTF-8 strings and turn it into a Rust
         9960 &lt;code&gt;Vec&amp;lt;String&amp;gt;&lt;/code&gt; or something?  Easy:&lt;/p&gt;
         9961 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char_array&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// comes from Glib&lt;/span&gt;
         9962 &lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rust_translators&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrContainer&lt;/span&gt;::&lt;span class="n"&gt;from_glib_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c_char_array&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9963 &lt;span class="c1"&gt;// rust_translators is a Vec&amp;lt;String&amp;gt;&lt;/span&gt;
         9964 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9965 
         9966 &lt;p&gt;Let's look at how this bad boy is implemented.&lt;/p&gt;
         9967 &lt;h3&gt;First stage: &lt;code&gt;impl FromGlibPtrContainer for Vec&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;
         9968 &lt;p&gt;We want to go from a "&lt;code&gt;*mut *mut c_char&lt;/code&gt;" (in C parlance, a "&lt;code&gt;gchar **&lt;/code&gt;")
         9969 to a &lt;code&gt;Vec&amp;lt;String&amp;gt;&lt;/code&gt;.  Indeed, there is an implementation of the
         9970 &lt;code&gt;FromGlibPtrContainer&lt;/code&gt; trait for &lt;code&gt;Vec&lt;/code&gt;s
         9971 &lt;a href="https://github.com/gtk-rs/glib/blob/e46aa7f27cc74f3cdcb54d94feb4a8861df21c7f/src/translate.rs#L1136"&gt;here&lt;/a&gt;.  These are the first few lines:&lt;/p&gt;
         9972 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;: &lt;span class="nc"&gt;Ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PP&lt;/span&gt;: &lt;span class="nc"&gt;Ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;: &lt;span class="nc"&gt;FromGlibPtrArrayContainerAsVec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PP&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PP&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9973 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_glib_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="nc"&gt;PP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9974 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrArrayContainerAsVec&lt;/span&gt;::&lt;span class="n"&gt;from_glib_none_as_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9975 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9976 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9977 
         9978 &lt;p&gt;So... that &lt;code&gt;from_glib_none()&lt;/code&gt; will return a &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt;, which is what we
         9979 want.  Let's look at the first few lines of &lt;a href="https://github.com/gtk-rs/glib/blob/e46aa7f27cc74f3cdcb54d94feb4a8861df21c7f/src/translate.rs#L1087"&gt;&lt;code&gt;FromGlibPtrArrayContainerAsVec&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
         9980 &lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
         9981 &lt;span class="normal"&gt;2&lt;/span&gt;
         9982 &lt;span class="normal"&gt;3&lt;/span&gt;
         9983 &lt;span class="normal"&gt;4&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrArrayContainerAsVec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cp"&gt;$ffi_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$ffi_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9984 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_glib_none_as_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$ffi_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9985 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;FromGlibContainerAsVec&lt;/span&gt;::&lt;span class="n"&gt;from_glib_none_num_as_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_ptr_array_len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9986 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
         9987 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
         9988 &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
         9989 &lt;p&gt;Aha!  This is inside a &lt;a href="https://github.com/gtk-rs/glib/blob/e46aa7f27cc74f3cdcb54d94feb4a8861df21c7f/src/translate.rs#L1117"&gt;macro&lt;/a&gt;, thus the &lt;code&gt;$ffi_name&lt;/code&gt; garbage.
         9990 It's done like that so the same trait can be implemented for &lt;code&gt;const&lt;/code&gt; and
         9991 &lt;code&gt;mut&lt;/code&gt; pointers to &lt;code&gt;c_char&lt;/code&gt;.&lt;/p&gt;
         9992 &lt;p&gt;See the call to &lt;code&gt;c_ptr_array_len()&lt;/code&gt; in line 3?  That's what figures
         9993 out where the NULL pointer is at the end of the array: it figures out
         9994 the array's length. &lt;/p&gt;
         9995 &lt;h3&gt;Second stage: &lt;code&gt;impl FromGlibContainerAsVec::from_glib_none_num_as_vec()&lt;/code&gt;&lt;/h3&gt;
         9996 &lt;p&gt;Now that the length of the array is known, the implementation calls
         9997 &lt;a href="https://github.com/gtk-rs/glib/blob/e46aa7f27cc74f3cdcb54d94feb4a8861df21c7f/src/translate.rs#L1038"&gt;&lt;code&gt;FromGlibContainerAsVec::from_glib_none_num_as_vec()&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
         9998 &lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
         9999 &lt;span class="normal"&gt; 2&lt;/span&gt;
        10000 &lt;span class="normal"&gt; 3&lt;/span&gt;
        10001 &lt;span class="normal"&gt; 4&lt;/span&gt;
        10002 &lt;span class="normal"&gt; 5&lt;/span&gt;
        10003 &lt;span class="normal"&gt; 6&lt;/span&gt;
        10004 &lt;span class="normal"&gt; 7&lt;/span&gt;
        10005 &lt;span class="normal"&gt; 8&lt;/span&gt;
        10006 &lt;span class="normal"&gt; 9&lt;/span&gt;
        10007 &lt;span class="normal"&gt;10&lt;/span&gt;
        10008 &lt;span class="normal"&gt;11&lt;/span&gt;
        10009 &lt;span class="normal"&gt;12&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibContainerAsVec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cp"&gt;$ffi_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$ffi_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10010 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_glib_none_num_as_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$ffi_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;: &lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10011 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10012 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10013 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10014 
        10015 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;::&lt;span class="n"&gt;with_capacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10016 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10017 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from_glib_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;::&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;isize&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$ffi_name&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10018 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10019 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10020 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10021 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10022 &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
        10023 &lt;p&gt;Lines 3/4: If the number of elements is zero, or the array is NULL,
        10024 return an empty &lt;code&gt;Vec&lt;/code&gt;.&lt;/p&gt;
        10025 &lt;p&gt;Line 7: Allocate a &lt;code&gt;Vec&lt;/code&gt; of suitable size.&lt;/p&gt;
        10026 &lt;p&gt;Lines 8/9: For each of the pointers in the C array, call
        10027 &lt;code&gt;from_glib_none()&lt;/code&gt; to convert it from a &lt;code&gt;*const c_char&lt;/code&gt; to a &lt;code&gt;String&lt;/code&gt;,
        10028 like we saw in &lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html"&gt;the first part&lt;/a&gt;.&lt;/p&gt;
        10029 &lt;p&gt;Done!  We started with a &lt;code&gt;*mut *mut c_char&lt;/code&gt; or a &lt;code&gt;*const *const
        10030 c_char&lt;/code&gt; and ended up with a &lt;code&gt;Vec&amp;lt;String&amp;gt;&lt;/code&gt;, which is what we wanted.&lt;/p&gt;
        10031 &lt;h1 id="passing-glists"&gt;Passing &lt;code&gt;GList&lt;/code&gt;s to Rust&lt;/h1&gt;
        10032 &lt;p&gt;Some functions don't give you an array; they give you a &lt;code&gt;GList&lt;/code&gt; or
        10033 &lt;code&gt;GSList&lt;/code&gt;.  There is an implementation of
        10034 &lt;code&gt;FromGlibPtrArrayContainerAsVec&lt;/code&gt; &lt;a href="https://github.com/gtk-rs/glib/blob/e46aa7f27cc74f3cdcb54d94feb4a8861df21c7f/src/translate.rs#L1254"&gt;that understands
        10035 &lt;code&gt;GList&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
        10036 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrArrayContainerAsVec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GlibPtrDefault&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;::&lt;span class="n"&gt;GlibType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;GList&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10037 &lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;: &lt;span class="nc"&gt;GlibPtrDefault&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrNone&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GlibPtrDefault&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;::&lt;span class="n"&gt;GlibType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrFull&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GlibPtrDefault&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;::&lt;span class="n"&gt;GlibType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10038 
        10039 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_glib_none_as_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;GList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10040 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;g_list_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10041 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;FromGlibContainer&lt;/span&gt;::&lt;span class="n"&gt;from_glib_none_num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10042 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10043 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10044 
        10045 &lt;p&gt;The &lt;code&gt;impl&lt;/code&gt; declaration is pretty horrible, so just look at the
        10046 method:  &lt;code&gt;from_glib_none_as_vec()&lt;/code&gt; takes in a &lt;code&gt;GList&lt;/code&gt;, then calls
        10047 &lt;code&gt;g_list_length()&lt;/code&gt; on it, and finally calls
        10048 &lt;code&gt;FromGlibContainer::from_glib_none_num()&lt;/code&gt; with the length it computed.&lt;/p&gt;
        10049 &lt;h3&gt;I have a Glib container and its length&lt;/h3&gt;
        10050 &lt;p&gt;In turn, that &lt;code&gt;from_glib_none_num()&lt;/code&gt; goes &lt;a href="https://github.com/gtk-rs/glib/blob/e46aa7f27cc74f3cdcb54d94feb4a8861df21c7f/src/translate.rs#L1122"&gt;here&lt;/a&gt;:&lt;/p&gt;
        10051 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PP&lt;/span&gt;: &lt;span class="nc"&gt;Ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;: &lt;span class="nc"&gt;FromGlibContainerAsVec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PP&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PP&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10052 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_glib_none_num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="nc"&gt;PP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;: &lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10053 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;FromGlibContainerAsVec&lt;/span&gt;::&lt;span class="n"&gt;from_glib_none_num_as_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10054 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10055 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10056 
        10057 &lt;p&gt;Okay, getting closer to the actual implementation.&lt;/p&gt;
        10058 &lt;h3&gt;Give me a vector already&lt;/h3&gt;
        10059 &lt;p&gt;Finally, we get to the function that &lt;a href="https://github.com/gtk-rs/glib/blob/e46aa7f27cc74f3cdcb54d94feb4a8861df21c7f/src/translate.rs#L1211"&gt;walks the &lt;code&gt;GList&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
        10060 &lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
        10061 &lt;span class="normal"&gt; 2&lt;/span&gt;
        10062 &lt;span class="normal"&gt; 3&lt;/span&gt;
        10063 &lt;span class="normal"&gt; 4&lt;/span&gt;
        10064 &lt;span class="normal"&gt; 5&lt;/span&gt;
        10065 &lt;span class="normal"&gt; 6&lt;/span&gt;
        10066 &lt;span class="normal"&gt; 7&lt;/span&gt;
        10067 &lt;span class="normal"&gt; 8&lt;/span&gt;
        10068 &lt;span class="normal"&gt; 9&lt;/span&gt;
        10069 &lt;span class="normal"&gt;10&lt;/span&gt;
        10070 &lt;span class="normal"&gt;11&lt;/span&gt;
        10071 &lt;span class="normal"&gt;12&lt;/span&gt;
        10072 &lt;span class="normal"&gt;13&lt;/span&gt;
        10073 &lt;span class="normal"&gt;14&lt;/span&gt;
        10074 &lt;span class="normal"&gt;15&lt;/span&gt;
        10075 &lt;span class="normal"&gt;16&lt;/span&gt;
        10076 &lt;span class="normal"&gt;17&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibContainerAsVec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GlibPtrDefault&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;::&lt;span class="n"&gt;GlibType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;GList&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10077 &lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;: &lt;span class="nc"&gt;GlibPtrDefault&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrNone&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GlibPtrDefault&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;::&lt;span class="n"&gt;GlibType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrFull&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GlibPtrDefault&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;::&lt;span class="n"&gt;GlibType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10078 
        10079 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_glib_none_num_as_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;GList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;: &lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10080 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10081 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10082 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10083 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;::&lt;span class="n"&gt;with_capacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10084 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10085 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;item_ptr&lt;/span&gt;: &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GlibPtrDefault&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;::&lt;span class="n"&gt;GlibType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ptr&lt;/span&gt;::&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10086 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;item_ptr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10087 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from_glib_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_ptr&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10088 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10089 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10090 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10091 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10092 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10093 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10094 &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
        10095 &lt;p&gt;Again, ignore the horrible &lt;code&gt;impl&lt;/code&gt; declaration and just look at
        10096 &lt;code&gt;from_glib_none_num_as_vec()&lt;/code&gt;.&lt;/p&gt;
        10097 &lt;p&gt;Line 4: that function takes in a &lt;code&gt;ptr&lt;/code&gt; to a &lt;code&gt;GList&lt;/code&gt;, and a &lt;code&gt;num&lt;/code&gt; with
        10098 the list's length, which we already computed above.&lt;/p&gt;
        10099 &lt;p&gt;Line 5: Return an empty vector if we have an empty list.&lt;/p&gt;
        10100 &lt;p&gt;Line 8: Allocate a vector of suitable capacity.&lt;/p&gt;
        10101 &lt;p&gt;Line 9: For each element, convert it with &lt;code&gt;from_glib_none()&lt;/code&gt; and push
        10102 it to the array.&lt;/p&gt;
        10103 &lt;p&gt;Line 14: Walk to the next element in the list.&lt;/p&gt;
        10104 &lt;h1 id="passing-containers-to-glib"&gt;Passing containers from Rust to Glib&lt;/h1&gt;
        10105 &lt;p&gt;This post is getting a bit long, so I'll just mention this briefly.
        10106 There is a trait &lt;code&gt;ToGlibContainerFromSlice&lt;/code&gt; that takes a Rust slice,
        10107 and can convert it to various Glib types.&lt;/p&gt;
        10108 &lt;ul&gt;
        10109 &lt;li&gt;
        10110 &lt;p&gt;To &lt;a href="https://github.com/gtk-rs/glib/blob/e46aa7f27cc74f3cdcb54d94feb4a8861df21c7f/src/translate.rs#L616"&gt;&lt;code&gt;GSlist&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/gtk-rs/glib/blob/e46aa7f27cc74f3cdcb54d94feb4a8861df21c7f/src/translate.rs#L566"&gt;&lt;code&gt;GList&lt;/code&gt;&lt;/a&gt;.  These have
        10111   methods like &lt;code&gt;to_glib_none_from_slice()&lt;/code&gt; and
        10112   &lt;code&gt;to_glib_full_from_slice()&lt;/code&gt;&lt;/p&gt;
        10113 &lt;/li&gt;
        10114 &lt;li&gt;
        10115 &lt;p&gt;To an &lt;a href="https://github.com/gtk-rs/glib/blob/e46aa7f27cc74f3cdcb54d94feb4a8861df21c7f/src/translate.rs#L471"&gt;array of fundamental types&lt;/a&gt;.  Here, you can choose
        10116   between &lt;code&gt;to_glib_none_from_slice()&lt;/code&gt;, which gives you a &lt;code&gt;Stash&lt;/code&gt; like
        10117   we saw &lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html"&gt;the last time&lt;/a&gt;.  Or, you can use
        10118   &lt;code&gt;to_glib_full_from_slice()&lt;/code&gt;, which gives you back a &lt;code&gt;g_malloc()&lt;/code&gt;ed
        10119   array with copied items.  Finally, &lt;code&gt;to_glib_container_from_slice()&lt;/code&gt;
        10120   gives you back a &lt;code&gt;g_malloc()&lt;/code&gt;ed array of &lt;em&gt;pointers&lt;/em&gt; to values rather
        10121   than plain values themselves.  Which function you choose depends on
        10122   which C API you want to call.&lt;/p&gt;
        10123 &lt;/li&gt;
        10124 &lt;/ul&gt;
        10125 &lt;p&gt;I hope this post gives you enough practice to be able to "follow the
        10126 traits" for each of those if you want to look at the implementations.&lt;/p&gt;
        10127 &lt;h1&gt;Next up&lt;/h1&gt;
        10128 &lt;p&gt;Passing boxed types, like public structs.&lt;/p&gt;
        10129 &lt;p&gt;Passing reference-counted types.&lt;/p&gt;
        10130 &lt;p&gt;How glib-rs wraps GObjects.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="gnome"></category></entry><entry><title>How Glib-rs works, part 1: Type conversions</title><link href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html" rel="alternate"></link><published>2017-08-25T16:07:47-05:00</published><updated>2017-08-25T16:07:47-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-08-25:/~federico/blog/how-glib-rs-works-part-1.html</id><summary type="html">&lt;ul&gt;
        10131 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html"&gt;How Glib-rs works, part 1: Type conversions&lt;/a&gt;&lt;/li&gt;
        10132 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-2.html"&gt;How Glib-rs works, part 2: Transferring lists and arrays&lt;/a&gt;&lt;/li&gt;
        10133 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-3.html"&gt;How Glib-rs works, part 3: Boxed types&lt;/a&gt;&lt;/li&gt;
        10134 &lt;/ul&gt;
        10135 &lt;p&gt;During the &lt;a href="https://wiki.gnome.org/Hackfests/Rust2017"&gt;GNOME+Rust hackfest in Mexico City&lt;/a&gt;, &lt;a href="http://smallcultfollowing.com/babysteps/"&gt;Niko Matsakis&lt;/a&gt;
        10136 started the implementation of &lt;a href="http://smallcultfollowing.com/babysteps/blog/2017/05/02/gnome-class-integrating-rust-and-the-gnome-object-system/"&gt;gnome-class&lt;/a&gt;, a procedural macro
        10137 that will let people implement new GObject classes in …&lt;/p&gt;</summary><content type="html">&lt;ul&gt;
        10138 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-1.html"&gt;How Glib-rs works, part 1: Type conversions&lt;/a&gt;&lt;/li&gt;
        10139 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-2.html"&gt;How Glib-rs works, part 2: Transferring lists and arrays&lt;/a&gt;&lt;/li&gt;
        10140 &lt;li&gt;&lt;a href="https://people.gnome.org/~federico/blog/how-glib-rs-works-part-3.html"&gt;How Glib-rs works, part 3: Boxed types&lt;/a&gt;&lt;/li&gt;
        10141 &lt;/ul&gt;
        10142 &lt;p&gt;During the &lt;a href="https://wiki.gnome.org/Hackfests/Rust2017"&gt;GNOME+Rust hackfest in Mexico City&lt;/a&gt;, &lt;a href="http://smallcultfollowing.com/babysteps/"&gt;Niko Matsakis&lt;/a&gt;
        10143 started the implementation of &lt;a href="http://smallcultfollowing.com/babysteps/blog/2017/05/02/gnome-class-integrating-rust-and-the-gnome-object-system/"&gt;gnome-class&lt;/a&gt;, a procedural macro
        10144 that will let people implement new GObject classes in Rust and export
        10145 them to the world.  Currently, if you want to write a new GObject
        10146 (e.g. a new widget) and put it in a library so that it can be used
        10147 from language bindings via GObject-Introspection, you have to do it in
        10148 C.  It would be nice to be able to do this in a safe language like
        10149 Rust.&lt;/p&gt;
        10150 &lt;h1&gt;How would it be done by hand?&lt;/h1&gt;
        10151 &lt;p&gt;In a C implementation of a new GObject subclass, one calls things like
        10152 &lt;code&gt;g_type_register_static()&lt;/code&gt; and &lt;code&gt;g_signal_new()&lt;/code&gt; by hand, while being
        10153 careful to specify the correct &lt;code&gt;GType&lt;/code&gt; for each value, and being
        10154 super-careful about everything, as C demands.&lt;/p&gt;
        10155 &lt;p&gt;In Rust, one &lt;em&gt;can&lt;/em&gt; in fact do exactly the same thing.  You can call the
        10156 same, low-level GObject and GType functions.  You can use
        10157 &lt;code&gt;#[repr(C)]&lt;/code&gt;] for the instance and class structs that GObject will
        10158 allocate for you, and which you then fill in.&lt;/p&gt;
        10159 &lt;p&gt;You can see an example of this in gst-plugins-rs.  This is where it implements a &lt;code&gt;Sink&lt;/code&gt;
        10160 GObject, in Rust, by calling Glib functions by
        10161 hand: &lt;a href="https://github.com/sdroege/gst-plugin-rs/blob/782fe5dcc93dbd1c5501821659c8ae1e4331e494/gst-plugin/src/sink.rs#L297"&gt;struct declarations&lt;/a&gt;, &lt;a href="https://github.com/sdroege/gst-plugin-rs/blob/782fe5dcc93dbd1c5501821659c8ae1e4331e494/gst-plugin/src/sink.rs#L356"&gt;&lt;code&gt;class_init()&lt;/code&gt; function&lt;/a&gt;,
        10162 &lt;a href="https://github.com/sdroege/gst-plugin-rs/blob/782fe5dcc93dbd1c5501821659c8ae1e4331e494/gst-plugin/src/sink.rs#L479"&gt;registration of type and interfaces&lt;/a&gt;.&lt;/p&gt;
        10163 &lt;h1&gt;How would it be done by a machine?&lt;/h1&gt;
        10164 &lt;p&gt;That's what Niko's gnome-class is about.  During the hackfest it
        10165 got to the point of being able to generate the code to create a new
        10166 GObject subclass, register it, and export functions for methods.  The
        10167 syntax is not finalized yet, but it looks something like this:&lt;/p&gt;
        10168 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10169 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10170 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;CounterPrivate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10171 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;: &lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10172 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10173 
        10174 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value_changed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10175 
        10176 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;set_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;: &lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10177 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10178 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10179 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;// private.emit_value_changed();&lt;/span&gt;
        10180 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10181 
        10182 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10183 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10184 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10185 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10186 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10187 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10188 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10189 
        10190 &lt;p&gt;I started adding support for declaring GObject signals — mainly being
        10191 able to parse them from what goes inside &lt;code&gt;gobject_gen!()&lt;/code&gt; — and then
        10192 being able to call &lt;code&gt;g_signal_newv()&lt;/code&gt; at the appropriate time during
        10193 the &lt;code&gt;class_init()&lt;/code&gt; implementation.&lt;/p&gt;
        10194 &lt;h1&gt;Types in signals&lt;/h1&gt;
        10195 &lt;p&gt;Creating a signal for a GObject class is basically like specifying a
        10196 function prototype:  the object will invoke a callback function with
        10197 certain arguments and return value when the signal is emitted.  For
        10198 example, this is how &lt;code&gt;GtkButton&lt;/code&gt; registers its &lt;a href="https://git.gnome.org/browse/gtk+/tree/gtk/gtkwidget.c?id=e26b60d48cc29a319b3ccc6c92157d9da1f9ceba#n2000"&gt;&lt;code&gt;button-press-event&lt;/code&gt;
        10199 signal&lt;/a&gt;:&lt;/p&gt;
        10200 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;  &lt;span class="n"&gt;button_press_event_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        10201     &lt;span class="n"&gt;g_signal_new&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;I_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;button-press-event&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        10202                   &lt;span class="p"&gt;...&lt;/span&gt;
        10203                   &lt;span class="n"&gt;G_TYPE_BOOLEAN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="cm"&gt;/* type of return value */&lt;/span&gt;
        10204                   &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                 &lt;span class="cm"&gt;/* how many arguments? */&lt;/span&gt;
        10205                   &lt;span class="n"&gt;GDK_TYPE_EVENT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="cm"&gt;/* type of first and only argument */&lt;/span&gt;
        10206 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10207 
        10208 &lt;p&gt;&lt;code&gt;g_signal_new()&lt;/code&gt; creates the signal and returns a &lt;em&gt;signal id&lt;/em&gt;, an
        10209 integer.  Later, when the object wants to emit the signal, it uses
        10210 that signal id like this:&lt;/p&gt;
        10211 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;GtkEventButton&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
        10212 &lt;span class="n"&gt;gboolean&lt;/span&gt; &lt;span class="n"&gt;return_val&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        10213 
        10214 &lt;span class="n"&gt;g_signal_emit&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;button_press_event_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;return_val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        10215 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10216 
        10217 &lt;p&gt;In the nice &lt;code&gt;gobject_gen!()&lt;/code&gt; macro, if I am going to have a signal
        10218 declaration like&lt;/p&gt;
        10219 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;button_press_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;ButtonPressEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10220 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10221 
        10222 &lt;p&gt;then I will need to be able to translate the type names for
        10223 &lt;code&gt;ButtonPressEvent&lt;/code&gt; and &lt;code&gt;bool&lt;/code&gt; into something that &lt;code&gt;g_signal_newv()&lt;/code&gt; will
        10224 understand:  I need the &lt;a href="https://developer.gnome.org/gobject/stable/gobject-Type-Information.html#GType"&gt;GType&lt;/a&gt; values for those.  Fundamental
        10225 types like &lt;code&gt;gboolean&lt;/code&gt; get constants like &lt;a href="https://developer.gnome.org/gobject/stable/gobject-Type-Information.html#G-TYPE-BOOLEAN:CAPS"&gt;G_TYPE_BOOLEAN&lt;/a&gt;.  Types
        10226 that are defined at runtime, like &lt;code&gt;GDK_TYPE_EVENT&lt;/code&gt;, get GType values
        10227 generated at runtime, too, when one registers the type with
        10228 &lt;code&gt;g_type_register_*()&lt;/code&gt;.&lt;/p&gt;
        10229 &lt;table&gt;
        10230 &lt;thead&gt;
        10231 &lt;tr&gt;
        10232 &lt;th align="left"&gt;Rust type&lt;/th&gt;
        10233 &lt;th align="left"&gt;GType&lt;/th&gt;
        10234 &lt;/tr&gt;
        10235 &lt;/thead&gt;
        10236 &lt;tbody&gt;
        10237 &lt;tr&gt;
        10238 &lt;td align="left"&gt;i32&lt;/td&gt;
        10239 &lt;td align="left"&gt;G_TYPE_INT&lt;/td&gt;
        10240 &lt;/tr&gt;
        10241 &lt;tr&gt;
        10242 &lt;td align="left"&gt;u32&lt;/td&gt;
        10243 &lt;td align="left"&gt;G_TYPE_UINT&lt;/td&gt;
        10244 &lt;/tr&gt;
        10245 &lt;tr&gt;
        10246 &lt;td align="left"&gt;bool&lt;/td&gt;
        10247 &lt;td align="left"&gt;G_TYPE_BOOLEAN&lt;/td&gt;
        10248 &lt;/tr&gt;
        10249 &lt;tr&gt;
        10250 &lt;td align="left"&gt;etc.&lt;/td&gt;
        10251 &lt;td align="left"&gt;etc.&lt;/td&gt;
        10252 &lt;/tr&gt;
        10253 &lt;/tbody&gt;
        10254 &lt;/table&gt;
        10255 &lt;h1&gt;Glib types in Rust&lt;/h1&gt;
        10256 &lt;p&gt;How does &lt;a href="http://gtk-rs.org/docs/glib/"&gt;glib-rs&lt;/a&gt;, the Rust binding to Glib and GObject, handle
        10257 types?&lt;/p&gt;
        10258 &lt;h2&gt;Going from Glib to Rust&lt;/h2&gt;
        10259 &lt;p&gt;First we need a way to convert Glib's types to Rust, and vice-versa.
        10260 There is a trait to convert simple Glib types into Rust types:&lt;/p&gt;
        10261 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlib&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;: &lt;span class="nb"&gt;Sized&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10262 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_glib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;: &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10263 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10264 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10265 
        10266 &lt;p&gt;This means, if I have a &lt;code&gt;T&lt;/code&gt; which is a Glib type, this trait will give
        10267 you a &lt;code&gt;from_glib()&lt;/code&gt; function which will convert it to a Rust type
        10268 which is &lt;code&gt;Sized&lt;/code&gt;, i.e. a type whose size is known at compilation time.&lt;/p&gt;
        10269 &lt;p&gt;For example, this is how it is implemented for booleans:&lt;/p&gt;
        10270 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlib&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;gboolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10271 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[inline]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10272 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_glib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;: &lt;span class="nc"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;gboolean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10273 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;GFALSE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10274 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10275 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10276 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10277 
        10278 &lt;p&gt;and you use it like this:&lt;/p&gt;
        10279 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_gboolean&lt;/span&gt;: &lt;span class="nc"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;gboolean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;g_some_function_that_returns_gboolean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10280 
        10281 &lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_rust_bool&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;from_glib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_gboolean&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10282 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10283 
        10284 &lt;p&gt;Booleans in glib and Rust have &lt;a href="https://people.gnome.org/~federico/news-2017-04.html#gboolean-is-not-rust-bool"&gt;different sizes&lt;/a&gt;, and also
        10285 different values.  Glib's booleans use the C convention: 0 is false
        10286 and anything else is true, while in Rust booleans are strictly &lt;code&gt;false&lt;/code&gt;
        10287 or &lt;code&gt;true&lt;/code&gt;, and the size is undefined (with the current Rust ABI, it's
        10288 one byte).&lt;/p&gt;
        10289 &lt;h2&gt;Going from Rust to Glib&lt;/h2&gt;
        10290 &lt;p&gt;And to go the other way around, from a Rust &lt;code&gt;bool&lt;/code&gt; to a &lt;code&gt;gboolean&lt;/code&gt;?
        10291 There is this trait:&lt;/p&gt;
        10292 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ToGlib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10293 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;GlibType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10294 
        10295 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;to_glib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Self&lt;/span&gt;::&lt;span class="n"&gt;GlibType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10296 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10297 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10298 
        10299 &lt;p&gt;This means, if you have a Rust type that maps to a corresponding
        10300 &lt;code&gt;GlibType&lt;/code&gt;, this will give you a &lt;code&gt;to_glib()&lt;/code&gt; function to do the
        10301 conversion.&lt;/p&gt;
        10302 &lt;p&gt;This is the implementation for booleans:&lt;/p&gt;
        10303 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ToGlib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10304 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;GlibType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;gboolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10305 
        10306 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[inline]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10307 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;to_glib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;gboolean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10308 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;GTRUE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;GFALSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10309 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10310 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10311 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10312 
        10313 &lt;p&gt;And it is used like this:&lt;/p&gt;
        10314 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_rust_bool&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10315 
        10316 &lt;span class="n"&gt;g_some_function_that_takes_gboolean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_rust_bool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_glib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10317 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10318 
        10319 &lt;p&gt;(If you are thinking "a function call to marshal a boolean" — note how
        10320 the functions are inlined, and the optimizer basically compiles them
        10321 down to nothing.)&lt;/p&gt;
        10322 &lt;h2 id="pointer-types"&gt;Pointer types - from Glib to Rust&lt;/h2&gt;
        10323 &lt;p&gt;That's all very nice for simple types like booleans and ints.
        10324 Pointers to other objects are slightly more complicated.&lt;/p&gt;
        10325 &lt;p&gt;GObject-Introspection allows one to specify how pointer arguments to
        10326 functions are handled by using a &lt;a href="https://developer.gnome.org/gi/stable/gi-GIArgInfo.html#GITransfer"&gt;&lt;em&gt;transfer&lt;/em&gt;&lt;/a&gt; specifier.  &lt;/p&gt;
        10327 &lt;h3&gt;&lt;code&gt;(transfer none)&lt;/code&gt;&lt;/h3&gt;
        10328 &lt;p&gt;For example, if you call &lt;code&gt;gtk_window_set_title(window, "Hello")&lt;/code&gt;, you
        10329 would expect the function to make its own copy of the &lt;code&gt;"Hello"&lt;/code&gt;
        10330 string.  In Rust terms, you would be passing it a simple &lt;em&gt;borrowed
        10331 reference&lt;/em&gt;.  GObject-Introspection (we'll abbreviate it as GI) calls
        10332 this &lt;code&gt;GI_TRANSFER_NOTHING&lt;/code&gt;, and it's specified by using
        10333 &lt;code&gt;(transfer none)&lt;/code&gt; in the documentation strings for function arguments
        10334 or return values.&lt;/p&gt;
        10335 &lt;p&gt;The corresponding trait to bring in pointers from Glib to Rust,
        10336 without taking ownership, is this.  It's &lt;code&gt;unsafe&lt;/code&gt; because it will be
        10337 used to de-reference pointers that come from the wild west:&lt;/p&gt;
        10338 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrNone&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;: &lt;span class="nc"&gt;Ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;: &lt;span class="nb"&gt;Sized&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10339 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_glib_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="nc"&gt;P&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10340 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10341 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10342 
        10343 &lt;p&gt;And you use it via this generic function:&lt;/p&gt;
        10344 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[inline]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10345 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_glib_none&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;: &lt;span class="nc"&gt;Ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;: &lt;span class="nc"&gt;FromGlibPtrNone&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="nc"&gt;P&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10346 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrNone&lt;/span&gt;::&lt;span class="n"&gt;from_glib_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10347 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10348 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10349 
        10350 &lt;p&gt;Let's look at how this works.  Here is the &lt;code&gt;FromGlibPtrNone&lt;/code&gt; trait
        10351 implemented for strings.&lt;/p&gt;
        10352 &lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
        10353 &lt;span class="normal"&gt;2&lt;/span&gt;
        10354 &lt;span class="normal"&gt;3&lt;/span&gt;
        10355 &lt;span class="normal"&gt;4&lt;/span&gt;
        10356 &lt;span class="normal"&gt;5&lt;/span&gt;
        10357 &lt;span class="normal"&gt;6&lt;/span&gt;
        10358 &lt;span class="normal"&gt;7&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrNone&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10359 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[inline]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10360 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_glib_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Self&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10361 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10362 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;::&lt;span class="n"&gt;from_utf8_lossy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CStr&lt;/span&gt;::&lt;span class="n"&gt;from_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;to_bytes&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="n"&gt;into_owned&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10363 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10364 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10365 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10366 &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
        10367 &lt;p&gt;Line 1: given a pointer to a &lt;code&gt;c_char&lt;/code&gt;, the conversion to &lt;code&gt;String&lt;/code&gt;...&lt;/p&gt;
        10368 &lt;p&gt;Line 4: check for NULL pointers&lt;/p&gt;
        10369 &lt;p&gt;Line 5: Use the CStr to wrap the C
        10370 &lt;code&gt;ptr&lt;/code&gt;, &lt;a href="https://people.gnome.org/~federico/blog/correctness-in-rust-reading-strings.html"&gt;like we looked at last time&lt;/a&gt;, validate it as UTF-8 and
        10371 copy the string for us.&lt;/p&gt;
        10372 &lt;p&gt;Unfortunately, there's a copy involved in the last step.  It may be
        10373 possible to use &lt;a href="https://doc.rust-lang.org/std/borrow/enum.Cow.html"&gt;&lt;code&gt;Cow&amp;lt;&amp;amp;str&amp;gt;&lt;/code&gt;&lt;/a&gt; there instead to avoid a copy if
        10374 the &lt;code&gt;char*&lt;/code&gt; from Glib is indeed valid UTF-8.&lt;/p&gt;
        10375 &lt;h3&gt;&lt;code&gt;(transfer full)&lt;/code&gt;&lt;/h3&gt;
        10376 &lt;p&gt;And how about transferring ownership of the pointed-to value?  There
        10377 is this trait:&lt;/p&gt;
        10378 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrFull&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;: &lt;span class="nc"&gt;Ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;: &lt;span class="nb"&gt;Sized&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10379 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_glib_full&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="nc"&gt;P&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10380 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10381 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10382 
        10383 &lt;p&gt;And the implementation for strings is as follows.  In Glib's scheme of
        10384 things, "transferring ownership of a string" means that the recipient
        10385 of the string must eventually &lt;code&gt;g_free()&lt;/code&gt; it.&lt;/p&gt;
        10386 &lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
        10387 &lt;span class="normal"&gt;2&lt;/span&gt;
        10388 &lt;span class="normal"&gt;3&lt;/span&gt;
        10389 &lt;span class="normal"&gt;4&lt;/span&gt;
        10390 &lt;span class="normal"&gt;5&lt;/span&gt;
        10391 &lt;span class="normal"&gt;6&lt;/span&gt;
        10392 &lt;span class="normal"&gt;7&lt;/span&gt;
        10393 &lt;span class="normal"&gt;8&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FromGlibPtrFull&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10394 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[inline]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10395 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_glib_full&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Self&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10396 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;from_glib_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10397 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;g_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10398 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10399 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10400 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10401 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10402 &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
        10403 &lt;p&gt;Line 1: given a pointer to a &lt;code&gt;c_char&lt;/code&gt;, the conversion to &lt;code&gt;String&lt;/code&gt;...&lt;/p&gt;
        10404 &lt;p&gt;Line 4: Do the conversion with &lt;code&gt;from_glib_none()&lt;/code&gt; with the trait we
        10405 saw before, put it in &lt;code&gt;res&lt;/code&gt;.&lt;/p&gt;
        10406 &lt;p&gt;Line 5: Call &lt;code&gt;g_free()&lt;/code&gt; on the original C string.&lt;/p&gt;
        10407 &lt;p&gt;Line 6: Return the &lt;code&gt;res&lt;/code&gt;, a Rust string which we own.&lt;/p&gt;
        10408 &lt;h2&gt;Pointer types - from Rust to Glib&lt;/h2&gt;
        10409 &lt;p&gt;Consider the case where you want to pass a &lt;code&gt;String&lt;/code&gt; from Rust to a Glib function
        10410 that takes a &lt;code&gt;*const c_char&lt;/code&gt; — in C parlance, a &lt;code&gt;char *&lt;/code&gt;, without the
        10411 Glib function acquiring ownership of the string.  For example, assume
        10412 that the C version of &lt;code&gt;gtk_window_set_title()&lt;/code&gt; is in the &lt;code&gt;gtk_ffi&lt;/code&gt;
        10413 module.  You may want to call it like this:&lt;/p&gt;
        10414 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;rust_binding_to_window_set_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;Gtk&lt;/span&gt;::&lt;span class="n"&gt;Window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10415 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;gtk_ffi&lt;/span&gt;::&lt;span class="n"&gt;gtk_window_set_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make_c_string_from_rust_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10416 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10417 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10418 
        10419 &lt;p&gt;Now, what would that &lt;code&gt;make_c_string_from_rust_string()&lt;/code&gt; look like?&lt;/p&gt;
        10420 &lt;ul&gt;
        10421 &lt;li&gt;
        10422 &lt;p&gt;&lt;strong&gt;We have:&lt;/strong&gt; a Rust &lt;code&gt;String&lt;/code&gt; — UTF-8, known length, no nul terminator&lt;/p&gt;
        10423 &lt;/li&gt;
        10424 &lt;li&gt;
        10425 &lt;p&gt;&lt;strong&gt;We want:&lt;/strong&gt; a &lt;code&gt;*const char&lt;/code&gt; — nul-terminated UTF-8&lt;/p&gt;
        10426 &lt;/li&gt;
        10427 &lt;/ul&gt;
        10428 &lt;p&gt;So, let's write this:&lt;/p&gt;
        10429 &lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
        10430 &lt;span class="normal"&gt;2&lt;/span&gt;
        10431 &lt;span class="normal"&gt;3&lt;/span&gt;
        10432 &lt;span class="normal"&gt;4&lt;/span&gt;
        10433 &lt;span class="normal"&gt;5&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;make_c_string_from_rust_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10434 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cstr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CString&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10435 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cstr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;into_raw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10436 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10437 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10438 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10439 &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
        10440 &lt;p&gt;Line 1: Take in a &lt;code&gt;&amp;amp;String&lt;/code&gt;; return a &lt;code&gt;*const c_char&lt;/code&gt;.&lt;/p&gt;
        10441 &lt;p&gt;Line 2: Build a &lt;a href="https://people.gnome.org/~federico/blog/correctness-in-rust-reading-strings.html"&gt;&lt;code&gt;CString&lt;/code&gt;&lt;/a&gt; like we way a few days ago:  this
        10442 allocates a byte buffer with space for a nul terminator, and copies
        10443 the string's bytes.  We &lt;code&gt;unwrap()&lt;/code&gt; for this simple example, because
        10444 &lt;code&gt;CString::new()&lt;/code&gt; will return an error if the &lt;code&gt;String&lt;/code&gt; contained nul
        10445 characters in the middle of the string, which C doesn't understand.&lt;/p&gt;
        10446 &lt;p&gt;Line 3: Call &lt;code&gt;into_raw()&lt;/code&gt; to get a pointer to the byte buffer, and
        10447 cast it to a &lt;code&gt;*const c_char&lt;/code&gt;.  &lt;em&gt;We'll need to free this value later.&lt;/em&gt;&lt;/p&gt;
        10448 &lt;p&gt;But this kind of sucks, because we the have to use this function, pass
        10449 the pointer to a C function, and then reconstitute the &lt;code&gt;CString&lt;/code&gt; so it
        10450 can free the byte buffer:&lt;/p&gt;
        10451 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make_c_string_from_rust_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10452 &lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_function_that_takes_a_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10453 &lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CString&lt;/span&gt;::&lt;span class="n"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10454 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10455 
        10456 &lt;p&gt;The solution that Glib-rs provides for this is very Rusty, and rather
        10457 elegant.&lt;/p&gt;
        10458 &lt;h3&gt;Stashes&lt;/h3&gt;
        10459 &lt;p&gt;We want:&lt;/p&gt;
        10460 &lt;ul&gt;
        10461 &lt;li&gt;A temporary place to put a piece of data&lt;/li&gt;
        10462 &lt;li&gt;A pointer to that buffer&lt;/li&gt;
        10463 &lt;li&gt;Automatic memory management for both of those&lt;/li&gt;
        10464 &lt;/ul&gt;
        10465 &lt;p&gt;Glib-rs defines a &lt;code&gt;Stash&lt;/code&gt; for this:&lt;/p&gt;
        10466 &lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
        10467 &lt;span class="normal"&gt;2&lt;/span&gt;
        10468 &lt;span class="normal"&gt;3&lt;/span&gt;
        10469 &lt;span class="normal"&gt;4&lt;/span&gt;
        10470 &lt;span class="normal"&gt;5&lt;/span&gt;
        10471 &lt;span class="normal"&gt;6&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Stash&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;                                 &lt;/span&gt;&lt;span class="c1"&gt;// we have a lifetime&lt;/span&gt;
        10472 &lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;: &lt;span class="nb"&gt;Copy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;                            &lt;/span&gt;&lt;span class="c1"&gt;// the pointer must be copy-able&lt;/span&gt;
        10473 &lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;: &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="nb"&gt;Sized&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ToGlibPtr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;// Type for the temporary place&lt;/span&gt;
        10474 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;                                           &lt;/span&gt;&lt;span class="c1"&gt;// We store a pointer...&lt;/span&gt;
        10475 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ToGlibPtr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;::&lt;span class="n"&gt;Storage&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="c1"&gt;// ... to a piece of data with that lifetime ...&lt;/span&gt;
        10476 &lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10477 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10478 &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
        10479 &lt;p&gt;... and the piece of data must be of of the &lt;em&gt;associated type&lt;/em&gt;
        10480 &lt;code&gt;ToGlibPtr::Storage&lt;/code&gt;, which we will see shortly.&lt;/p&gt;
        10481 &lt;p&gt;This struct &lt;code&gt;Stash&lt;/code&gt; goes along with the &lt;code&gt;ToGlibPtr&lt;/code&gt; trait:&lt;/p&gt;
        10482 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ToGlibPtr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;: &lt;span class="nb"&gt;Copy&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10483 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Storage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10484 
        10485 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;to_glib_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Stash&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// returns a Stash whose temporary storage&lt;/span&gt;
        10486 &lt;span class="w"&gt;                                                      &lt;/span&gt;&lt;span class="c1"&gt;// has the lifetime of our original data&lt;/span&gt;
        10487 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10488 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10489 
        10490 &lt;p&gt;Let's unpack this by looking at the implementation of the "transfer a
        10491 String to a C function while keeping ownership":&lt;/p&gt;
        10492 &lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
        10493 &lt;span class="normal"&gt;2&lt;/span&gt;
        10494 &lt;span class="normal"&gt;3&lt;/span&gt;
        10495 &lt;span class="normal"&gt;4&lt;/span&gt;
        10496 &lt;span class="normal"&gt;5&lt;/span&gt;
        10497 &lt;span class="normal"&gt;6&lt;/span&gt;
        10498 &lt;span class="normal"&gt;7&lt;/span&gt;
        10499 &lt;span class="normal"&gt;8&lt;/span&gt;
        10500 &lt;span class="normal"&gt;9&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ToGlibPtr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10501 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Storage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10502 
        10503 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[inline]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10504 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;to_glib_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Stash&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10505 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CString&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10506 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Stash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ptr&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10507 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10508 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10509 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10510 &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
        10511 &lt;p&gt;Line 1: We implement &lt;code&gt;ToGlibPtr&amp;lt;'a *const c_char&amp;gt;&lt;/code&gt; for &lt;code&gt;String&lt;/code&gt;,
        10512 declaring the lifetime &lt;code&gt;'a&lt;/code&gt; for the &lt;code&gt;Stash&lt;/code&gt;.&lt;/p&gt;
        10513 &lt;p&gt;Line 2: Our temporary storage is a &lt;code&gt;CString&lt;/code&gt;.&lt;/p&gt;
        10514 &lt;p&gt;Line 6: Make a CString like before.&lt;/p&gt;
        10515 &lt;p&gt;Line 7: Create the &lt;code&gt;Stash&lt;/code&gt; with a pointer to the CString's contents,
        10516 and the CString itself.&lt;/p&gt;
        10517 &lt;h3&gt;&lt;code&gt;(transfer none)&lt;/code&gt;&lt;/h3&gt;
        10518 &lt;p&gt;Now, we can use "&lt;code&gt;.0&lt;/code&gt;" to extract the first field from our &lt;code&gt;Stash&lt;/code&gt;,
        10519 which is precisely the pointer we want to a byte buffer:&lt;/p&gt;
        10520 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10521 &lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_function_which_takes_a_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_glib_none&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10522 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10523 
        10524 &lt;p&gt;Now Rust knows that the temporary buffer inside the &lt;code&gt;Stash&lt;/code&gt; has the lifetime of
        10525 &lt;code&gt;my_string&lt;/code&gt;, and it will free it automatically when the string goes
        10526 out of scope.  If we can accept the &lt;code&gt;.to_glib_none().0&lt;/code&gt; incantation
        10527 for "lending" pointers to C, this works perfectly.&lt;/p&gt;
        10528 &lt;h3 id="ptr-transfer-full"&gt;&lt;code&gt;(transfer full)&lt;/code&gt;&lt;/h3&gt;
        10529 &lt;p&gt;And for transferring ownership to the C function?  The &lt;code&gt;ToGlibPtr&lt;/code&gt;
        10530 trait has another method:&lt;/p&gt;
        10531 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ToGlibPtr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;: &lt;span class="nb"&gt;Copy&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10532 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10533 
        10534 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;to_glib_full&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;P&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10535 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10536 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10537 
        10538 &lt;p&gt;And here is the implementation for strings:&lt;/p&gt;
        10539 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ToGlibPtr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10540 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;to_glib_full&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10541 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10542 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;glib_ffi&lt;/span&gt;::&lt;span class="n"&gt;g_strndup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ptr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
        10543 &lt;span class="w"&gt;                                &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;size_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10544 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10545 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10546 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10547 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10548 
        10549 &lt;p&gt;We basically &lt;code&gt;g_strndup()&lt;/code&gt; the Rust string's contents from its byte
        10550 buffer &lt;em&gt;and&lt;/em&gt; its &lt;code&gt;len()&lt;/code&gt;, and we can then pass this on to C.  &lt;em&gt;That&lt;/em&gt;
        10551 code will be responsible for &lt;code&gt;g_free()&lt;/code&gt;ing the C-side string.&lt;/p&gt;
        10552 &lt;h1&gt;Next up&lt;/h1&gt;
        10553 &lt;p&gt;Transferring lists and arrays.  Stay tuned!&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="gnome"></category></entry><entry><title>Correctness in Rust: building strings</title><link href="https://people.gnome.org/~federico/blog/correctness-in-rust-reading-strings.html" rel="alternate"></link><published>2017-08-16T20:26:39-05:00</published><updated>2017-08-16T20:26:39-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-08-16:/~federico/blog/correctness-in-rust-reading-strings.html</id><summary type="html">&lt;p&gt;Rust tries to follow the "make illegal states unrepresentable" mantra
        10554 in several ways.  In this post I'll show several things related to the
        10555 process of building strings, from bytes in memory, or from a file, or
        10556 from &lt;code&gt;char *&lt;/code&gt; things passed from C.&lt;/p&gt;
        10557 &lt;h1&gt;Strings in Rust&lt;/h1&gt;
        10558 &lt;p&gt;The easiest way to build …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Rust tries to follow the "make illegal states unrepresentable" mantra
        10559 in several ways.  In this post I'll show several things related to the
        10560 process of building strings, from bytes in memory, or from a file, or
        10561 from &lt;code&gt;char *&lt;/code&gt; things passed from C.&lt;/p&gt;
        10562 &lt;h1&gt;Strings in Rust&lt;/h1&gt;
        10563 &lt;p&gt;The easiest way to build a string is to do it directly at compile
        10564 time:&lt;/p&gt;
        10565 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10566 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10567 
        10568 &lt;p&gt;In Rust, strings are UTF-8.  Here, the compiler checks our string
        10569 literal is valid UTF-8.  If we try to be sneaky and insert an
        10570 invalid character...&lt;/p&gt;
        10571 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello \xf0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10572 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10573 
        10574 &lt;p&gt;We get a compiler error:&lt;/p&gt;
        10575 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;error: this form of character escape may only be used with characters in the range [\x00-\x7f]
        10576  --&amp;gt; foo.rs:2:30
        10577   |
        10578 2 |     let my_string = &amp;quot;Hello \xf0&amp;quot;;
        10579   |                              ^^
        10580 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10581 
        10582 &lt;p&gt;Rust strings know their length, unlike C strings.  They &lt;em&gt;can&lt;/em&gt; contain
        10583 a nul character in the middle, because they don't need a nul
        10584 terminator at the end.&lt;/p&gt;
        10585 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello &lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s"&gt; zero&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10586 &lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10587 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10588 
        10589 &lt;p&gt;The output is what you expect:&lt;/p&gt;
        10590 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$ ./foo | hexdump -C
        10591 00000000  48 65 6c 6c 6f 20 00 20  7a 65 72 6f 0a           |Hello . zero.|
        10592 0000000d                    ^ note the nul char here
        10593 $
        10594 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10595 
        10596 &lt;p&gt;So, to summarize, in Rust:&lt;/p&gt;
        10597 &lt;ul&gt;
        10598 &lt;li&gt;Strings are encoded in UTF-8&lt;/li&gt;
        10599 &lt;li&gt;Strings know their length&lt;/li&gt;
        10600 &lt;li&gt;Strings can have nul chars in the middle&lt;/li&gt;
        10601 &lt;/ul&gt;
        10602 &lt;p&gt;This is a bit different from C:&lt;/p&gt;
        10603 &lt;ul&gt;
        10604 &lt;li&gt;Strings don't exist!&lt;/li&gt;
        10605 &lt;/ul&gt;
        10606 &lt;p&gt;Okay, just kidding.  In C:&lt;/p&gt;
        10607 &lt;ul&gt;
        10608 &lt;li&gt;A lot of software has standardized on UTF-8.&lt;/li&gt;
        10609 &lt;li&gt;Strings don't know their length - a &lt;code&gt;char *&lt;/code&gt; is a raw pointer to the
        10610   beginning of the string.&lt;/li&gt;
        10611 &lt;li&gt;Strings conventionally have a nul terminator, that is, a zero byte
        10612   that marks the end of the string.  Therefore, you can't have nul
        10613   characters in the middle of strings.&lt;/li&gt;
        10614 &lt;/ul&gt;
        10615 &lt;h1&gt;Building a string from bytes&lt;/h1&gt;
        10616 &lt;p&gt;Let's say you have an array of bytes and want to make a string from
        10617 them.  Rust won't let you just cast the array, like C would.  First
        10618 you need to do UTF-8 validation.  For example:&lt;/p&gt;
        10619 &lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
        10620 &lt;span class="normal"&gt; 2&lt;/span&gt;
        10621 &lt;span class="normal"&gt; 3&lt;/span&gt;
        10622 &lt;span class="normal"&gt; 4&lt;/span&gt;
        10623 &lt;span class="normal"&gt; 5&lt;/span&gt;
        10624 &lt;span class="normal"&gt; 6&lt;/span&gt;
        10625 &lt;span class="normal"&gt; 7&lt;/span&gt;
        10626 &lt;span class="normal"&gt; 8&lt;/span&gt;
        10627 &lt;span class="normal"&gt; 9&lt;/span&gt;
        10628 &lt;span class="normal"&gt;10&lt;/span&gt;
        10629 &lt;span class="normal"&gt;11&lt;/span&gt;
        10630 &lt;span class="normal"&gt;12&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;convert_and_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;: &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10631 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;::&lt;span class="n"&gt;from_utf8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10632 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10633 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10634 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10635 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10636 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10637 
        10638 &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10639 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;convert_and_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x6c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x6c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x6f&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10640 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;convert_and_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xf0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x6c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x6c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x6f&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10641 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10642 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10643 &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
        10644 &lt;p&gt;In lines 10 and 11, we call &lt;code&gt;convert_and_print()&lt;/code&gt; with different
        10645 arrays of bytes; the first one is valid UTF-8, and the second one
        10646 isn't.&lt;/p&gt;
        10647 &lt;p&gt;Line 2 calls &lt;a href="https://doc.rust-lang.org/std/string/struct.String.html#method.from_utf8"&gt;&lt;code&gt;String::from_utf8()&lt;/code&gt;&lt;/a&gt;, which returns a &lt;code&gt;Result&lt;/code&gt;,
        10648 i.e. something with a success value or an error.  In lines 3-5 we
        10649 unpack this &lt;code&gt;Result&lt;/code&gt;.  If it's &lt;code&gt;Ok&lt;/code&gt;, we print the converted string,
        10650 which has been validated for UTF-8.  Otherwise, we print the debug
        10651 representation of the error.&lt;/p&gt;
        10652 &lt;p&gt;The program prints the following:&lt;/p&gt;
        10653 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$ ~/foo
        10654 Hello
        10655 FromUtf8Error { bytes: [72, 101, 240, 108, 108, 111], error: Utf8Error { valid_up_to: 2, error_len: Some(1) } }
        10656 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10657 
        10658 &lt;p&gt;Here, in the error case, the &lt;a href="https://doc.rust-lang.org/std/str/struct.Utf8Error.html"&gt;&lt;code&gt;Utf8Error&lt;/code&gt;&lt;/a&gt; tells us that the bytes
        10659 are UTF-8 and are &lt;code&gt;valid_up_to&lt;/code&gt; index 2; that is the first problematic
        10660 index.  We also get some extra information which lets the program know
        10661 if the problematic sequence was incomplete and truncated at the end of
        10662 the byte array, or if it's complete and in the middle.&lt;/p&gt;
        10663 &lt;p&gt;And for a "just make this printable, pls" API?  We can
        10664 use &lt;a href="https://doc.rust-lang.org/std/string/struct.String.html#method.from_utf8_lossy"&gt;&lt;code&gt;String::from_utf8_lossy()&lt;/code&gt;&lt;/a&gt;, which replaces invalid UTF-8
        10665 sequences with &lt;code&gt;U+FFFD REPLACEMENT CHARACTER&lt;/code&gt;:&lt;/p&gt;
        10666 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;convert_and_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;: &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10667 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;::&lt;span class="n"&gt;from_utf8_lossy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10668 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10669 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10670 
        10671 &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10672 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;convert_and_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x6c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x6c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x6f&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10673 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;convert_and_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xf0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x6c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x6c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x6f&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10674 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10675 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10676 
        10677 &lt;p&gt;This prints the following:&lt;/p&gt;
        10678 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$ ~/foo
        10679 Hello
        10680 He�llo
        10681 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10682 
        10683 &lt;h1&gt;Reading from files into strings&lt;/h1&gt;
        10684 &lt;p&gt;Now, let's assume you want to read chunks of a file and put them into
        10685 strings.  Let's go from the low-level parts up to the high level "read
        10686 a line" API.&lt;/p&gt;
        10687 &lt;h2&gt;Single bytes and single UTF-8 characters&lt;/h2&gt;
        10688 &lt;p&gt;When you open a &lt;a href="https://doc.rust-lang.org/std/fs/struct.File.html"&gt;&lt;code&gt;File&lt;/code&gt;&lt;/a&gt;, you get an object that implements the
        10689 &lt;a href="https://doc.rust-lang.org/std/io/trait.Read.html"&gt;&lt;code&gt;Read&lt;/code&gt;&lt;/a&gt; trait.  In addition to the usual "read me some bytes" method,
        10690 it can also give you back an iterator over &lt;em&gt;bytes&lt;/em&gt;, or an iterator
        10691 over UTF-8 &lt;em&gt;characters&lt;/em&gt;.&lt;/p&gt;
        10692 &lt;p&gt;The &lt;a href="https://doc.rust-lang.org/std/io/trait.Read.html#method.bytes"&gt;&lt;code&gt;Read.bytes()&lt;/code&gt;&lt;/a&gt; method gives you back a &lt;a href="https://doc.rust-lang.org/std/io/struct.Bytes.html"&gt;&lt;code&gt;Bytes&lt;/code&gt;&lt;/a&gt; iterator,
        10693 whose &lt;code&gt;next()&lt;/code&gt; method returns &lt;code&gt;Result&amp;lt;u8, io::Error&amp;gt;&lt;/code&gt;.  When you ask
        10694 the iterator for its next item, that &lt;code&gt;Result&lt;/code&gt; means you'll get a byte
        10695 out of it successfully, or an I/O error.&lt;/p&gt;
        10696 &lt;p&gt;In contrast, the &lt;a href="https://doc.rust-lang.org/std/io/trait.Read.html#method.chars"&gt;&lt;code&gt;Read.chars()&lt;/code&gt;&lt;/a&gt; method gives you back
        10697 a &lt;a href="https://doc.rust-lang.org/std/io/struct.Chars.html"&gt;&lt;code&gt;Chars&lt;/code&gt;&lt;/a&gt; iterator, and its &lt;code&gt;next()&lt;/code&gt; method returns
        10698 &lt;code&gt;Result&amp;lt;char, CharsError&amp;gt;&lt;/code&gt;, not &lt;code&gt;io::Error&lt;/code&gt;.  This
        10699 extended &lt;a href="https://doc.rust-lang.org/std/io/enum.CharsError.html"&gt;&lt;code&gt;CharsError&lt;/code&gt;&lt;/a&gt; has a &lt;code&gt;NotUtf8&lt;/code&gt; case, which you get back
        10700 when &lt;code&gt;next()&lt;/code&gt; tries to read the next UTF-8 sequence from the file and
        10701 the file has invalid data.  &lt;code&gt;CharsError&lt;/code&gt; also has a case for normal
        10702 I/O errors.&lt;/p&gt;
        10703 &lt;h2&gt;Reading lines&lt;/h2&gt;
        10704 &lt;p&gt;While you could build a UTF-8 string one character at a time, there
        10705 are more efficient ways to do it.&lt;/p&gt;
        10706 &lt;p&gt;You can create a &lt;a href="https://doc.rust-lang.org/std/io/struct.BufReader.html"&gt;&lt;code&gt;BufReader&lt;/code&gt;&lt;/a&gt;, a buffered reader, out of anything
        10707 that implements the &lt;a href="https://doc.rust-lang.org/std/io/trait.Read.html"&gt;&lt;code&gt;Read&lt;/code&gt;&lt;/a&gt; trait.  &lt;code&gt;BufReader&lt;/code&gt; has a
        10708 convenient &lt;a href="https://doc.rust-lang.org/std/io/trait.BufRead.html#method.read_line"&gt;&lt;code&gt;read_line()&lt;/code&gt;&lt;/a&gt; method, to which you pass a mutable
        10709 String and it returns a &lt;code&gt;Result&amp;lt;usize, io::Error&amp;gt;&lt;/code&gt; with either the
        10710 number of bytes read, or an error.&lt;/p&gt;
        10711 &lt;p&gt;That method is declared in the &lt;a href="https://doc.rust-lang.org/std/io/trait.BufRead.html"&gt;&lt;code&gt;BufRead&lt;/code&gt;&lt;/a&gt; trait, which &lt;code&gt;BufReader&lt;/code&gt;
        10712 implements.  Why the separation?  Because other concrete structs also
        10713 implement &lt;code&gt;BufRead&lt;/code&gt;, such as &lt;a href="https://doc.rust-lang.org/std/io/struct.Cursor.html"&gt;&lt;code&gt;Cursor&lt;/code&gt;&lt;/a&gt; — a nice wrapper that lets
        10714 you use a vector of bytes like an I/O &lt;code&gt;Read&lt;/code&gt; or &lt;code&gt;Write&lt;/code&gt;
        10715 implementation, similar to &lt;a href="https://developer.gnome.org/gio/stable/GMemoryInputStream.html"&gt;&lt;code&gt;GMemoryInputStream&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
        10716 &lt;p&gt;If you prefer an iterator rather than the &lt;code&gt;read_line()&lt;/code&gt; function,
        10717 &lt;code&gt;BufRead&lt;/code&gt; also gives you a &lt;a href="https://doc.rust-lang.org/std/io/trait.BufRead.html#method.lines"&gt;&lt;code&gt;lines()&lt;/code&gt;&lt;/a&gt; method, which gives you back
        10718 a &lt;a href="https://doc.rust-lang.org/std/io/struct.Lines.html"&gt;&lt;code&gt;Lines&lt;/code&gt;&lt;/a&gt; iterator.&lt;/p&gt;
        10719 &lt;p&gt;In both cases — the &lt;code&gt;read_line()&lt;/code&gt; method or the &lt;code&gt;Lines&lt;/code&gt; iterator, the
        10720 error that you can get back can be of &lt;a href="https://doc.rust-lang.org/std/io/enum.ErrorKind.html"&gt;&lt;code&gt;ErrorKind&lt;/code&gt;&lt;/a&gt;&lt;code&gt;::InvalidData&lt;/code&gt;,
        10721 which indicates that there was an invalid UTF-8 sequence in the line
        10722 to be read.  It can also be a normal I/O error, of course.&lt;/p&gt;
        10723 &lt;h1&gt;Summary so far&lt;/h1&gt;
        10724 &lt;p&gt;There is no way to build a &lt;code&gt;String&lt;/code&gt;, or a &lt;code&gt;&amp;amp;str&lt;/code&gt; slice, from invalid
        10725 UTF-8 data.  All the methods that let you turn bytes into string-like
        10726 things perform validation, and return a &lt;code&gt;Result&lt;/code&gt; to let you know if
        10727 your bytes validated correctly.&lt;/p&gt;
        10728 &lt;p&gt;The exceptions are in the &lt;code&gt;unsafe&lt;/code&gt; methods,
        10729 like &lt;a href="https://doc.rust-lang.org/std/string/struct.String.html#method.from_utf8_unchecked"&gt;&lt;code&gt;String::from_utf8_unchecked()&lt;/code&gt;&lt;/a&gt;.  You should really only use
        10730 them if you are &lt;em&gt;absolutely sure&lt;/em&gt; that your bytes were validated as
        10731 UTF-8 beforehand.&lt;/p&gt;
        10732 &lt;p&gt;There is no way to bring in data from a file (or anything file-like,
        10733 that implements the &lt;a href="https://doc.rust-lang.org/std/io/trait.Read.html"&gt;&lt;code&gt;Read&lt;/code&gt;&lt;/a&gt; trait) and turn it into a &lt;code&gt;String&lt;/code&gt;
        10734 without going through functions that do UTF-8 validation.  There is
        10735 not an unsafe "read a line" API without validation — you would have to
        10736 build one yourself, but the I/O hit is probably going to be slower than
        10737 validating data in memory, anyway, so you may as well validate.&lt;/p&gt;
        10738 &lt;h1&gt;C strings and Rust&lt;/h1&gt;
        10739 &lt;p&gt;For unfortunate historical reasons, C flings around &lt;code&gt;char *&lt;/code&gt; to mean
        10740 different things.  In the context of Glib, it can mean&lt;/p&gt;
        10741 &lt;ul&gt;
        10742 &lt;li&gt;A valid, nul-terminated UTF-8 sequence of bytes (a "normal string")&lt;/li&gt;
        10743 &lt;li&gt;A nul-terminated file path, which has no meaningful encoding&lt;/li&gt;
        10744 &lt;li&gt;A nul-terminated sequence of bytes, not validated as UTF-8.&lt;/li&gt;
        10745 &lt;/ul&gt;
        10746 &lt;p&gt;What a particular &lt;code&gt;char *&lt;/code&gt; means depends on which API you got it from.&lt;/p&gt;
        10747 &lt;h2&gt;Bringing a string from C to Rust&lt;/h2&gt;
        10748 &lt;p&gt;From Rust's viewpoint, getting a raw &lt;code&gt;char *&lt;/code&gt; from C (a "&lt;code&gt;*const
        10749 c_char&lt;/code&gt;" in Rust parlance) means that it gets a pointer to a buffer of
        10750 unknown length.&lt;/p&gt;
        10751 &lt;p&gt;Now, that may not be entirely accurate:&lt;/p&gt;
        10752 &lt;ul&gt;
        10753 &lt;li&gt;You may indeed only have a pointer to a buffer of unknown length&lt;/li&gt;
        10754 &lt;li&gt;You may have a pointer to a buffer, and also know its length
        10755   (i.e. the offset at which the nul terminator is)&lt;/li&gt;
        10756 &lt;/ul&gt;
        10757 &lt;p&gt;The Rust standard library provides a &lt;a href="https://doc.rust-lang.org/std/ffi/struct.CStr.html"&gt;&lt;code&gt;CStr&lt;/code&gt;&lt;/a&gt; object, which means,
        10758 "I have a pointer to an array of bytes, and I know its length, and I
        10759 know the last byte is a nul".&lt;/p&gt;
        10760 &lt;p&gt;&lt;code&gt;CStr&lt;/code&gt; provides an &lt;a href="https://doc.rust-lang.org/std/ffi/struct.CStr.html#method.from_ptr"&gt;&lt;code&gt;unsafe from_ptr()&lt;/code&gt;&lt;/a&gt; constructor which takes a
        10761 raw pointer, and walks the memory to which it points until it finds a
        10762 nul byte.  You &lt;em&gt;must&lt;/em&gt; give it a valid pointer, and you had better
        10763 guarantee that there is a nul terminator, or &lt;code&gt;CStr&lt;/code&gt; will walk until
        10764 the end of your process' address space looking for one.&lt;/p&gt;
        10765 &lt;p&gt;Alternatively, if you know the length of your byte array, and you know
        10766 that it has a nul byte at the end, you can
        10767 call &lt;a href="https://doc.rust-lang.org/std/ffi/struct.CStr.html#method.from_bytes_with_nul"&gt;&lt;code&gt;CStr::from_bytes_with_nul()&lt;/code&gt;&lt;/a&gt;.  You pass it a &lt;code&gt;&amp;amp;[u8]&lt;/code&gt; slice;
        10768 the function will check that a) the last byte in that slice is indeed
        10769 a nul, and b) there are no nul bytes in the middle.&lt;/p&gt;
        10770 &lt;p&gt;The unsafe version of this last function
        10771 is &lt;a href="https://doc.rust-lang.org/std/ffi/struct.CStr.html#method.from_bytes_with_nul_unchecked"&gt;&lt;code&gt;unsafe CStr::from_bytes_with_nul_unchecked()&lt;/code&gt;&lt;/a&gt;: it also takes
        10772 an &lt;code&gt;&amp;amp;[u8]&lt;/code&gt; slice, but &lt;em&gt;you&lt;/em&gt; must guarantee that the last byte is a nul
        10773 and that there are no nul bytes in the middle.&lt;/p&gt;
        10774 &lt;p&gt;&lt;em&gt;I really like that the Rust documentation tells you when functions
        10775 are not "instantaneous" and must instead walks arrays, like to do
        10776 validation or to look for the nul terminator above.&lt;/em&gt;&lt;/p&gt;
        10777 &lt;h2&gt;Turning a CStr into a string-like&lt;/h2&gt;
        10778 &lt;p&gt;Now, the above indicates that a &lt;code&gt;CStr&lt;/code&gt; is a nul-terminated array of
        10779 bytes.  We have no idea what the bytes inside look like; we just know
        10780 that they don't contain any other nul bytes.&lt;/p&gt;
        10781 &lt;p&gt;There is a &lt;a href="https://doc.rust-lang.org/std/ffi/struct.CStr.html#method.to_str"&gt;&lt;code&gt;CStr::to_str()&lt;/code&gt;&lt;/a&gt; method, which returns a
        10782 &lt;code&gt;Result&amp;lt;&amp;amp;str, Utf8Error&amp;gt;&lt;/code&gt;.  It performs UTF-8 validation on the array
        10783 of bytes.  If the array is valid, the function just returns a slice of
        10784 the validated bytes minus the nul terminator (i.e. just what you
        10785 expect for a Rust string slice).  Otherwise, it returns an &lt;code&gt;Utf8Error&lt;/code&gt;
        10786 with the details like we discussed before.&lt;/p&gt;
        10787 &lt;p&gt;There is also &lt;a href="https://doc.rust-lang.org/std/ffi/struct.CStr.html#method.to_string_lossy"&gt;&lt;code&gt;CStr::to_string_lossy()&lt;/code&gt;&lt;/a&gt; which does the
        10788 replacement of invalid UTF-8 sequences like we discussed before.&lt;/p&gt;
        10789 &lt;h1&gt;Conclusion&lt;/h1&gt;
        10790 &lt;p&gt;Strings in Rust are UTF-8 encoded, they know their length, and they
        10791 can have nul bytes in the middle.&lt;/p&gt;
        10792 &lt;p&gt;To build a string from raw bytes, you must go through functions that
        10793 do UTF-8 validation and tell you if it failed.  There are unsafe
        10794 functions that let you skip validation, but then of course you are on
        10795 your own.&lt;/p&gt;
        10796 &lt;p&gt;The low-level functions which read data from files operate on bytes.
        10797 On top of those, there are convenience functions to read validated
        10798 UTF-8 characters, lines, etc.  All of these tell you when there was
        10799 invalid UTF-8 or an I/O error.&lt;/p&gt;
        10800 &lt;p&gt;Rust lets you wrap a raw &lt;code&gt;char *&lt;/code&gt; that you got from C into something
        10801 that can later be validated and turned into a string.  Anything that
        10802 manipulates a raw pointer is &lt;code&gt;unsafe&lt;/code&gt;; this includes the "wrap me this
        10803 pointer into a C string abstraction" API, and the "build me an array
        10804 of bytes from this raw pointer" API.  Later, you can validate &lt;em&gt;those&lt;/em&gt;
        10805 as UTF-8 and build real Rust strings — or know if the validation
        10806 failed.&lt;/p&gt;
        10807 &lt;p&gt;Rust builds these little "corridors" through the API so that illegal
        10808 states are unrepresentable.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category></entry><entry><title>GUADEC 2017 presentation</title><link href="https://people.gnome.org/~federico/blog/guadec-2017.html" rel="alternate"></link><published>2017-08-09T20:20:49-05:00</published><updated>2017-08-09T20:20:52-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-08-09:/~federico/blog/guadec-2017.html</id><summary type="html">&lt;p&gt;During GUADEC this year I gave a presentation
        10809 called
        10810 &lt;a href="https://people.gnome.org/~federico/blog/docs/fmq-porting-c-to-rust.pdf"&gt;Replacing C library code with Rust: what I learned with librsvg&lt;/a&gt;.
        10811 This is the PDF file; be sure to scroll past the full-page
        10812 presentation pages until you reach the speaker's notes, especially for
        10813 the code sections!&lt;/p&gt;
        10814 &lt;p&gt;&lt;a href="https://people.gnome.org/~federico/blog/docs/fmq-porting-c-to-rust.pdf"&gt;&lt;img alt="Replacing C library code with Rust - link to PDF" src="https://people.gnome.org/~federico/blog/images/fmq-porting-c-to-rust.png"&gt;&lt;/a&gt;&lt;/p&gt;
        10815 &lt;p&gt;You can also get the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;During GUADEC this year I gave a presentation
        10816 called
        10817 &lt;a href="https://people.gnome.org/~federico/blog/docs/fmq-porting-c-to-rust.pdf"&gt;Replacing C library code with Rust: what I learned with librsvg&lt;/a&gt;.
        10818 This is the PDF file; be sure to scroll past the full-page
        10819 presentation pages until you reach the speaker's notes, especially for
        10820 the code sections!&lt;/p&gt;
        10821 &lt;p&gt;&lt;a href="https://people.gnome.org/~federico/blog/docs/fmq-porting-c-to-rust.pdf"&gt;&lt;img alt="Replacing C library code with Rust - link to PDF" src="https://people.gnome.org/~federico/blog/images/fmq-porting-c-to-rust.png"&gt;&lt;/a&gt;&lt;/p&gt;
        10822 &lt;p&gt;You can also get the &lt;a href="https://people.gnome.org/~federico/blog/docs/fmq-porting-c-to-rust.odp"&gt;ODP file&lt;/a&gt; for the presentation.  This is
        10823 released under a &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC-BY-SA license&lt;/a&gt;.&lt;/p&gt;
        10824 &lt;p&gt;For the presentation, my daughter Luciana made some drawings of
        10825 Ferris, the Rust mascot, also released under the same license:&lt;/p&gt;
        10826 &lt;p&gt;&lt;a href="https://people.gnome.org/~federico/blog/docs/ferris-1.png"&gt;&lt;img alt="Ferris says hi" src="https://people.gnome.org/~federico/blog/docs/ferris-1-thumb.png"&gt;&lt;/a&gt;
        10827 &lt;a href="https://people.gnome.org/~federico/blog/docs/ferris-2.png"&gt;&lt;img alt="Ferris busy at work" src="https://people.gnome.org/~federico/blog/docs/ferris-2-thumb.png"&gt;&lt;/a&gt;
        10828 &lt;a href="https://people.gnome.org/~federico/blog/docs/ferris-3.png"&gt;&lt;img alt="Ferris makes a mess" src="https://people.gnome.org/~federico/blog/docs/ferris-3-thumb.png"&gt;&lt;/a&gt;
        10829 &lt;a href="https://people.gnome.org/~federico/blog/docs/ferris-4.png"&gt;&lt;img alt="Ferris presents her work" src="https://people.gnome.org/~federico/blog/docs/ferris-4-thumb.png"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="misc"></category><category term="gnome"></category><category term="guadec"></category><category term="librsvg"></category><category term="rust"></category><category term="talks"></category></entry><entry><title>Surviving a rust-cssparser API break</title><link href="https://people.gnome.org/~federico/blog/surviving-rust-cssparser-api-break.html" rel="alternate"></link><published>2017-08-01T06:02:30-05:00</published><updated>2017-08-01T06:02:37-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-08-01:/~federico/blog/surviving-rust-cssparser-api-break.html</id><summary type="html">&lt;p&gt;Yesterday I looked into updating librsvg's Rust dependencies.  There have
        10830 been some API breaks (!!!) in the unstable libraries that it uses
        10831 since the last time I locked them.  This post is about an interesting
        10832 case of API breakage.&lt;/p&gt;
        10833 &lt;p&gt;&lt;a href="https://github.com/servo/rust-cssparser"&gt;rust-cssparser&lt;/a&gt; is the crate that &lt;a href="https://servo.org/"&gt;Servo&lt;/a&gt; uses for parsing
        10834 CSS.  Well, more …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Yesterday I looked into updating librsvg's Rust dependencies.  There have
        10835 been some API breaks (!!!) in the unstable libraries that it uses
        10836 since the last time I locked them.  This post is about an interesting
        10837 case of API breakage.&lt;/p&gt;
        10838 &lt;p&gt;&lt;a href="https://github.com/servo/rust-cssparser"&gt;rust-cssparser&lt;/a&gt; is the crate that &lt;a href="https://servo.org/"&gt;Servo&lt;/a&gt; uses for parsing
        10839 CSS.  Well, more like &lt;em&gt;tokenizing&lt;/em&gt; CSS: you give it a string, it
        10840 gives you back tokens, and you are supposed to compose CSS selector
        10841 information or other CSS values from the tokens.&lt;/p&gt;
        10842 &lt;p&gt;Librsvg uses rust-cssparser now for most of the micro-languages in
        10843 SVG's attribute values, instead of its old, fragile C parsers.  I hope
        10844 to be able to use it in conjunction with Servo's &lt;a href="https://github.com/servo/servo/tree/master/components/selectors"&gt;rust-selectors&lt;/a&gt;
        10845 crate to fully parse CSS data and replace &lt;a href="https://git.gnome.org/browse/libcroco"&gt;libcroco&lt;/a&gt;.&lt;/p&gt;
        10846 &lt;p&gt;A few months ago, rust-cssparser's API looked more or less like the
        10847 following.  This is the old representation of a &lt;code&gt;Token&lt;/code&gt;:&lt;/p&gt;
        10848 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10849 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// an identifier&lt;/span&gt;
        10850 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Ident&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Cow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10851 
        10852 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// a plain number&lt;/span&gt;
        10853 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NumericValue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10854 
        10855 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// a percentage value normalized to [0.0, 1.0]&lt;/span&gt;
        10856 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Percentage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PercentageValue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10857 
        10858 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;WhiteSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10859 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Comma&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10860 
        10861 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10862 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10863 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10864 
        10865 &lt;p&gt;That is, a &lt;code&gt;Token&lt;/code&gt; can be an &lt;code&gt;Ident&lt;/code&gt;ifier with a string name, or a
        10866 &lt;code&gt;Number&lt;/code&gt;, a &lt;code&gt;Percentage&lt;/code&gt;, whitespace, a comma, and many others.&lt;/p&gt;
        10867 &lt;p&gt;On top of that is the old API for a &lt;code&gt;Parser&lt;/code&gt;, which you construct with
        10868 a string and then it gives you back tokens:&lt;/p&gt;
        10869 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10870 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt; &lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Parser&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10871 
        10872 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10873 
        10874 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10875 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10876 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10877 
        10878 &lt;p&gt;This means the following.  You create the parser out of a string slice
        10879 with &lt;code&gt;new()&lt;/code&gt;.  You can then extract a &lt;code&gt;Result&lt;/code&gt; with a &lt;code&gt;Token&lt;/code&gt;
        10880 sucessfully, or with an empty error value.  The parser uses a lifetime
        10881 &lt;code&gt;'i&lt;/code&gt; on the string from which it is constructed:  the &lt;code&gt;Token&lt;/code&gt;s that
        10882 return identifiers, for example, could return sub-string slices that
        10883 come from the original string, and the parser has to be marked with a
        10884 lifetime so that it does not outlive its underlying string.&lt;/p&gt;
        10885 &lt;p&gt;A few commits later, rust-cssparser got changed to return detailed
        10886 error values, so that instead of &lt;code&gt;()&lt;/code&gt; you get a a &lt;code&gt;BasicParseError&lt;/code&gt;
        10887 with sub-cases like &lt;code&gt;UnexpectedToken&lt;/code&gt; or &lt;code&gt;EndOfInput&lt;/code&gt;.&lt;/p&gt;
        10888 &lt;p&gt;After the changes to the error values for results, I didn't pay much
        10889 attention to rust-cssparser for while.  Yesterday I wanted to update
        10890 librsvg to use the newest rust-cssparser, and had some interesting
        10891 problems.&lt;/p&gt;
        10892 &lt;p&gt;First, &lt;code&gt;Parser::new()&lt;/code&gt; was changed from taking just a &lt;code&gt;&amp;amp;str&lt;/code&gt; slice to
        10893 taking a &lt;code&gt;ParserInput&lt;/code&gt; struct.  This is an implementation detail which
        10894 lets the parser cache the last token it saw.  Not a big deal:&lt;/p&gt;
        10895 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// instead of constructing a parser like&lt;/span&gt;
        10896 &lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10897 
        10898 &lt;span class="c1"&gt;// you now construct it like&lt;/span&gt;
        10899 &lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParserInput&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10900 &lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10901 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10902 
        10903 &lt;p&gt;I am not completely sure why this is exposed to the public API, since
        10904 Rust won't allow you to have two mutable references to a
        10905 &lt;code&gt;ParserInput&lt;/code&gt;, and the only consumer of a (mutable) &lt;code&gt;ParserInput&lt;/code&gt; is
        10906 the &lt;code&gt;Parser&lt;/code&gt;, anyway.&lt;/p&gt;
        10907 &lt;p&gt;However, the &lt;code&gt;parser.next()&lt;/code&gt; function changed:&lt;/p&gt;
        10908 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// old version&lt;/span&gt;
        10909 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10910 
        10911 &lt;span class="c1"&gt;// new version&lt;/span&gt;
        10912 &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BasicParseError&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10913 &lt;span class="c1"&gt;// note this bad boy here -------^&lt;/span&gt;
        10914 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10915 
        10916 &lt;p&gt;The successful &lt;code&gt;Result&lt;/code&gt; from &lt;code&gt;next()&lt;/code&gt; is now a &lt;em&gt;reference&lt;/em&gt; to a
        10917 &lt;code&gt;Token&lt;/code&gt;, not a plain &lt;code&gt;Token&lt;/code&gt; value which you now own.  The parser is
        10918 giving you a borrowed reference to its internally-cached token.&lt;/p&gt;
        10919 &lt;p&gt;My parsing functions for the old API looked similar to the
        10920 following.  This is a function that parses a string into an angle; it
        10921 can look like &lt;code&gt;"45deg"&lt;/code&gt; or &lt;code&gt;"1.5rad"&lt;/code&gt;, for example.&lt;/p&gt;
        10922 &lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
        10923 &lt;span class="normal"&gt; 2&lt;/span&gt;
        10924 &lt;span class="normal"&gt; 3&lt;/span&gt;
        10925 &lt;span class="normal"&gt; 4&lt;/span&gt;
        10926 &lt;span class="normal"&gt; 5&lt;/span&gt;
        10927 &lt;span class="normal"&gt; 6&lt;/span&gt;
        10928 &lt;span class="normal"&gt; 7&lt;/span&gt;
        10929 &lt;span class="normal"&gt; 8&lt;/span&gt;
        10930 &lt;span class="normal"&gt; 9&lt;/span&gt;
        10931 &lt;span class="normal"&gt;10&lt;/span&gt;
        10932 &lt;span class="normal"&gt;11&lt;/span&gt;
        10933 &lt;span class="normal"&gt;12&lt;/span&gt;
        10934 &lt;span class="normal"&gt;13&lt;/span&gt;
        10935 &lt;span class="normal"&gt;14&lt;/span&gt;
        10936 &lt;span class="normal"&gt;15&lt;/span&gt;
        10937 &lt;span class="normal"&gt;16&lt;/span&gt;
        10938 &lt;span class="normal"&gt;17&lt;/span&gt;
        10939 &lt;span class="normal"&gt;18&lt;/span&gt;
        10940 &lt;span class="normal"&gt;19&lt;/span&gt;
        10941 &lt;span class="normal"&gt;20&lt;/span&gt;
        10942 &lt;span class="normal"&gt;21&lt;/span&gt;
        10943 &lt;span class="normal"&gt;22&lt;/span&gt;
        10944 &lt;span class="normal"&gt;23&lt;/span&gt;
        10945 &lt;span class="normal"&gt;24&lt;/span&gt;
        10946 &lt;span class="normal"&gt;25&lt;/span&gt;
        10947 &lt;span class="normal"&gt;26&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse_angle_degrees&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10948 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10949 
        10950 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10951 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map_err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;expected angle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10952 
        10953 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10954 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;::&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NumericValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10955 
        10956 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;::&lt;span class="n"&gt;Dimension&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NumericValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10957 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10958 
        10959 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10960 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;deg&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10961 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;grad&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;360.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;400.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10962 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rad&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;180.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PI&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10963 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;expected angle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10964 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10965 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10966 
        10967 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;expected angle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10968 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="n"&gt;and_then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10969 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expect_exhausted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10970 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10971 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map_err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;expected angle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10972 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10973 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10974 &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
        10975 &lt;p&gt;This is a bit ugly, but it was the first version that passed the
        10976 tests.  Lines 4 and 5 mean, "get the first token or return an error".
        10977 Line 17 means, "anything except &lt;code&gt;deg&lt;/code&gt;, &lt;code&gt;grad&lt;/code&gt;, or &lt;code&gt;rad&lt;/code&gt; for the units
        10978 causes the &lt;code&gt;match&lt;/code&gt; expression to generate an error".  Finally, I was
        10979 feeling very proud of using &lt;code&gt;and_then()&lt;/code&gt; in line 22, with
        10980 &lt;code&gt;parser.expect_exhausted()&lt;/code&gt;, to ensure that the parser would not find
        10981 any more tokens after the angle/units.&lt;/p&gt;
        10982 &lt;p&gt;However, in the new version of rust-cssparser, Parser.next() gives
        10983 back a &lt;code&gt;Result&lt;/code&gt; with a &lt;code&gt;&amp;amp;Token&lt;/code&gt; success value — a &lt;em&gt;reference&lt;/em&gt; to a
        10984 token —, while the old version returned a plain &lt;code&gt;Token&lt;/code&gt;.  No problem,
        10985 I thought, I'm just going to de-reference the value in the &lt;code&gt;match&lt;/code&gt; and
        10986 be done with it:&lt;/p&gt;
        10987 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10988 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map_err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;expected angle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10989 
        10990 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10991 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//    ^ dereference here...&lt;/span&gt;
        10992 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;::&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10993 
        10994 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;::&lt;span class="n"&gt;Dimension&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        10995 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//                            ^ avoid moving the unit value&lt;/span&gt;
        10996 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        10997 
        10998 &lt;p&gt;The compiler complained elsewhere.  The whole function now looked like
        10999 this:&lt;/p&gt;
        11000 &lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
        11001 &lt;span class="normal"&gt; 2&lt;/span&gt;
        11002 &lt;span class="normal"&gt; 3&lt;/span&gt;
        11003 &lt;span class="normal"&gt; 4&lt;/span&gt;
        11004 &lt;span class="normal"&gt; 5&lt;/span&gt;
        11005 &lt;span class="normal"&gt; 6&lt;/span&gt;
        11006 &lt;span class="normal"&gt; 7&lt;/span&gt;
        11007 &lt;span class="normal"&gt; 8&lt;/span&gt;
        11008 &lt;span class="normal"&gt; 9&lt;/span&gt;
        11009 &lt;span class="normal"&gt;10&lt;/span&gt;
        11010 &lt;span class="normal"&gt;11&lt;/span&gt;
        11011 &lt;span class="normal"&gt;12&lt;/span&gt;
        11012 &lt;span class="normal"&gt;13&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;parse_angle_degrees&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11013 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11014 
        11015 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11016 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map_err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;expected angle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11017 
        11018 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11019 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
        11020 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="n"&gt;and_then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11021 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expect_exhausted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11022 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11023 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map_err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;expected angle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11024 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11025 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11026 &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
        11027 &lt;p&gt;But in line 4, &lt;code&gt;token&lt;/code&gt; is now a reference to something that lives
        11028 inside &lt;code&gt;parser&lt;/code&gt;, and &lt;code&gt;parser&lt;/code&gt; is therefore borrowed mutably.  The
        11029 compiler didn't like that line 10 (the call to
        11030 &lt;code&gt;parser.expect_exhausted()&lt;/code&gt;) was trying to borrow &lt;code&gt;parser&lt;/code&gt; mutably
        11031 again.&lt;/p&gt;
        11032 &lt;p&gt;I played a bit with creating a temporary scope around the assignment
        11033 to &lt;code&gt;token&lt;/code&gt; so that it would only borrow &lt;code&gt;parser&lt;/code&gt; mutably inside that
        11034 scope.  Things ended up like this, without the call to &lt;code&gt;and_then()&lt;/code&gt;
        11035 after the &lt;code&gt;match&lt;/code&gt;:&lt;/p&gt;
        11036 &lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
        11037 &lt;span class="normal"&gt; 2&lt;/span&gt;
        11038 &lt;span class="normal"&gt; 3&lt;/span&gt;
        11039 &lt;span class="normal"&gt; 4&lt;/span&gt;
        11040 &lt;span class="normal"&gt; 5&lt;/span&gt;
        11041 &lt;span class="normal"&gt; 6&lt;/span&gt;
        11042 &lt;span class="normal"&gt; 7&lt;/span&gt;
        11043 &lt;span class="normal"&gt; 8&lt;/span&gt;
        11044 &lt;span class="normal"&gt; 9&lt;/span&gt;
        11045 &lt;span class="normal"&gt;10&lt;/span&gt;
        11046 &lt;span class="normal"&gt;11&lt;/span&gt;
        11047 &lt;span class="normal"&gt;12&lt;/span&gt;
        11048 &lt;span class="normal"&gt;13&lt;/span&gt;
        11049 &lt;span class="normal"&gt;14&lt;/span&gt;
        11050 &lt;span class="normal"&gt;15&lt;/span&gt;
        11051 &lt;span class="normal"&gt;16&lt;/span&gt;
        11052 &lt;span class="normal"&gt;17&lt;/span&gt;
        11053 &lt;span class="normal"&gt;18&lt;/span&gt;
        11054 &lt;span class="normal"&gt;19&lt;/span&gt;
        11055 &lt;span class="normal"&gt;20&lt;/span&gt;
        11056 &lt;span class="normal"&gt;21&lt;/span&gt;
        11057 &lt;span class="normal"&gt;22&lt;/span&gt;
        11058 &lt;span class="normal"&gt;23&lt;/span&gt;
        11059 &lt;span class="normal"&gt;24&lt;/span&gt;
        11060 &lt;span class="normal"&gt;25&lt;/span&gt;
        11061 &lt;span class="normal"&gt;26&lt;/span&gt;
        11062 &lt;span class="normal"&gt;27&lt;/span&gt;
        11063 &lt;span class="normal"&gt;28&lt;/span&gt;
        11064 &lt;span class="normal"&gt;29&lt;/span&gt;
        11065 &lt;span class="normal"&gt;30&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;angle_degrees&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nb"&gt;Result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11066 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParserInput&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11067 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11068 
        11069 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11070 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11071 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map_err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;expected angle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11072 
        11073 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11074 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;::&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11075 
        11076 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;::&lt;span class="n"&gt;Dimension&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11077 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11078 
        11079 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11080 &lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;deg&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11081 &lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;grad&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;360.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;400.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11082 &lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rad&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;180.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11083 &lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;expected &amp;#39;deg&amp;#39; | &amp;#39;grad&amp;#39; | &amp;#39;rad&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11084 &lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11085 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11086 
        11087 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;expected angle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11088 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11089 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11090 
        11091 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expect_exhausted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;map_err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParseError&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;expected angle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11092 
        11093 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11094 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11095 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11096 &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
        11097 &lt;p&gt;Lines 5 through 25 are basically&lt;/p&gt;
        11098 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11099 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// parse out the angle; return if error&lt;/span&gt;
        11100 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11101 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11102 
        11103 &lt;p&gt;And after &lt;em&gt;that&lt;/em&gt; is done, I test for &lt;code&gt;parser.expect_exhausted()&lt;/code&gt;.
        11104 There is no chaining of results with helper functions; instead it's
        11105 just going through each token linearly.&lt;/p&gt;
        11106 &lt;p&gt;The API break was annoying to deal with, but fortunately the calling
        11107 code ended up cleaner, and I didn't have to change anything in the
        11108 tests.  I hope rust-cssparser can stabilize its API for consumers that
        11109 are not Servo.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category><category term="gnome"></category><category term="librsvg"></category></entry><entry><title>Legacy Systems as Old Cities</title><link href="https://people.gnome.org/~federico/blog/legacy-systems-as-old-cities.html" rel="alternate"></link><published>2017-06-28T21:26:00-05:00</published><updated>2017-07-10T22:40:24-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-06-28:/~federico/blog/legacy-systems-as-old-cities.html</id><summary type="html">&lt;p&gt;&lt;em&gt;I just realized that I only tweeted about this a couple of months ago,
        11110 but never blogged about it.  Shame on me!&lt;/em&gt;&lt;/p&gt;
        11111 &lt;p&gt;I wrote an article, &lt;a href="https://recompilermag.com/issues/issue-4/legacy-systems-as-old-cities/"&gt;Legacy Systems as Old Cities&lt;/a&gt;, for The
        11112 Recompiler magazine.  Is GNOME, now at 20 years old, legacy software?
        11113 Is it different from mainframe software …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;I just realized that I only tweeted about this a couple of months ago,
        11114 but never blogged about it.  Shame on me!&lt;/em&gt;&lt;/p&gt;
        11115 &lt;p&gt;I wrote an article, &lt;a href="https://recompilermag.com/issues/issue-4/legacy-systems-as-old-cities/"&gt;Legacy Systems as Old Cities&lt;/a&gt;, for The
        11116 Recompiler magazine.  Is GNOME, now at 20 years old, legacy software?
        11117 Is it different from mainframe software because "everyone" can change
        11118 it?  Does long-lived software have the same patterns of change as
        11119 cities and physical artifacts?  Can we learn from the building trades
        11120 and urbanism for maintaining software in the long term?  &lt;em&gt;Could we
        11121 turn legacy software into a good legacy?&lt;/em&gt;&lt;/p&gt;
        11122 &lt;p&gt;You can read the article &lt;a href="https://recompilermag.com/issues/issue-4/legacy-systems-as-old-cities/"&gt;here&lt;/a&gt;.&lt;/p&gt;
        11123 &lt;p&gt;Also, let me take this opportunity to recommend &lt;a href="https://recompilermag.com"&gt;The Recompiler&lt;/a&gt;
        11124 magazine.  It is the most enjoyable technical publication I read.
        11125 Their &lt;a href="https://recompilermag.com/podcast/"&gt;podcast&lt;/a&gt; is also excellent!&lt;/p&gt;
        11126 &lt;p&gt;&lt;strong&gt;Update 2017/06/10&lt;/strong&gt; - Spanish version of the article, &lt;a href="legacy-systems-as-old-cities-es.html"&gt;Los Sistemas Heredados como Ciudades Viejas&lt;/a&gt;&lt;/p&gt;</content><category term="misc"></category><category term="recompiler"></category><category term="gnome"></category><category term="urbanism"></category></entry><entry><title>Setting Alt-Tab behavior in gnome-shell</title><link href="https://people.gnome.org/~federico/blog/alt-tab.html" rel="alternate"></link><published>2017-06-22T10:25:02-05:00</published><updated>2017-06-22T10:25:06-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-06-22:/~federico/blog/alt-tab.html</id><summary type="html">&lt;p&gt;After updating my distro a few months ago, I somehow lost my tweaks to
        11127 the Alt-Tab behavior in gnome-shell.&lt;/p&gt;
        11128 &lt;p&gt;The default is to have &lt;code&gt;Alt-Tab&lt;/code&gt; switch you between applications in the
        11129 current workspace.  One can use &lt;code&gt;Alt-backtick&lt;/code&gt; (or whatever key you
        11130 have above Tab) to switch between windows in the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;After updating my distro a few months ago, I somehow lost my tweaks to
        11131 the Alt-Tab behavior in gnome-shell.&lt;/p&gt;
        11132 &lt;p&gt;The default is to have &lt;code&gt;Alt-Tab&lt;/code&gt; switch you between applications in the
        11133 current workspace.  One can use &lt;code&gt;Alt-backtick&lt;/code&gt; (or whatever key you
        11134 have above Tab) to switch between windows in the current application.&lt;/p&gt;
        11135 &lt;p&gt;I prefer a Windows-like setup, where &lt;code&gt;Alt-Tab&lt;/code&gt; switches between
        11136 windows in the current workspace, regardless of the application to
        11137 which they belong.&lt;/p&gt;
        11138 &lt;p&gt;Many moons ago there was a gnome-shell extension to change this
        11139 behavior, but these days (GNOME 3.24) it can be done without
        11140 extensions.  It is a bit convoluted.&lt;/p&gt;
        11141 &lt;h1&gt;With the GUI&lt;/h1&gt;
        11142 &lt;p&gt;If you are using X instead of Wayland, this works:&lt;/p&gt;
        11143 &lt;ol&gt;
        11144 &lt;li&gt;
        11145 &lt;p&gt;Unset the &lt;strong&gt;Switch applications&lt;/strong&gt; command.  To do this, run
        11146    &lt;code&gt;gnome-control-center&lt;/code&gt;, go to &lt;em&gt;Keyboard&lt;/em&gt;, and find the &lt;em&gt;Switch
        11147    applications&lt;/em&gt; command.  Click on it, and hit &lt;code&gt;Backspace&lt;/code&gt; in the
        11148    dialog that prompts you for the keyboard shortcut.  Click on the
        11149    &lt;em&gt;Set&lt;/em&gt; button.&lt;/p&gt;
        11150 &lt;/li&gt;
        11151 &lt;li&gt;
        11152 &lt;p&gt;Set the &lt;strong&gt;Switch windows&lt;/strong&gt; command.  While still in the
        11153    &lt;em&gt;Keyboard&lt;/em&gt; settings, find the &lt;em&gt;Switch windows&lt;/em&gt; command.  Click on
        11154    it, and hit &lt;code&gt;Alt-Tab&lt;/code&gt;.  Click &lt;em&gt;Set&lt;/em&gt;.&lt;/p&gt;
        11155 &lt;/li&gt;
        11156 &lt;/ol&gt;
        11157 &lt;p&gt;That should be all you need, unless you are in Wayland.  In that case,
        11158 you need to do it on the command line.&lt;/p&gt;
        11159 &lt;h1&gt;With the command line, or in Wayland&lt;/h1&gt;
        11160 &lt;p&gt;The kind people on &lt;a href="irc://irc.gnome.org/#gnome-hackers"&gt;&lt;code&gt;#gnome-hackers&lt;/code&gt;&lt;/a&gt; tell me that as of GNOME
        11161 3.24, changing &lt;code&gt;Alt-Tab&lt;/code&gt; doesn't work on Wayland as in (2) above,
        11162 because the compositor captures the &lt;code&gt;Alt-Tab&lt;/code&gt; key when you type it
        11163 inside the dialog that prompts you for a keyboard shortcut.  In that
        11164 case, you have to change the configuration keys directly instead of
        11165 using the GUI:&lt;/p&gt;
        11166 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;gsettings &lt;span class="nb"&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-applications &lt;span class="s2"&gt;&amp;quot;[]&amp;quot;&lt;/span&gt;
        11167 gsettings &lt;span class="nb"&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-applications-backward &lt;span class="s2"&gt;&amp;quot;[]&amp;quot;&lt;/span&gt;
        11168 gsettings &lt;span class="nb"&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-windows &lt;span class="s2"&gt;&amp;quot;[&amp;#39;&amp;lt;Alt&amp;gt;Tab&amp;#39;, &amp;#39;&amp;lt;Super&amp;gt;Tab&amp;#39;]&amp;quot;&lt;/span&gt;
        11169 gsettings &lt;span class="nb"&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-windows-backward  &lt;span class="s2"&gt;&amp;quot;[&amp;#39;&amp;lt;Alt&amp;gt;&amp;lt;Shift&amp;gt;Tab&amp;#39;, &amp;#39;&amp;lt;Super&amp;gt;&amp;lt;Shift&amp;gt;Tab&amp;#39;]&amp;quot;&lt;/span&gt;
        11170 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11171 
        11172 &lt;p&gt;Of course the above also works in X, too.&lt;/p&gt;
        11173 &lt;h1&gt;Changing windows across all workspaces&lt;/h1&gt;
        11174 &lt;p&gt;If you'd like to switch between windows in all workspaces, rather than
        11175 in the current workspace, find the &lt;code&gt;org.gnome.shell.window-switcher
        11176 current-workspace-only&lt;/code&gt; GSettings key and change it.  You can do this
        11177 in &lt;code&gt;dconf-editor&lt;/code&gt;, or on the command line with&lt;/p&gt;
        11178 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;gsettings &lt;span class="nb"&gt;set&lt;/span&gt; org.gnome.shell.window-switcher current-workspace-only &lt;span class="nb"&gt;true&lt;/span&gt;
        11179 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="misc"></category><category term="gnome"></category><category term="gnome-shell"></category></entry><entry><title>Exploring Rust's standard library: system calls and errors</title><link href="https://people.gnome.org/~federico/blog/rust-libstd-syscalls-and-errors.html" rel="alternate"></link><published>2017-06-12T10:55:26-05:00</published><updated>2017-06-12T17:11:52-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-06-12:/~federico/blog/rust-libstd-syscalls-and-errors.html</id><summary type="html">&lt;p&gt;In this post I'll show you the code path that Rust takes inside its
        11180 standard library when you open a file.  I wanted to learn how Rust
        11181 handles system calls and &lt;code&gt;errno&lt;/code&gt;, and all the little subtleties of the
        11182 POSIX API.  This is what I learned!&lt;/p&gt;
        11183 &lt;h1&gt;The C side of …&lt;/h1&gt;</summary><content type="html">&lt;p&gt;In this post I'll show you the code path that Rust takes inside its
        11184 standard library when you open a file.  I wanted to learn how Rust
        11185 handles system calls and &lt;code&gt;errno&lt;/code&gt;, and all the little subtleties of the
        11186 POSIX API.  This is what I learned!&lt;/p&gt;
        11187 &lt;h1&gt;The C side of things&lt;/h1&gt;
        11188 &lt;p&gt;When you open a file, or create a socket, or do anything else that
        11189 returns an object that can be accessed like a file, you get a &lt;em&gt;file
        11190 descriptor&lt;/em&gt; in the form of an &lt;code&gt;int&lt;/code&gt;.&lt;/p&gt;
        11191 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cm"&gt;/* All of these return a int with a file descriptor, or&lt;/span&gt;
        11192 &lt;span class="cm"&gt; * -1 in case of error.&lt;/span&gt;
        11193 &lt;span class="cm"&gt; */&lt;/span&gt;
        11194 &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;
        11195 &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        11196 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11197 
        11198 &lt;p&gt;You get a nonnegative integer in case of success, or -1 in case of an
        11199 error.  If there's an error, you look at &lt;code&gt;errno&lt;/code&gt;, which gives you an
        11200 integer error code.  &lt;/p&gt;
        11201 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        11202 
        11203 &lt;span class="nl"&gt;retry_open&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        11204 &lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;open&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/foo/bar/baz.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        11205 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        11206     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ENOENT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        11207         &lt;span class="cm"&gt;/* File doesn&amp;#39;t exist */&lt;/span&gt;
        11208     &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        11209         &lt;span class="p"&gt;...&lt;/span&gt;
        11210     &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EINTR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        11211         &lt;span class="k"&gt;goto&lt;/span&gt; &lt;span class="n"&gt;retry_open&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* interrupted system call; let&amp;#39;s retry */&lt;/span&gt;
        11212     &lt;span class="p"&gt;}&lt;/span&gt;
        11213 &lt;span class="p"&gt;}&lt;/span&gt;
        11214 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11215 
        11216 &lt;p&gt;Many system calls can return &lt;code&gt;EINTR&lt;/code&gt;, which means "interrupted system
        11217 call", which means that &lt;em&gt;something&lt;/em&gt; interrupted the kernel while it
        11218 was doing your system call and it returned control to userspace, with
        11219 the syscall unfinished.  For example, your process may have received a
        11220 Unix signal (e.g. you send it &lt;code&gt;SIGSTOP&lt;/code&gt; by pressing Ctrl-Z on a
        11221 terminal, or you resized the terminal and your process got a
        11222 &lt;code&gt;SIGWINCH&lt;/code&gt;).  Most of the time &lt;code&gt;EINTR&lt;/code&gt; means simply that you must
        11223 retry the operation:  if you Control-Z a program to suspend it, and
        11224 then &lt;code&gt;fg&lt;/code&gt; to continue it again; and if the program was in the middle
        11225 of &lt;code&gt;open()&lt;/code&gt;ing a file, you would expect it to continue at that exact
        11226 point and to actually open the file.  Software that doesn't check for
        11227 &lt;code&gt;EINTR&lt;/code&gt; can fail in very subtle ways!&lt;/p&gt;
        11228 &lt;p&gt;Once you have an open file descriptor, you can read from it:&lt;/p&gt;
        11229 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;ssize_t&lt;/span&gt;
        11230 &lt;span class="nf"&gt;read_five_bytes&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        11231 &lt;span class="p"&gt;{&lt;/span&gt;
        11232     &lt;span class="kt"&gt;ssize_t&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        11233 
        11234     &lt;span class="nl"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        11235     &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        11236     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        11237         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EINTR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        11238             &lt;span class="k"&gt;goto&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        11239         &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        11240             &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* the caller should cherk errno */&lt;/span&gt;
        11241         &lt;span class="p"&gt;}&lt;/span&gt;
        11242     &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        11243         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* success */&lt;/span&gt;
        11244     &lt;span class="p"&gt;}&lt;/span&gt;
        11245 &lt;span class="p"&gt;}&lt;/span&gt;
        11246 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11247 
        11248 &lt;p&gt;... and one has to remember that if &lt;code&gt;read()&lt;/code&gt; returns 0, it means we
        11249 were at the end-of-file; if it returns less than the number of bytes
        11250 requested it means we were close to the end of file; if this is a
        11251 nonblocking socket and it returns &lt;code&gt;EWOULDBLOCK&lt;/code&gt; or &lt;code&gt;EAGAIN&lt;/code&gt; then one
        11252 must decide to retry the operation or actually wait and try again
        11253 later.&lt;/p&gt;
        11254 &lt;p&gt;There is a lot of buggy software written in C that tries to use the
        11255 POSIX API directly, and gets these subtleties wrong.  Most programs
        11256 written in high-level languages use the I/O facilities provided by
        11257 their language, which hopefully make things easier.&lt;/p&gt;
        11258 &lt;h1&gt;I/O in Rust&lt;/h1&gt;
        11259 &lt;p&gt;Rust makes &lt;a href="https://doc.rust-lang.org/book/first-edition/error-handling.html"&gt;error handling&lt;/a&gt; convenient and safe.  If you decide to
        11260 ignore an error, the code &lt;em&gt;looks&lt;/em&gt; like it is ignoring the error
        11261 (e.g. you can grep for &lt;code&gt;unwrap()&lt;/code&gt; and find lazy code).  The
        11262 code actually &lt;em&gt;looks better&lt;/em&gt; if it doesn't ignore the error and
        11263 properly propagates it upstream (e.g. you can use the &lt;code&gt;?&lt;/code&gt; shortcut to
        11264 propagate errors to the calling function).&lt;/p&gt;
        11265 &lt;p&gt;I keep recommending &lt;a href="http://joeduffyblog.com/2016/02/07/the-error-model/"&gt;this article on error models&lt;/a&gt; to people; it
        11266 discusses POSIX-like error codes vs. exceptions vs. more modern
        11267 approaches like Haskell's and Rust's - definitely worth studying over
        11268 a few of days (also, see Miguel's valiant effort to &lt;a href="https://github.com/migueldeicaza/NStack"&gt;move C# I/O away
        11269 from exceptions for I/O errors&lt;/a&gt;).&lt;/p&gt;
        11270 &lt;p&gt;So, what happens when one opens a file in Rust, from the toplevel API
        11271 down to the system calls?  Let's go down the rabbit hole.&lt;/p&gt;
        11272 &lt;p&gt;You can open a file like this:&lt;/p&gt;
        11273 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;::&lt;span class="n"&gt;fs&lt;/span&gt;::&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11274 
        11275 &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11276 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;::&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11277 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11278 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11279 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11280 
        11281 &lt;p&gt;This does &lt;em&gt;not&lt;/em&gt; give you a raw file descriptor; it gives you an
        11282 &lt;code&gt;io::Result&amp;lt;fs::File, io::Error&amp;gt;&lt;/code&gt;, which you must pick apart to see if
        11283 you actually got back a File that you can operate on, or an error.&lt;/p&gt;
        11284 &lt;p&gt;Let's look at the &lt;a href="https://github.com/rust-lang/rust/blob/3f8b93693da78c2cfe1d7f1dc6834c5ba61e0cc0/src/libstd/fs.rs#L235"&gt;implementation of &lt;code&gt;File::open()&lt;/code&gt; and &lt;code&gt;File::create()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
        11285 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11286 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;: &lt;span class="nb"&gt;AsRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;: &lt;span class="nc"&gt;P&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;io&lt;/span&gt;::&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11287 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;OpenOptions&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ref&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11288 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11289 
        11290 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;: &lt;span class="nb"&gt;AsRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;: &lt;span class="nc"&gt;P&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;io&lt;/span&gt;::&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11291 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;OpenOptions&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;truncate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ref&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11292 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11293 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11294 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11295 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11296 
        11297 &lt;p&gt;Here, &lt;code&gt;OpenOptions&lt;/code&gt; is an auxiliary struct that implements a "builder"
        11298 pattern.  Instead of passing bitflags for the various
        11299 &lt;code&gt;O_CREATE/O_APPEND/etc.&lt;/code&gt; flags from the &lt;code&gt;open(2)&lt;/code&gt; system call, one
        11300 builds a struct with the desired options, and finally calls &lt;code&gt;.open()&lt;/code&gt;
        11301 on it.&lt;/p&gt;
        11302 &lt;p&gt;So, let's look at the &lt;a href="https://github.com/rust-lang/rust/blob/3f8b93693da78c2cfe1d7f1dc6834c5ba61e0cc0/src/libstd/fs.rs#L670"&gt;implementation of &lt;code&gt;OpenOptions.open()&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
        11303 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;: &lt;span class="nb"&gt;AsRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;: &lt;span class="nc"&gt;P&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;io&lt;/span&gt;::&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11304 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ref&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11305 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11306 
        11307 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;_open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;io&lt;/span&gt;::&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11308 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fs_imp&lt;/span&gt;::&lt;span class="n"&gt;File&lt;/span&gt;::&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11309 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt;: &lt;span class="nc"&gt;inner&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11310 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11311 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11312 
        11313 &lt;p&gt;See that &lt;code&gt;fs_imp::File::open()&lt;/code&gt;?  That's what we want: it's the
        11314 platform-specific wrapper for opening files.  Let's look
        11315 at &lt;a href="https://github.com/rust-lang/rust/blob/3f8b93693da78c2cfe1d7f1dc6834c5ba61e0cc0/src/libstd/sys/unix/fs.rs#L422"&gt;its implementation for Unix&lt;/a&gt;:&lt;/p&gt;
        11316 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;OpenOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;io&lt;/span&gt;::&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11317 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cstr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11318 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;::&lt;span class="n"&gt;open_c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11319 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11320 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11321 
        11322 &lt;p&gt;The first line, &lt;code&gt;let path = cstr(path)?&lt;/code&gt; tries to convert a &lt;code&gt;Path&lt;/code&gt;
        11323 into a nul-terminated C string.  The second line calls the following:&lt;/p&gt;
        11324 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;open_c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;CStr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;OpenOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;io&lt;/span&gt;::&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11325 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc&lt;/span&gt;::&lt;span class="n"&gt;O_CLOEXEC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11326 &lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_access_mode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11327 &lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_creation_mode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11328 &lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;custom_flags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;libc&lt;/span&gt;::&lt;span class="n"&gt;O_ACCMODE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11329 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cvt_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11330 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;open64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ptr&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11331 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11332 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FileDesc&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11333 
        11334 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11335 
        11336 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11337 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11338 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11339 
        11340 &lt;p&gt;Here, &lt;code&gt;let flags = ...&lt;/code&gt; converts the &lt;code&gt;OpenOptions&lt;/code&gt; we had in the
        11341 beginning to an int with bit flags.&lt;/p&gt;
        11342 &lt;p&gt;Then, it does &lt;code&gt;let fd = cvt_r (LAMBDA)&lt;/code&gt;, and that lambda function
        11343 calls the actual &lt;code&gt;open64()&lt;/code&gt; from libc (a Rust wrapper for the system's
        11344 libc):  it returns a file descriptor, or -1 on error.  Why is this
        11345 done in a lambda?  Let's look at &lt;a href="https://github.com/rust-lang/rust/blob/3f8b93693da78c2cfe1d7f1dc6834c5ba61e0cc0/src/libstd/sys/unix/mod.rs#L155"&gt;&lt;code&gt;cvt_r()&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
        11346 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;cvt_r&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;: &lt;span class="nc"&gt;F&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;io&lt;/span&gt;::&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11347 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;: &lt;span class="nc"&gt;IsMinusOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11348 &lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;: &lt;span class="nb"&gt;FnMut&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11349 &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11350 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;loop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11351 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cvt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11352 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ErrorKind&lt;/span&gt;::&lt;span class="n"&gt;Interrupted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11353 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11354 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11355 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11356 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11357 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11358 
        11359 &lt;p&gt;Okay!  Here &lt;code&gt;f&lt;/code&gt; is the lambda that calls &lt;code&gt;open64()&lt;/code&gt;; &lt;code&gt;cvt_r()&lt;/code&gt; calls
        11360 it in a loop and translates the POSIX-like result into something
        11361 friendly to Rust.  This loop is where it handles &lt;code&gt;EINTR&lt;/code&gt;, which gets
        11362 translated into &lt;code&gt;ErrorKind::Interrupted&lt;/code&gt;.  I suppose &lt;code&gt;cvt_r()&lt;/code&gt; stands
        11363 for &lt;code&gt;convert_retry()&lt;/code&gt;?  Let's look at
        11364 the &lt;a href="https://github.com/rust-lang/rust/blob/3f8b93693da78c2cfe1d7f1dc6834c5ba61e0cc0/src/libstd/sys/unix/mod.rs#L147"&gt;implementation of &lt;code&gt;cvt()&lt;/code&gt;&lt;/a&gt;, which fetches the error code:&lt;/p&gt;
        11365 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;cvt&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;: &lt;span class="nc"&gt;IsMinusOne&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;: &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;io&lt;/span&gt;::&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11366 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_minus_one&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11367 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;::&lt;span class="n"&gt;Error&lt;/span&gt;::&lt;span class="n"&gt;last_os_error&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11368 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11369 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11370 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11371 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11372 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11373 
        11374 &lt;p&gt;(The &lt;code&gt;IsMinusOne&lt;/code&gt; shenanigans are just a Rust-ism to help convert
        11375 multiple integer types without a lot of &lt;code&gt;as&lt;/code&gt; casts.)&lt;/p&gt;
        11376 &lt;p&gt;The above means, if the POSIX-like result was -1, return an &lt;code&gt;Err()&lt;/code&gt; from
        11377 the last error returned by the operating system.  That should surely
        11378 be &lt;code&gt;errno&lt;/code&gt; internally, correct?  Let's look at
        11379 the &lt;a href="https://github.com/rust-lang/rust/blob/3f8b93693da78c2cfe1d7f1dc6834c5ba61e0cc0/src/libstd/io/error.rs#L268"&gt;implementation for &lt;code&gt;io::Error::last_os_error()&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
        11380 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;last_os_error&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11381 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;::&lt;span class="n"&gt;from_raw_os_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;::&lt;span class="n"&gt;os&lt;/span&gt;::&lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11382 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11383 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11384 
        11385 &lt;p&gt;We don't need to look at &lt;code&gt;Error::from_raw_os_error()&lt;/code&gt;; it's just a
        11386 conversion function from an &lt;code&gt;errno&lt;/code&gt; value into a Rust enum value.
        11387 However, let's look at &lt;a href="https://github.com/rust-lang/rust/blob/3f8b93693da78c2cfe1d7f1dc6834c5ba61e0cc0/src/libstd/sys/unix/os.rs#L60"&gt;&lt;code&gt;sys::os::errno()&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
        11388 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;errno&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="kt"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11389 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11390 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;errno_location&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11391 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11392 &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11393 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11394 
        11395 &lt;p&gt;Here, &lt;code&gt;errno_location()&lt;/code&gt; is an &lt;code&gt;extern&lt;/code&gt; function defined in GNU libc
        11396 (or whatever C library your Unix uses).  It returns a pointer to the
        11397 actual int which is the &lt;code&gt;errno&lt;/code&gt; thread-local variable.  Since non-C
        11398 code can't use libc's global variables directly, there needs to be a
        11399 way to get their addresses via function calls - that's what
        11400 &lt;code&gt;errno_location()&lt;/code&gt; is for.&lt;/p&gt;
        11401 &lt;h2&gt;And on Windows?&lt;/h2&gt;
        11402 &lt;p&gt;Remember the internal &lt;code&gt;File.open()&lt;/code&gt;?  This is what it looks
        11403 like &lt;a href="https://github.com/rust-lang/rust/blob/3f8b93693da78c2cfe1d7f1dc6834c5ba61e0cc0/src/libstd/sys/windows/fs.rs#L257"&gt;on Windows&lt;/a&gt;:&lt;/p&gt;
        11404 &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;OpenOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;io&lt;/span&gt;::&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11405 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to_u16s&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11406 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11407 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;::&lt;span class="n"&gt;CreateFileW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ptr&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11408 &lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_access_mode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11409 &lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;share_mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11410 &lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;security_attributes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11411 &lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_creation_mode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11412 &lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_flags_and_attributes&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11413 &lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;::&lt;span class="n"&gt;null_mut&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11414 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11415 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;::&lt;span class="n"&gt;INVALID_HANDLE_VALUE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11416 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;::&lt;span class="n"&gt;last_os_error&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11417 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11418 &lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;: &lt;span class="nc"&gt;Handle&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11419 &lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11420 &lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
        11421 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        11422 
        11423 &lt;p&gt;&lt;code&gt;CreateFileW()&lt;/code&gt; is the Windows API function to open files.  The
        11424 conversion of error codes inside &lt;code&gt;Error::last_os_error()&lt;/code&gt; happens
        11425 analogously - it calls &lt;code&gt;GetLastError()&lt;/code&gt; from the Windows API and
        11426 converts it.&lt;/p&gt;
        11427 &lt;h2&gt;Can we not call C libraries?&lt;/h2&gt;
        11428 &lt;p&gt;The Rust/Unix code above depends on the system's libc for &lt;code&gt;open()&lt;/code&gt; and
        11429 &lt;code&gt;errno&lt;/code&gt;, which are entirely C constructs.  Libc is what actually does
        11430 the system calls.  There are efforts to make the Rust standard library
        11431 &lt;em&gt;not&lt;/em&gt; use libc and use syscalls directly.&lt;/p&gt;
        11432 &lt;p&gt;As an example, you can look at
        11433 the &lt;a href="https://github.com/rust-lang/rust/blob/3f8b93693da78c2cfe1d7f1dc6834c5ba61e0cc0/src/libstd/sys/redox/syscall/call.rs"&gt;Rust standard library for Redox&lt;/a&gt;.  Redox is a new operating
        11434 system kernel entirely written in Rust.  Fun times!&lt;/p&gt;
        11435 &lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; If you want to see what a C-less libstd would look
        11436 like, &lt;a href="https://github.com/japaric/steed"&gt;take a look at steed&lt;/a&gt;, an effort to reimplement Rust's libstd
        11437 without C dependencies.&lt;/p&gt;
        11438 &lt;h1&gt;Conclusion&lt;/h1&gt;
        11439 &lt;p&gt;Rust is very meticulous about error handling, but it succeeds in
        11440 making it pleasant to read.  I/O functions give you back an
        11441 &lt;code&gt;io::Result&amp;lt;&amp;gt;&lt;/code&gt;, which you piece apart to see if it succeeded or got an
        11442 error.&lt;/p&gt;
        11443 &lt;p&gt;Internally, and for each platform it supports, the Rust standard
        11444 library translates &lt;code&gt;errno&lt;/code&gt; from libc into an &lt;code&gt;io::ErrorKind&lt;/code&gt; Rust
        11445 enum.  The standard library also automatically handles Unix-isms like
        11446 retrying operations on &lt;code&gt;EINTR&lt;/code&gt;.&lt;/p&gt;
        11447 &lt;p&gt;I've been enjoying reading the &lt;a href="https://github.com/rust-lang/rust/tree/master/src/libstd"&gt;Rust standard library code&lt;/a&gt;:  it
        11448 has taught me many Rust-isms, and it's nice to see how the
        11449 hairy/historical libc constructs are translated into clean Rust
        11450 idioms.  I hope this little trip down the rabbit hole for the
        11451 &lt;code&gt;open(2)&lt;/code&gt; system call lets you look in other interesting places, too.&lt;/p&gt;</content><category term="misc"></category><category term="rust"></category></entry><entry><title>Moving to a new blog engine</title><link href="https://people.gnome.org/~federico/blog/new-blog.html" rel="alternate"></link><published>2017-06-09T09:08:15-05:00</published><updated>2017-06-09T09:13:41-05:00</updated><author><name>Federico Mena Quintero</name></author><id>tag:people.gnome.org,2017-06-09:/~federico/blog/new-blog.html</id><summary type="html">&lt;p&gt;In 2003 I wrote
        11452 an
        11453 &lt;a href="https://people.gnome.org/~federico/misc/activity-log.el"&gt;Emacs script to write my blog and produce an RSS feed&lt;/a&gt;.
        11454 Back then, I seemed to write multiple short blog entries in a day
        11455 rather than longer articles (&lt;em&gt;doing Mastodon before it was cool?&lt;/em&gt;).
        11456 But my blogging patterns have changed.  I've been wanting to add …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In 2003 I wrote
        11457 an
        11458 &lt;a href="https://people.gnome.org/~federico/misc/activity-log.el"&gt;Emacs script to write my blog and produce an RSS feed&lt;/a&gt;.
        11459 Back then, I seemed to write multiple short blog entries in a day
        11460 rather than longer articles (&lt;em&gt;doing Mastodon before it was cool?&lt;/em&gt;).
        11461 But my blogging patterns have changed.  I've been wanting to add some
        11462 more features to the script:  moving to a page-per-post model, support
        11463 for draft articles, tags, and syntax highlighting for code excerpts...&lt;/p&gt;
        11464 &lt;p&gt;This is a wheel that I do not find worth reinventing these days.
        11465 After &lt;a href="https://mastodon.social/@federicomena/8360985"&gt;asking on Mastodon&lt;/a&gt; about static site
        11466 generators (thanks to everyone who replied!), I've decided to give
        11467 &lt;a href="https://blog.getpelican.com/"&gt;Pelican&lt;/a&gt; a try.  I've reached the age where "obvious, beautiful
        11468 documentation" is high on my list of things to look for when shopping
        11469 for tools, and Pelican's docs are nice from the start.&lt;/p&gt;
        11470 &lt;p&gt;The old blog is still available &lt;a href="https://people.gnome.org/~federico/news.html"&gt;in the old location&lt;/a&gt;.&lt;/p&gt;
        11471 &lt;p&gt;If you find broken links, or stuff that doesn't work correctly here,
        11472