<rss version="2.0">
  <channel>
    <title>fnordig - posts tagged with 'rust'</title>
    <link>https://fnordig.de</link>
    <description>fnordig - post tagged with 'rust'</description>
    <item>
      <title>Build your project Zig-style</title>
      <link>https://fnordig.de/2026/06/16/build-your-project-zig-style</link>
      <description>&lt;p&gt;Over the past few nights I&#39;ve been tinkering with the &lt;a href=&quot;https://ziglang.org/&quot;&gt;Zig&lt;/a&gt; build system,
after it got &lt;a href=&quot;https://ziglang.org/devlog/2026/?20260213#2026-05-26&quot;&gt;a bit of a rework lately&lt;/a&gt;.
I had a plan:
Learn a bit more about Zig,
learn a bit more about the Zig build system
and get a deeper understanding of what &lt;a href=&quot;https://doc.rust-lang.org/cargo/&quot;&gt;Cargo&lt;/a&gt; does to build a Rust project.&lt;/p&gt;
&lt;div class=&quot;aside-group&quot;&gt;
&lt;p&gt;Building Rust projects with something that is not Rust is something &lt;a href=&quot;https://fnordig.de/2020/06/19/build-your-project/&quot;&gt;I have experience with&lt;/a&gt;.
With Zig I tinkered around a bit before and I&#39;m keeping an eye on its development.
The Zig build system was completely new to me.&lt;/p&gt;
&lt;aside&gt;
I wrote an implementation of &lt;a href=&quot;https://wiki.xxiivv.com/site/uxn.html&quot;&gt;Uxn&lt;/a&gt; in Zig
(it&#39;s not published).
&lt;/aside&gt;&lt;/div&gt;
&lt;p&gt;So just like that I present: &lt;a href=&quot;https://git.fnordig.de/jer/bygge-zig&quot;&gt;bygge-zig&lt;/a&gt;.&lt;br /&gt;
It builds Rust code:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;src/mozilla/glean$ ls -l Cargo.toml
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;-rw-r--r-- 1 jer staff 616 Jun 15 16:10 Cargo.toml
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;src/mozilla/glean$ zig build --summary line
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Build Summary: 194/194 steps succeeded
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;src/mozilla/glean$ du -sh .zig-cache
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;952M    .zig-cache
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;src/mozilla/glean$ tree zig-out
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;zig-out
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;├── bin
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│   └── uniffi-bindgen
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;└── lib
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    ├── glean
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    ├── glean_core
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    └── uniffi_bindgen
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a build of the &lt;a href=&quot;https://github.com/mozilla/glean&quot;&gt;Glean SDK&lt;/a&gt;, my main project at work.&lt;/p&gt;
&lt;p&gt;In 374 lines of Zig (and 79 lines of Ruby) I replicated what Cargo does in 80.000 lines of Rust.
That includes building Rust code, building proc-macros and building and running build scripts (those &lt;code&gt;build.rs&lt;/code&gt; files in the top-level directory of some crates).&lt;br /&gt;
Of course that is an oversimplification.
Turns out a complete Rust build system is really tricky.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bygge-zig&lt;/code&gt; does nothing about resolving and fetching dependencies.
It does not figure out what depends on what.
It does not decide which features should be active.
It translates what the build should look like into something the Zig build system can handle.&lt;/p&gt;
&lt;p&gt;At one point Cargo had &lt;a href=&quot;https://doc.rust-lang.org/cargo/reference/unstable.html#build-plan&quot;&gt;build plans&lt;/a&gt;,
which allowed to gather information about how to run the build, mostly.
That was removed and now there is a new way to get most of that information: &lt;a href=&quot;https://doc.rust-lang.org/cargo/reference/unstable.html#unit-graph&quot;&gt;the unit graph&lt;/a&gt; (on Rust Nightly):&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ cargo +nightly build -Z unstable-options --unit-graph | jq .
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &amp;quot;version&amp;quot;: 1,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &amp;quot;units&amp;quot;: [
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &amp;quot;pkg_id&amp;quot;: &amp;quot;path+file:///home/jer/src/bygge-zig/crates/hello-world#0.1.0&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &amp;quot;target&amp;quot;: {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;kind&amp;quot;: [
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;          &amp;quot;bin&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        ],
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;crate_types&amp;quot;: [
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;          &amp;quot;bin&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        ],
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;name&amp;quot;: &amp;quot;hello-world&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;src_path&amp;quot;: &amp;quot;/home/jer/src/bygge-zig/crates/hello-world/src/main.rs&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;edition&amp;quot;: &amp;quot;2024&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;doc&amp;quot;: true,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;doctest&amp;quot;: false,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;test&amp;quot;: true
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &amp;quot;profile&amp;quot;: {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;name&amp;quot;: &amp;quot;dev&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;opt_level&amp;quot;: &amp;quot;0&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;lto&amp;quot;: &amp;quot;false&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;codegen_backend&amp;quot;: null,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;codegen_units&amp;quot;: null,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;debuginfo&amp;quot;: 2,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;split_debuginfo&amp;quot;: &amp;quot;unpacked&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;debug_assertions&amp;quot;: true,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;overflow_checks&amp;quot;: true,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;rpath&amp;quot;: false,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;incremental&amp;quot;: true,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;panic&amp;quot;: &amp;quot;unwind&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &amp;quot;strip&amp;quot;: {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;          &amp;quot;deferred&amp;quot;: &amp;quot;None&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &amp;quot;platform&amp;quot;: null,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &amp;quot;mode&amp;quot;: &amp;quot;build&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &amp;quot;features&amp;quot;: [],
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &amp;quot;dependencies&amp;quot;: [
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;          &amp;quot;index&amp;quot;: 1,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;          &amp;quot;extern_crate_name&amp;quot;: &amp;quot;world&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;          &amp;quot;public&amp;quot;: false,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;          &amp;quot;noprelude&amp;quot;: false,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;          &amp;quot;nounused&amp;quot;: false
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      ]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;lt;snip&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This emits the units of work that Cargo will execute for the build.
It still requires a lot more effort to turn that into something actually executable.
For example the generated shell command for the first unit in the example graph is this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;CARGO_CRATE_NAME=hello_world \
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;CARGO_PKG_NAME=hello-world \
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;CARGO_PKG_VERSION=1.0.0 \
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;lt;snip&amp;gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;rustc /home/jer/src/bygge-zig/crates/hello-world/src/main.rs \
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  --edition 2024 \
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  --extern world=target/debug/deps/libworld.rlib \
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  -L target/debug/deps
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This assumes the &lt;code&gt;world&lt;/code&gt; library is already built and placed in the &lt;code&gt;target/debug/deps/&lt;/code&gt; directory.
There&#39;s many more &lt;a href=&quot;https://doc.rust-lang.org/cargo/reference/environment-variables.html&quot;&gt;more environment variables&lt;/a&gt; that are set for a build.&lt;/p&gt;
&lt;p&gt;The Glean SDK (and the expanded sample project) does make use of both proc-macros and build scripts across its dependencies.
The way they need to be built differs from library code.
proc-macros are built into dynamic libraries and loaded by the Rust compiler at compile time.
&lt;a href=&quot;https://doc.rust-lang.org/cargo/reference/build-scripts.html&quot;&gt;Build scripts&lt;/a&gt; are &lt;em&gt;always&lt;/em&gt; built for the host target and run before the crate&#39;s code gets compiled.
Build scripts print out additional configuration to stdout,
which is parsed by Cargo and injected into the rest of the build.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ RUSTC=rustc OUT_DIR=.zig-cache/tmp .zig-cache/o/98128f/rust/build_script_build
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo::rustc-check-cfg=cfg(build_ran)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo::rustc-cfg=build_ran
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ cat .zig-cache/tmp/code.rs
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;pub const NAME: &amp;amp;&amp;#39;static str = &amp;quot;builder&amp;quot;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will result in the parameter &lt;code&gt;--cfg=build_ran&lt;/code&gt; being appended to the &lt;code&gt;rustc&lt;/code&gt; invocation for &lt;code&gt;hello-world/src/lib.rs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Not every environment variable is read by every project.
Not every &lt;code&gt;build.rs&lt;/code&gt; output line is needed for every build.
To build the Glean SDK I&#39;m getting away with the bare minimum.
Nonetheless &lt;code&gt;bygge-zig&lt;/code&gt; is able to drive quite a complicated build.
And it does that on both macOS and Linux just fine.&lt;/p&gt;
&lt;h2&gt;What I learned about Zig&lt;/h2&gt;
&lt;p&gt;In this project I didn&#39;t really use much of what makes Zig Zig.
No &lt;code&gt;comptime&lt;/code&gt;, no error handling, no arena allocators.
It is definitely an improvement over writing similar code in C, with a larger standard library and some generic data types to use.
Some of the more Zig things I barely scratched.
String handling requires an allocator, so it needs to be passed around, it&#39;s embedded in the &lt;code&gt;std.Build&lt;/code&gt; structure available in a &lt;code&gt;build.zig&lt;/code&gt;.
Built-in deserialization works by using comptime magic behind the scenes.
JSON parsing makes use of that (but comes with terrible error messages).&lt;/p&gt;
&lt;p&gt;I really got used to Rust&#39;s ownership system, where I don&#39;t have to think about who&#39;s responsible for freeing some data.
Zig doesn&#39;t have that.
Sometimes you pass things by value, other times by reference.
But in the latter case are you now responsible to free it?
That&#39;s communicated by documentation, not by types.
In &lt;code&gt;bygge-zig&lt;/code&gt; I simply do not deallocate.
It&#39;s a short-running process, so all memory is gone by the end of it anyway.&lt;/p&gt;
&lt;p&gt;Zig wants all code to be warning-free.
And so do I — when the code is done.
Unused variables however are a part of development
and I would prefer if the build still runs through in that case.
Different philosophy.
At the same time Zig is lazy and unused bits of the code, like functions that never get called, don&#39;t even get looked at and don&#39;t trigger compile errors.&lt;/p&gt;
&lt;p&gt;The biggest plus though is: Compiling Zig code is fast.&lt;/p&gt;
&lt;h2&gt;What I learned about the Zig build system&lt;/h2&gt;
&lt;p&gt;It&#39;s badly documented, if at all.&lt;br /&gt;
The &lt;a href=&quot;https://ziglang.org/learn/build-system/&quot;&gt;Zig Build System&lt;/a&gt; article tells you a bit of how to use it for your Zig project and maybe some dependencies.
The &lt;a href=&quot;https://ziglang.org/documentation/master/std/#std.Build&quot;&gt;&lt;code&gt;std.Build&lt;/code&gt; page&lt;/a&gt; has a bit of API documentation,
but no usage examples.
Some parts don&#39;t even get API documentation and so you have to guess from the name how it&#39;s intended to be used.
Because of the &lt;a href=&quot;https://ziglang.org/devlog/2026/?20260213#2026-05-26&quot;&gt;recent build system&lt;/a&gt; changes a lot of the existing usage doesn&#39;t apply anymore.
After the recent big changes to the build system it&#39;s also &lt;a href=&quot;https://codeberg.org/ziglang/zig/pulls/35428#user-content-followup-issues&quot;&gt;incomplete&lt;/a&gt;.
Some sharp edges are expected.&lt;/p&gt;
&lt;p&gt;My current use of the Zig build system in &lt;code&gt;bygge-zig&lt;/code&gt; is inefficient, guaranteed to be wrong and very very hacky.
After all I&#39;m not using it for what it&#39;s mainly build for (building Zig projects).
But I got it to work.&lt;/p&gt;
&lt;p&gt;I still don&#39;t know how the caching system is supposed to work.
Right now &lt;code&gt;bygge-zig&lt;/code&gt; rebuilds far too much stuff.
Every run of &lt;code&gt;zig build&lt;/code&gt; grows &lt;code&gt;.zig-cache&lt;/code&gt; by some 200 MB.
This makes &lt;code&gt;bygge-zig&lt;/code&gt; far worse than Cargo.
There&#39;s still more to learn about this.&lt;/p&gt;
&lt;h2&gt;What I learned about the Cargo build&lt;/h2&gt;
&lt;p&gt;It&#39;s hella complicated.
I learned some of what it does with &lt;a href=&quot;https://fnordig.de/2020/06/19/build-your-project/&quot;&gt;bygge&lt;/a&gt; back then, but I cheated on some things and hardcoded a lot of options.
Cargo does so much behind the scenes and getting that replicated in an outside tool is hard.
Every crate in your dependency tree relies on a different Cargo feature.
Implementing a replacement is thus a lot of trial and error until you get it right.
There&#39;s a lot of legacy ways to do things and Cargo supports them all.
On top of that &lt;code&gt;rustc&lt;/code&gt; does a lot of things by itself as well.
&lt;code&gt;rustc&lt;/code&gt; knows how to traverse the module tree of a crate if you give it the top-level file.
Built Rust libraries are identified by their metadata and metadata gets placed into &lt;code&gt;.rmeta&lt;/code&gt; files.
Metadata (and filenames in case of Cargo) contain hashes of all the input, including the compiler version and other external bits of information.
&lt;code&gt;rustc&lt;/code&gt; refuses to use built libraries if the metadata of the library and its transitive dependencies is wrong or missing.
Sometimes the error message doesn&#39;t tell you that.&lt;/p&gt;
&lt;p&gt;I feel like I now understand 20% of the build process.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2026/06/16/build-your-project-zig-style</guid>
      <pubDate>Tue, 16 Jun 2026 11:00:00 +0200</pubDate>
    </item>
    <item>
      <title>makerust</title>
      <link>https://fnordig.de/2026/04/23/makerust</link>
      <description>&lt;div class=&quot;aside-group&quot;&gt;
&lt;p&gt;In 2023 I learned about (GNU) make&#39;s &lt;a href=&quot;https://www.gnu.org/software/make/manual/html_node/One-Shell.html&quot;&gt;&lt;code&gt;.ONESHELL&lt;/code&gt;&lt;/a&gt;.
Put this in your Makefile:&lt;/p&gt;
&lt;aside&gt;
ref. &lt;a href=&quot;https://hachyderm.io/@jer/110255986490429550&quot;&gt;https://hachyderm.io/@jer/110255986490429550&lt;/a&gt;
&lt;/aside&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;SHELL &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;python3
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;.ONESHELL&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;date
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;date&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;	from datetime import datetime
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;	print(datetime.now())
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;aside-group&quot;&gt;
&lt;p&gt;and &lt;code&gt;make date&lt;/code&gt; works.&lt;/p&gt;
&lt;aside&gt;
ref. &lt;a href=&quot;https://hachyderm.io/@jer/110255991586765653&quot;&gt;https://hachyderm.io/@jer/110255991586765653&lt;/a&gt;
&lt;/aside&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;; make date
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;from datetime import datetime
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;print(datetime.now())
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;2026-04-23 12:32:27.193732
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;aside-group&quot;&gt;
&lt;p&gt;So for obvious reasons I put together an example so you can write Rust in your Makefile:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.SHELLFLAGS &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;-c &amp;#39;echo &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;$$&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;1 &amp;gt; tmp.rs &amp;amp;&amp;amp; rustc tmp.rs -o out.bin &amp;amp;&amp;amp; ./out.bin&amp;#39; --
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;.ONESHELL&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;all
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;all&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;	&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;fn main() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;		println!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;hello make!&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;	}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;; make all
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;hello make!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;aside&gt;
ref. &lt;a href=&quot;https://hachyderm.io/@jer/110256028629066227&quot;&gt;https://hachyderm.io/@jer/110256028629066227&lt;/a&gt;
&lt;/aside&gt;&lt;/div&gt;&lt;div class=&quot;aside-group&quot;&gt;
&lt;p&gt;But what if you want to add dependencies?
That made me write &lt;a href=&quot;https://git.fnordig.de/jer/makerust&quot;&gt;makerust&lt;/a&gt;.
I never wrote it up as a blog post, so here it is,
now that I updated it to use cargo script (needs Rust nightly, ).&lt;/p&gt;
&lt;aside&gt;
Needs Rust Nightly. See &lt;a href=&quot;https://github.com/rust-lang/cargo/issues/12207&quot;&gt;Rust tracking PR #12207&lt;/a&gt;.
A version of makerust that runs on stable Rust is available &lt;a href=&quot;https://git.fnordig.de/jer/makerust/src/commit/a01137edd014e42b13fc02d4cf64b523e46a29c9&quot;&gt;in an earlier commit&lt;/a&gt;.
&lt;/aside&gt;&lt;/div&gt;
&lt;p&gt;So now you can write:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;include &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;makerust.mk
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;info&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;dep.xshell dep.anyhow
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;	&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;@
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;	use anyhow::Result&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;	use xshell::{cmd, Shell}&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;	
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;	fn main() -&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;		&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; sh &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; Shell&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;new()&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;		&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; branch &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;main&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;		&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; commit_hash &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; cmd&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(sh, &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;git rev-parse {branch}&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;).read()&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;		println!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;makerust running on commit {commit_hash}&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;		Ok(())
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;	}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then it works:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;; make info
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;makerust running on commit 438da52bae8e0afbcb46d19852cb0def6f21d619
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Why?&lt;/h2&gt;
&lt;p&gt;make is good. Rust is good. In combination it can only get better.&lt;/p&gt;
&lt;h2&gt;But really ... why?&lt;/h2&gt;
&lt;p&gt;We don&#39;t ask this question around here.&lt;/p&gt;
&lt;h2&gt;Should I really?&lt;/h2&gt;
&lt;p&gt;Check with your team first, but I can&#39;t see a reason why not.&lt;/p&gt;
&lt;h2&gt;This is a joke, right?&lt;/h2&gt;
&lt;p&gt;I don&#39;t make jokes on the internet.&lt;/p&gt;
&lt;hr /&gt;
&lt;div class=&quot;aside-group&quot;&gt;
&lt;p&gt;THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, BUT ALSO I TAKE FULL RESPONSIBILITY FOR
THIS UNUTTERABLE HORROR AND YOU SHALL RECITE MY NAME FOR FOREVER ALONGSIDE IT.&lt;/p&gt;
&lt;aside&gt;
ref. &lt;a href=&quot;https://hachyderm.io/@thejpster/110258912875118911&quot;&gt;https://hachyderm.io/@thejpster/110258912875118911&lt;/a&gt;
&lt;/aside&gt;&lt;/div&gt;</description>
      <guid>https://fnordig.de/2026/04/23/makerust</guid>
      <pubDate>Thu, 23 Apr 2026 12:29:00 -0400</pubDate>
    </item>
    <item>
      <title>Rust reflection and a multi-array list</title>
      <link>https://fnordig.de/2026/03/25/rust-reflection-and-a-multi-array-list</link>
      <description>&lt;p&gt;Rust is experimenting with compile-time reflection in the form of &lt;code&gt;type_info&lt;/code&gt; (&lt;a href=&quot;https://github.com/rust-lang/rust/issues/146922&quot;&gt;Tracking issue #146922&lt;/a&gt;).
It&#39;s far from finished, but &lt;del&gt;the other day&lt;/del&gt; more than a month ago&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; the pull request for &lt;a href=&quot;https://github.com/rust-lang/rust/pull/151142&quot;&gt;Support ADT types in type info reflection&lt;/a&gt; landed.
With that PR the types expose enough information about structs to be useful to play around with.&lt;/p&gt;
&lt;p&gt;This is what the type info looks like for some types:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u32
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Type {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    kind: Int(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        Int {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            bits: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            signed: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    ),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    size: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Some&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    ),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;bool
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Type {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    kind: Bool(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        Bool,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    ),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    size: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Some&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    ),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;struct &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Foo {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    a: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Type {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    kind: Struct(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        Struct {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            generics: [],
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            fields: [
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                Field {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                    name: &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                    ty: TypeId(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0x1378bb1c0a0202683eb65e7c11f2e4d7&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                    offset: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            ],
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            non_exhaustive: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    ),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    size: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Some&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    ),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://play.rust-lang.org/?version=nightly&amp;amp;mode=debug&amp;amp;edition=2024&amp;amp;gist=f76ce09397c531bc57c302113c3b3d05&quot;&gt;This code snippet shows the structure of several more types&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The full type information is available at compile-time, so in &lt;code&gt;const fn&lt;/code&gt; and &lt;code&gt;const {  }&lt;/code&gt; blocks.
The const functions need to be called in a const context though.
&lt;a href=&quot;https://doc.rust-lang.org/nightly/std/any/struct.TypeId.html#method.info&quot;&gt;&lt;code&gt;TypeId::info&lt;/code&gt;&lt;/a&gt; panics if called at runtime.&lt;/p&gt;
&lt;p&gt;Whereas currently anything that wants to act on the shape of types usually works as a proc-macro,
the new reflection allows const code to do it without external crates nor external types to cooperate, e.g. by also annotating types using the proc-macro.&lt;/p&gt;
&lt;h2&gt;Building a multi-array list&lt;/h2&gt;
&lt;p&gt;Inspired by Zig&#39;s &lt;a href=&quot;https://ziglang.org/documentation/master/std/#std.MultiArrayList&quot;&gt;&lt;code&gt;MultiArrayList&lt;/code&gt;&lt;/a&gt; I set out to implement a similar type in Rust.&lt;/p&gt;
&lt;p&gt;To understand what a multi-array list even is I&#39;ll cite the Zig documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A &lt;code&gt;MultiArrayList&lt;/code&gt; stores a list of a struct or tagged union type.
Instead of storing a single list of items, &lt;code&gt;MultiArrayList&lt;/code&gt; stores separate lists for each field of the struct or lists of tags and bare unions.
This allows for memory savings if the struct or union has padding,
and also improves cache usage if only some fields or just tags are needed for a computation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To translate that into Rust code, imagine we have a struct like this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;struct &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Point {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    x: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;i32&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    y: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;i32&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we create a list of points:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; list &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Vec&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;::new();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;list.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(Point { x: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;47&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, y: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;23 &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;});
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;list.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(Point { x: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, y: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;5 &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;});
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In memory this will be laid out roughly like:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;┌─ list ───────────────────────┐
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│    2 │    4 │ 0x5c2c3ef8cae0 │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;└───────────────│──────────────┘
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                └─┌─ 0x5c2c3ef8cae0 ──────────┐
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                  │   47 │   23 │    0 │    5 │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                  └───────────────────────────┘
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The vector holds the length (&lt;code&gt;2&lt;/code&gt;), the capacity (&lt;code&gt;4&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;) and a pointer to the actual data allocated on the heap.
On the heap all values are laid out flat one after the other.
To Rust it&#39;s known that the &lt;code&gt;Point&lt;/code&gt; struct consists of 2 integers, of which it knows the size (32 bit = 4 bytes), and thus a &lt;code&gt;Point&lt;/code&gt; is 8 bytes.
Thus we can expect a new &lt;code&gt;Point&lt;/code&gt; every 8 bytes&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;For a multi-array list we turn it into this construct instead:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;┌─ list ────────────────────────┐
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│  0x6000028bc010 │    2 │    2 │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;└──│────────────────────────────┘
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;   │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;   └─┌─ 0x6000028bc010 ────────────────┐
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;     │ 0x6000028bc020 │ 0x6000028bc030 │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;     └──│───────────────│──────────────┘
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        │               └───────┐
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        └─┌─ 0x6000028bc020 ─┐  └─┌─ 0x6000028bc030 ─┐
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;          │   47 │    0      │    │   23 │    5      │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;          └──────────────────┘    └──────────────────┘
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our &lt;code&gt;list&lt;/code&gt; has a pointer to a list of pointers (&lt;code&gt;0x6000028bc010&lt;/code&gt;), a length (&lt;code&gt;2&lt;/code&gt;) and a capacity (also &lt;code&gt;2&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;).
The pointers in that list of pointers point to more lists.
Each of these lists contain the values of just one of the fields of &lt;code&gt;Point&lt;/code&gt;.
Or in Rust code&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;struct &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;MultiArrayList {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    elems: *&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;mut u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    cap: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    len: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This ends up being usable in Rust thanks to reflection&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-6-1&quot;&gt;&lt;a href=&quot;#fn-6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; points &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;MultiArrayList::&amp;lt;Point&amp;gt;::new();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; point &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; Point { x: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;47&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, y: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;23 &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;};
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;points.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(point);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; point: Box&amp;lt;Point&amp;gt; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; points.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;pop&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unrwap&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It allows to efficiently iterate over just one of the fields:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; points.items::&amp;lt;&lt;/span&gt;&lt;span style=&quot;background-color:#f5f5f5;font-weight:bold;color:#b52a1d;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;, i32&amp;gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;    dbg!(x);
&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or iterate over the whole list and grab the pieces as we need them:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; point &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; points.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;iter&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; point.get::&amp;lt;&lt;/span&gt;&lt;span style=&quot;background-color:#f5f5f5;font-weight:bold;color:#b52a1d;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;, i32&amp;gt;();
&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;  let y = point.get::&amp;lt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;, i32&amp;gt;();
&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;  dbg!(x, y);
&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now this example doesn&#39;t actually show any of the advantages a multi-array list might have.
There&#39;s no padding we could save.&lt;/p&gt;
&lt;p&gt;But I can prove that it does save reduce memory allocation that with the right &lt;del&gt;toppings&lt;/del&gt; types:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;; cargo run -q --example comparison
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Allocating 500 pizzas.
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Vec allocated:  16000 bytes
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;List allocated: 14016 bytes (-12.40%)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The code is available online: &lt;a href=&quot;https://git.fnordig.de/jer/multi-array-list&quot;&gt;https://git.fnordig.de/jer/multi-array-list&lt;/a&gt;.&lt;br /&gt;
You can also grab it from crates.io:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo add multi-array-list
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note though that it&#39;s nightly-only, uses several experimental features&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-7-1&quot;&gt;&lt;a href=&quot;#fn-7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;.
It is tested and Miri doesn&#39;t complain (yet), but I give absolutely no guarantees about it.
I think it might be easy to misuse this to transmute data without resorting to &lt;code&gt;unsafe&lt;/code&gt; and there be dragons.
I do not plan to actively maintain it, but maybe I use this as a playground to explore reflection a bit more.&lt;/p&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;I wrote the code shortly after the pull request landed and started the blog post the same day, but only finished it last night.&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Rust allocates a bit more up front to avoid many small allocations when it expects to grow later anyway. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;I&#39;m hand-waving things here a little bit. In theory Rust could choose a different layout here and swap around &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; in memory. &lt;a href=&quot;#fr-3-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;I did not implement over-allocation in my code. &lt;a href=&quot;#fr-4-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;Hand-waving even more and skipping the generic part here. &lt;a href=&quot;#fr-5-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-6&quot;&gt;
&lt;p&gt;Initially I wrote &quot;safe Rust&quot;, but the API currently exposed is unsafe to use. I should mark this &lt;code&gt;unsafe&lt;/code&gt;. &lt;a href=&quot;#fr-6-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-7&quot;&gt;
&lt;p&gt;Notably &lt;a href=&quot;https://doc.rust-lang.org/beta/unstable-book/language-features/adt-const-params.html&quot;&gt;adt_const_params&lt;/a&gt;, which gives me the wonderful possibility of using &lt;code&gt;&quot;x&quot;&lt;/code&gt; in the &lt;code&gt;items&lt;/code&gt; API, but breaks my blog&#39;s code highlighting. &lt;a href=&quot;#fr-7-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2026/03/25/rust-reflection-and-a-multi-array-list</guid>
      <pubDate>Wed, 25 Mar 2026 11:00:00 +0100</pubDate>
    </item>
    <item>
      <title>oelf - Mach-O support for sqlelf</title>
      <link>https://fnordig.de/2024/01/02/oelf</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://fzakaria.com/2023/03/19/sqlelf-and-20-years-of-nix.html&quot;&gt;sqlelf&lt;/a&gt; lets you explore ELF objects through the power of SQL.
It turns any executable into a queryable database.
Any? No, just those in ELF format, the standard binary file format on most Unix and Linux systems.
But not on macOS.
macOS relies on the Mach object file format, short Mach-O and sqlelf doesn&#39;t support that.
The library it uses for parsing in theory does, but that failed on my machine.
It depends on a heavy C++ library and I didn&#39;t want to bother figuring out how to build and change that.&lt;/p&gt;
&lt;p&gt;I still wanted &lt;a href=&quot;https://github.com/badboy/sqlelf/tree/with-macho-support&quot;&gt;sqlelf for mach-o binaries&lt;/a&gt;.
Luckily the hardest part was settled early on: &lt;a href=&quot;https://hachyderm.io/@fnordfish@mastodon.social/111476474716125707&quot;&gt;naming&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;lt;@fnordfish@mastodon.social&amp;gt;
@jer sollte auf jeden Fall „Ölf“ heißen!&lt;br /&gt;
(&lt;em&gt;translation:&lt;/em&gt; it should definitely be called „Ölf“)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So &lt;a href=&quot;https://pypi.org/project/oelf/&quot;&gt;oelf&lt;/a&gt; exists now.
The &lt;a href=&quot;https://github.com/badboy/oelf&quot;&gt;source code is on GitHub&lt;/a&gt;
and &lt;a href=&quot;https://github.com/badboy/sqlelf/tree/with-macho-support&quot;&gt;my fork of sqlelf adds it to sqlelf&lt;/a&gt; for easy use.&lt;/p&gt;
&lt;h3&gt;Install&lt;/h3&gt;
&lt;p&gt;I have released pre-built versions of oelf,
but nothing is upstreamed to sqlelf yet.
You can install it from git:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;pip install git+https://github.com/badboy/sqlelf@with-macho-support#egg=sqlelf
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On my M1 MacBook sqlelf doesn&#39;t work out of the box.
sqlelf depends on &lt;a href=&quot;https://www.capstone-engine.org/&quot;&gt;Capstone&lt;/a&gt;
and the installed library coming with the Python wrapper is &lt;code&gt;x86_64&lt;/code&gt; only,
so it won&#39;t load&lt;/p&gt;
&lt;p&gt;That&#39;s fixable.
Assuming you installed into a Python venv &lt;code&gt;.venv&lt;/code&gt;:&lt;br /&gt;
Install capstone from Homebrew, remove the bundled library and link to the global one instead:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;brew install capstone
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;rm .venv/lib/python3.11/site-packages/capstone/lib/libcapstone.dylib
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;ln -s $(brew --cellar capstone)/5.0.1/lib/libcapstone.5.dylib .venv/lib/python3.11/site-packages/capstone/lib/libcapstone.dylib
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Usage&lt;/h3&gt;
&lt;p&gt;Invoke &lt;code&gt;sqlelf&lt;/code&gt; and pass any number of Mach-O binaries as arguments.
This gives you an SQLite REPL, or you specify SQL commands with &lt;code&gt;--sql&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example sqlelf knows about libraries references by the binary:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ sqlelf /usr/bin/grep --sql &amp;#39;select * from macho_libs&amp;#39;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;┌───────────────┬────────────────────────────┐
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│     path      │            lib             │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│ /usr/bin/grep │ self                       │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│ /usr/bin/grep │ /usr/lib/libbz2.1.0.dylib  │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│ /usr/bin/grep │ /usr/lib/liblzma.5.dylib   │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│ /usr/bin/grep │ /usr/lib/libz.1.dylib      │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│ /usr/bin/grep │ /usr/lib/libSystem.B.dylib │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;└───────────────┴────────────────────────────┘
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;None of those &lt;code&gt;/usr/lib/*.dylib&lt;/code&gt; actually exists in the filesystem though,
because Apple now ships those as a big bundled cache file instead.&lt;/p&gt;
&lt;p&gt;I have not yet documented the schema nor is it anywhere near complete.
Use &lt;code&gt;.schema&lt;/code&gt; to get an overview.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ sqlelf /usr/bin/grep --sql &amp;#39;.schema macho_headers&amp;#39;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;CREATE TABLE macho_headers(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  path,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  magic,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  cputype,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  cpusubtype,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  filetype,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  ncmds,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  sizeofcmds,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  flags,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  reserved
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tables are persisted views over the data, so everything is in memory.
Most values are the raw values read from the file,
so you will have to look up what those values mean.&lt;/p&gt;
&lt;p&gt;For example the headers include all sorts of magic numbers and file types as integers:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ sqlelf /usr/bin/grep --sql &amp;#39;select * from macho_headers&amp;#39;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;┌───────────────┬────────────┬──────────┬────────────┬──────────┬───────┬────────────┬─────────┬──────────┐
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│     path      │   magic    │ cputype  │ cpusubtype │ filetype │ ncmds │ sizeofcmds │  flags  │ reserved │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│ /usr/bin/grep │ 4277009103 │ 16777223 │ 3          │ 2        │ 21    │ 1688       │ 2097285 │ 0        │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;└───────────────┴────────────┴──────────┴────────────┴──────────┴───────┴────────────┴─────────┴──────────┘
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can slice and dice the data as you wish&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ sqlelf /usr/bin/grep --sql &amp;quot;select name, type, global, n_value from macho_symbols where path = &amp;#39;/usr/bin/grep&amp;#39; limit 3&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;┌─────────────────────┬────────┬────────┬────────────┐
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│        name         │  type  │ global │  n_value   │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│ radr://5614542      │ N_PBUD │ 0      │ 90260802   │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│ __mh_execute_header │ N_SECT │ 1      │ 4294967296 │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;│ _BZ2_bzRead         │ N_UNDF │ 1      │ 0          │
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;└─────────────────────┴────────┴────────┴────────────┘
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Status&lt;/h3&gt;
&lt;p&gt;I hacked together &lt;code&gt;oelf&lt;/code&gt; in a matter of days.
I&#39;m using the excellent &lt;a href=&quot;https://pyo3.rs/&quot;&gt;pyo3&lt;/a&gt; to wrap &lt;a href=&quot;https://crates.io/crates/goblin&quot;&gt;goblin&lt;/a&gt;&#39;s functionality into a Python package, built with &lt;a href=&quot;https://maturin.rs/&quot;&gt;maturin&lt;/a&gt;.
It works reliably (yey for great tooling written in and for Rust!),
but so far I haven&#39;t documented much.
&lt;code&gt;oelf&lt;/code&gt; itself is a bit inconsistent in how it exposes different data.
The &lt;code&gt;sqlelf&lt;/code&gt; integration is really simple,
thanks to a nice extensible code structure of the project.
Now every newly exposed functionality in &lt;code&gt;oelf&lt;/code&gt; needs only defining the schema of a table
and mapping the retrieved data to its columns.&lt;/p&gt;
&lt;p&gt;I have yet to actually &lt;em&gt;use&lt;/em&gt; sqlelf myself more to explore binaries and all the data in there.
I also have only a bare understanding of the ELF format and much much less of the Mach-O format,
I&#39;m just barely good at plugging together existing things.&lt;/p&gt;
&lt;p&gt;Some things that might be good to do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Documentation (of course!)&lt;/li&gt;
&lt;li&gt;Add more sections and tables and &quot;translate&quot; magic values
&lt;ul&gt;
&lt;li&gt;e.g. load commands (&lt;code&gt;macho_load_commands&lt;/code&gt;) pretty-print the Rust object right now, this should be proper data in the column, maybe just JSON to begin with?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Can we extract and parse system libraries from the shared dyld cache?
&lt;ul&gt;
&lt;li&gt;Others &lt;a href=&quot;https://github.com/keith/dyld-shared-cache-extractor&quot;&gt;have built stuff&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Can we more lazily fetch data instead of copying into a persisted table once?&lt;/li&gt;
&lt;li&gt;Upstream changes or fork it so &lt;code&gt;sqlelf&lt;/code&gt; actually works out of the box on any non-Linux machine&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;&lt;code&gt;adr://5614542&lt;/code&gt;: &lt;a href=&quot;https://github.com/PureDarwin/PureDarwin/blob/a9f762d321016242bb95542301a91ecb4eb9bfd3/tools/cctools/misc/strip.c#L3789-L3817&quot;&gt;this is a workaround for a workaround because of a bug in the old classic static linker.&lt;/a&gt; &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2024/01/02/oelf</guid>
      <pubDate>Tue, 02 Jan 2024 13:00:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Building and Deploying a Rust library on iOS</title>
      <link>https://fnordig.de/2022/01/31/rust-libraries-on-ios</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work.
They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2022/01/31/this-week-in-glean-building-and-deploying-a-rust-library-on-ios/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;We ship the Glean SDK for multiple platforms, one of them being iOS applications.
Previously I talked about &lt;a href=&quot;/2021/04/16/rustc-ios-and-an-m1/&quot;&gt;how we got it to build on the Apple ARM machines&lt;/a&gt;.
Today we will take a closer look at how to bundle a Rust static library into an iOS application.&lt;/p&gt;
&lt;p&gt;The Glean SDK project was set up in 2019 and we have evolved its project configuration over time.
A lot has changed in Xcode since then, so for this article we&#39;re starting with a fresh Xcode project, a fresh Rust library and put it all together step by step.&lt;br /&gt;
This is essentially an update to the &lt;a href=&quot;https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-06-rust-on-ios.html&quot;&gt;Building and Deploying a Rust library on iOS&lt;/a&gt; article from 2017.&lt;/p&gt;
&lt;p&gt;For future readers: This was done using Xcode 13.2.1 and rustc 1.58.1.&lt;br /&gt;
&lt;em&gt;One note: I learned iOS development to the extent required to ship Glean iOS.
I&#39;ve never written a full iOS application and lack a lot of experience with Xcode.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;The application&lt;/h2&gt;
&lt;p&gt;The premise of our application is easy:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Show a non-interactive message to the user with data from a Rust library.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let&#39;s get started on that.&lt;/p&gt;
&lt;h2&gt;The project&lt;/h2&gt;
&lt;p&gt;We start with a fresh iOS project.
Go to File -&amp;gt; New -&amp;gt; Project, then choose the iOS App template,
give it a name such as &lt;code&gt;ShippingRust&lt;/code&gt;,
select where to store it and finally create it.
You&#39;re greeted with &lt;code&gt;ContentView.swift&lt;/code&gt; and the following code:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;import SwiftUI
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;struct ContentView: View {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    var body: some View {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        Text(&amp;quot;Hello, world!&amp;quot;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            .padding()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can build and run it now. This will open the Simulator and display &quot;Hello, world!&quot;.
We&#39;ll get back to the Swift application later.&lt;/p&gt;
&lt;h2&gt;The Rust parts&lt;/h2&gt;
&lt;p&gt;First we set up the Rust library.&lt;/p&gt;
&lt;p&gt;In a terminal navigate to your &lt;code&gt;ShippingRust&lt;/code&gt; project directory.
In there create a new Rust crate:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo new --lib shipping-rust-ffi
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We will need a static library, so we change the crate type in the generated &lt;code&gt;shipping-rust-ffi/Cargo.toml&lt;/code&gt;.
Add the following below the package configuration:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[lib]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;crate-type = [&amp;quot;staticlib&amp;quot;]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s also turn the project into a Cargo workspace.
Create a new top-level &lt;code&gt;Cargo.toml&lt;/code&gt; with the content:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[workspace]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;members = [
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &amp;quot;shipping-rust-ffi&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;cargo build&lt;/code&gt; in the project directory should work now and create a new static library.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ ls -l target/debug/libshipping_rust_ffi.a
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;-rw-r--r-- 2 jer staff 16061952 Jan 28 13:09 target/debug/libshipping_rust_ffi.a
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s add some code to &lt;code&gt;shipping-rust-ffi/src/lib.rs&lt;/code&gt; next.
Nothing fancy, a simple function taking some arguments and returning the sum:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::os::raw::&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;c_int&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[no_mangle]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub extern &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;C&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;shipping_rust_addition&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(a: c_int, b: c_int) -&amp;gt; c_int {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    a &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; b
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;no_mangle&lt;/code&gt; ensures the name lands in the compiled library as-is
and the &lt;code&gt;extern &quot;C&quot;&lt;/code&gt; makes sure it uses the right ABI.&lt;/p&gt;
&lt;p&gt;We now have a Rust library exporting a C-ABI compatible interface.
We can now consume this in our iOS application.&lt;/p&gt;
&lt;h2&gt;The Xcode parts&lt;/h2&gt;
&lt;p&gt;Before we can use the code we need a bit more setup.
Strap in, there&#39;s a lot of fiddly manual steps now&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;We start by linking against the &lt;code&gt;libshipping_rust_ffi.a&lt;/code&gt; library.
In your Xcode project open your target configuration&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;,
go to &quot;Build Phases&quot;, then look for &quot;Link Binary with Libraries&quot;.
Add a new one, in the popup select &quot;Add files&quot; on the bottom left
and look for the &lt;code&gt;target/debug/libshipping_rust_ffi.a&lt;/code&gt; file.
Yes, that&#39;s actually for the wrong target. This is just for the name, we&#39;ll fix up the path next.
Go to &quot;Build Settings&quot; and search for &quot;Library Search Paths&quot;.
It probably has the path to file in there right now for both &lt;code&gt;Debug&lt;/code&gt; and &lt;code&gt;Release&lt;/code&gt; builds.
Remove that one for &lt;code&gt;Debug&lt;/code&gt;, then add a new row by clicking the small &lt;code&gt;+&lt;/code&gt; symbol.
Select the &lt;code&gt;Any Driverkit&lt;/code&gt; matcher.
It doesn&#39;t matter which matcher you choose or what value you give it,
but when we overwrite this manually in the next step I&#39;ll assume you chose &lt;code&gt;Any Driverkit&lt;/code&gt;.
Do the same for the &lt;code&gt;Release&lt;/code&gt; configuration.&lt;/p&gt;
&lt;p&gt;Once that&#39;s done, save your project and go back to your project directory.
We will modify the project configuration to have Xcode look for the library based on the target it is building for&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.
Open up &lt;code&gt;ShippingRust.xcodeproj/project.pbxproj&lt;/code&gt; in a text editor,
then search for the first line with &lt;code&gt;&quot;LIBRARY_SEARCH_PATHS[sdk=driverkit*]&quot;&lt;/code&gt;.
It should be in a section saying &lt;code&gt;/* Debug */&lt;/code&gt;.
Remove the &lt;code&gt;LIBRARY_SEARCH_PATHS&lt;/code&gt; line and add 3 new ones:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;quot;LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]&amp;quot; = &amp;quot;$(PROJECT_DIR)/target/aarch64-apple-ios/debug&amp;quot;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;quot;LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]&amp;quot; = &amp;quot;$(PROJECT_DIR)/target/aarch64-apple-ios-sim/debug&amp;quot;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;quot;LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=x86_64]&amp;quot; = &amp;quot;$(PROJECT_DIR)/target/x86_64-apple-ios/debug&amp;quot;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Look for the next line with &lt;code&gt;&quot;LIBRARY_SEARCH_PATHS[sdk=driverkit*]&quot;&lt;/code&gt;, now in a &lt;code&gt;/* Release */&lt;/code&gt; section and replace it with:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;quot;LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]&amp;quot; = &amp;quot;$(PROJECT_DIR)/target/aarch64-apple-ios/release&amp;quot;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;quot;LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]&amp;quot; = &amp;quot;$(PROJECT_DIR)/target/aarch64-apple-ios-sim/release&amp;quot;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;quot;LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=x86_64]&amp;quot; = &amp;quot;$(PROJECT_DIR)/target/x86_64-apple-ios/release&amp;quot;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Save the file and return focus back to Xcode.
If you didn&#39;t make any typos Xcode should still have your project open.
In the settings you will find the library search paths as we&#39;ve just defined them.
If you messed something up Xcode will complain that it cannot read the project file if you try to go to the settings.&lt;/p&gt;
&lt;p&gt;Next we need to teach Xcode how to compile Rust code.
Once again go to your target settings, selecting the &quot;Build Phases&quot; tab again.&lt;/p&gt;
&lt;p&gt;There add a new &quot;Run Script&quot; phase, give it the name &quot;Build Rust library&quot;
(double-click the &quot;Run Script&quot; section header),
and set the command to:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;bash ${PROJECT_DIR}/bin/compile-library.sh shipping-rust-ffi $buildvariant
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;compile-library.sh&lt;/code&gt; script is going to do the heavy lifting.
The first argument is the crate name we want to compile, the second is the build variant to select.
This is not yet defined, so let&#39;s do it first.&lt;/p&gt;
&lt;p&gt;Go to the &quot;Build Settings&quot; tab and click the &lt;code&gt;+&lt;/code&gt; button to add a new &quot;User-Defined Setting&quot;.
Give it the name &lt;code&gt;buildvariant&lt;/code&gt; and choose a value based on the build variant: &lt;code&gt;debug&lt;/code&gt; for &lt;code&gt;Debug&lt;/code&gt; and &lt;code&gt;release&lt;/code&gt; for &lt;code&gt;Release&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now we need the actual script to build the Rust library for the right targets.
It&#39;s a bit long to write out, but the logic is not too complex:
First we select the Cargo profile to use based on our &lt;code&gt;buildvariant&lt;/code&gt; (that is whether to pass &lt;code&gt;--release&lt;/code&gt; or not),
then we set up &lt;code&gt;LIBRARY_PATH&lt;/code&gt; if necessary and finally compile the Rust library for the selected target.
Xcode passes the architectures to build in &lt;code&gt;ARCHS&lt;/code&gt;.
It&#39;s either &lt;code&gt;x86_64&lt;/code&gt; for simulator builds on Intel Mac hardware or &lt;code&gt;arm64&lt;/code&gt;.
If it&#39;s &lt;code&gt;arm64&lt;/code&gt; it can be either the simulator or an actual hardware target.
Those differ, but we can know which is which from what&#39;s in &lt;code&gt;LLVM_TARGET_TRIPLE_SUFFIX&lt;/code&gt; and select the right Rust target.&lt;/p&gt;
&lt;p&gt;Let&#39;s put all of that into a &lt;code&gt;compile-library.sh&lt;/code&gt; script.
Create a new directory &lt;code&gt;bin&lt;/code&gt; in your project directory.
In there create the file with the following content:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;$&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;-ne 2 &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;then
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;echo &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;Usage (note: only call inside xcode!):&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;echo &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;compile-library.sh &amp;lt;FFI_TARGET&amp;gt; &amp;lt;buildvariant&amp;gt;&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;exit&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; 1
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# what to pass to cargo build -p, e.g. your_lib_ffi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FFI_TARGET&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;1
&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# buildvariant from our xcconfigs
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;BUILDVARIANT&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;2
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;RELFLAG&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;[[ &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;$&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;BUILDVARIANT&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;debug&amp;quot; &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;]]&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;; then
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  RELFLAG&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;--release
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;set &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;-euvx
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;[[ &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;-n &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;${&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;DEVELOPER_SDK_DIR&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;:-&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;}&amp;quot; &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;]]&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;; then
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# Assume we&amp;#39;re in Xcode, which means we&amp;#39;re probably cross-compiling.
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# In this case, we need to add an extra library search path for build scripts and proc-macros,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# which run on the host instead of the target.
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# (macOS Big Sur does not have linkable libraries in /usr/lib/.)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;export &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;LIBRARY_PATH&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;${&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;DEVELOPER_SDK_DIR&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;}/MacOSX.sdk/usr/lib:${&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;LIBRARY_PATH&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;:-&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;}&amp;quot;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;IS_SIMULATOR&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;0
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;${&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;LLVM_TARGET_TRIPLE_SUFFIX&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;}&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;-simulator&amp;quot; &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;; then
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  IS_SIMULATOR&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;1
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; arch &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;in &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ARCHS&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;; do
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;case &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;$&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;arch&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;in
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    x86_64&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$IS_SIMULATOR -eq 0 &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;; then
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;echo &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;Building for x86_64, but not a simulator build. What&amp;#39;s going on?&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;2
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;exit&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; 2
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# Intel iOS simulator
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;export &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;CFLAGS_x86_64_apple_ios&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;-target x86_64-apple-ios&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      $HOME/.cargo/bin/cargo build -p $FFI_TARGET --lib $RELFLAG --target x86_64-apple-ios
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      ;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    arm64&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$IS_SIMULATOR -eq 0 &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;; then
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# Hardware iOS targets
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        $HOME/.cargo/bin/cargo build -p $FFI_TARGET --lib $RELFLAG --target aarch64-apple-ios
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;else
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        $HOME/.cargo/bin/cargo build -p $FFI_TARGET --lib $RELFLAG --target aarch64-apple-ios-sim
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;esac
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;done
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now we&#39;re done with the setup for compiling the Rust library automatically as part of the Xcode project build.&lt;/p&gt;
&lt;h2&gt;The code parts&lt;/h2&gt;
&lt;p&gt;We now have an Xcode project that builds our Rust library and links against it.
We now need to use this library!&lt;/p&gt;
&lt;p&gt;Swift speaks Objective-C, which is an extension to C,
but we need to tell it about the things available.
In C land that&#39;s done with a header.
Let&#39;s create a new file, select the &quot;Header File&quot; template and name it &lt;code&gt;FfiBridge.h&lt;/code&gt;.
This will create a new file with this content:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;#ifndef&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; FfiBridge_h
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;#define &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiBridge_h
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;#endif &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;/* FfiBridge_h */
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we need to add the definition of our function.
As a reminder this is its definition in Rust:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;extern &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;C&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;shipping_rust_addition&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(a: c_int, b: c_int) -&amp;gt; c_int;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This translates to the following in C:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;int &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;shipping_rust_addition&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;int &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;a, &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;int &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;b);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add that line between the &lt;code&gt;#define&lt;/code&gt; and &lt;code&gt;#endif&lt;/code&gt; lines.
Xcode doesn&#39;t know about that file yet, so once more into the &lt;code&gt;Build Settings&lt;/code&gt; of the target.
Search for &lt;code&gt;Objective-C Bridging Header&lt;/code&gt; and set it to &lt;code&gt;$(PROJECT_DIR)/ShippingRust/FfiBridge.h&lt;/code&gt;.
In &lt;code&gt;Build Phases&lt;/code&gt; add a new &lt;code&gt;Header Phase&lt;/code&gt;.
There you add the &lt;code&gt;FfiBridge.h&lt;/code&gt; as well.&lt;/p&gt;
&lt;p&gt;If it now all compiles we&#39;re finally ready to use our Rust library.&lt;/p&gt;
&lt;p&gt;Open up &lt;code&gt;ContentView.swift&lt;/code&gt; and change the code to call your Rust library:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;struct ContentView: View {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    var body: some View {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        Text(&amp;quot;Hello, world! \(shipping_rust_addition(30, 1))&amp;quot;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            .padding()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We simply interpolate the result of &lt;code&gt;shipping_rust_addition(30, 1)&lt;/code&gt; into the string displayed.&lt;/p&gt;
&lt;p&gt;Once we compile and run it in the simulator we see we&#39;ve succeeded at satisfying our premise:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Show a non-interactive message to the user with data from a Rust library.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2022/ios-simulator-helloworld31.png&quot; alt=&quot;iOS simulator running our application showing &amp;quot;Hello, world! 31&amp;quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Compiling for any iOS device should work just as well.&lt;/p&gt;
&lt;h2&gt;The next steps&lt;/h2&gt;
&lt;p&gt;This was a lot of setup for calling one simple function.
Luckily this is a one-time setup. From here on you can extend your Rust library, define them in the header file and call them from Swift.
If you go that route you should really start using &lt;a href=&quot;https://github.com/eqrion/cbindgen&quot;&gt;cbindgen&lt;/a&gt; to generate that header file automatically for you.&lt;/p&gt;
&lt;p&gt;This time we looked at building an iOS application directly calling a Rust library.
That&#39;s not actually how Glean works. The Glean Swift SDK itself wraps the Rust library and exposes a Swift library.
In a next blog post I&#39;ll showcase how we ship that as a Swift package.&lt;/p&gt;
&lt;p&gt;For Glean we&#39;re stepping away from manually writing our FFI functions.
We&#39;re instead migrating our code base to use &lt;a href=&quot;https://github.com/mozilla/uniffi-rs/&quot;&gt;UniFFI&lt;/a&gt;.
UniFFI will generate the C API from an API definitions file and also comes with a bit of runtime code to handle conversion between Rust, C and Swift data types for us.
We&#39;re not there yet for Glean, but you can try it on your own. &lt;a href=&quot;https://mozilla.github.io/uniffi-rs/&quot;&gt;Read the UniFFI documentation&lt;/a&gt; and integrate it into your project.
It should be possible to extent the setup we done her to also run the necessary steps for UniFFI.
Eventually I&#39;ll document how we did it as well.&lt;/p&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;And most of these steps are user-interface-dependent and might be different in future Xcode version. :( &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Click your project name in the tree view on the left. This gets you to the project configuration (backed by the &lt;code&gt;ShippingRust.xcodeproj/project.pbxproj&lt;/code&gt; file). You should then see the Targets, including your &lt;code&gt;ShippingRust&lt;/code&gt; target and probably &lt;code&gt;ShippingRustTests&lt;/code&gt; as well. We need the former. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;Previously we would have built a universal library containing the library of multiple targets. That doesn&#39;t work anymore now that &lt;code&gt;arm64&lt;/code&gt; can stand for both the simulator and hardware targets. Thus linking to the individual libraries is the way to go, as the now-deprecated &lt;a href=&quot;https://github.com/TimNN/cargo-lipo&quot;&gt;&lt;code&gt;cargo-lipo&lt;/code&gt;&lt;/a&gt; also points out. &lt;a href=&quot;#fr-3-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2022/01/31/rust-libraries-on-ios</guid>
      <pubDate>Mon, 31 Jan 2022 12:40:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Crashes &amp; a buggy Glean</title>
      <link>https://fnordig.de/2021/11/01/crashes-and-a-buggy-glean</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2021/11/01/this-week-in-glean-crashes-a-buggy-glean&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;In September I finally &lt;a href=&quot;/2021/09/17/glean-geckoview/&quot;&gt;landed work to ship Glean through GeckoView&lt;/a&gt;.
Contrary to what that post said Fenix did not actually &lt;em&gt;use&lt;/em&gt; Glean coming from GeckoView immediately due to another bug that took us &lt;a href=&quot;https://github.com/mozilla-mobile/android-components/pull/11045&quot;&gt;another few days&lt;/a&gt; to land.
Shortly after that was shipped in a Fenix Nightly release we received a crash report (&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1733757&quot;&gt;bug 1733757&lt;/a&gt;) pointing to code that we haven&#39;t touched in a long time.
And yet the change of switching from a standalone Glean library to shipping Glean in GeckoView uncovered a crashing bug, that quickly rose to be the top crasher for Fenix for more than a week.&lt;/p&gt;
&lt;p&gt;When I picked up that bug after the weekend I was still thinking that this would be &lt;em&gt;just&lt;/em&gt; a bug, which we can identify &amp;amp; fix and then get into the next Fenix release.
But in data land nothing is ever &lt;em&gt;just&lt;/em&gt; a bug.&lt;/p&gt;
&lt;p&gt;As I don&#39;t own an Android device myself I was initially restricted to the Android emulator,
but I was unsuccessful in triggering that bug in my simple use of Fenix or in any tests I wrote.
At some point I went as far as &lt;a href=&quot;https://fnordig.de/2021/10/14/fenix-physical-device-testing/&quot;&gt;leveraging physical devices in the Firebase test lab&lt;/a&gt;,
still with no success of hitting the bug.
Later that week I picked up an Android test device, hoping to find easy steps to reproduce the crash.
Thankfully we also have quality assurance people running tests and simply &lt;em&gt;using&lt;/em&gt; the browser
and reporting back steps to reproduce bugs and crashes.
And so that&#39;s what one of them, Delia, did: &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/issues/21767&quot;&gt;Providing simple steps to reproduce the crash&lt;/a&gt;.
Simple here meant: open a website and leave the phone untouched for roughly 8-9 minutes.
With those steps I was able to reproduce the crash in both the emulator and my test device as well.&lt;/p&gt;
&lt;p&gt;As I was waiting for the crash to occur I started reading the code again.
From the crash report I already knew the &lt;a href=&quot;https://github.com/mozilla/ffi-support/blob/0fdc22a8dfe3731be5fd39b311e4e4885219e26c/src/handle_map.rs#L409&quot;&gt;exact place where the code panics&lt;/a&gt; and thus crashes the application,
I just didn&#39;t know how it got there.
While reading the code around the panic and the knowledge that it takes several minutes to get to the panic I finally stumbled upon a clue:
The map implementation that was used internally has &lt;a href=&quot;https://github.com/mozilla/ffi-support/blob/0fdc22a8dfe3731be5fd39b311e4e4885219e26c/src/handle_map.rs#L160-L166&quot;&gt;a maximum capacity of elements it can store&lt;/a&gt;.
It even documents that it will panic&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;!&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;/// The maximum capacity of a [`HandleMap`]. Attempting to instantiate one with
&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;/// a larger capacity will cause a panic.
&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;///
&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;/// [...]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub const &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;MAX_CAPACITY&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;usize = &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1 &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;lt; &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I now knew that at some point Glean exhausts the map capacity,
slowly but eventually leading to a panic&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.
Most of Glean is set up to not require dynamically allocating new things other than the data itself,
but we never store the data itself within such a map.
So where are we using a map and dynamically add new entries to it and potentially forget to remove them after use?&lt;/p&gt;
&lt;p&gt;Luckily the stack trace from those crash reports gave me another clue:
All crashes were caused by &lt;a href=&quot;https://mozilla.github.io/glean/book/reference/metrics/labeled_counters.html&quot;&gt;labeled counters&lt;/a&gt;.
Some instrument-the-code-paths-and-recompile cycles later I was able to pinpoint it to the exact metric that was causing the crash.&lt;/p&gt;
&lt;p&gt;With all this information collected I was able to determine that while the panic was happening in a library we use,
the problem was that Glean had the wrong assumptions about how the use of labeled counters in Kotlin maps to objects in a Rust map.
On every subscript access to a labeled counter (&lt;code&gt;myCounter[&quot;label&quot;]&lt;/code&gt;) Glean would create a new object, store it in the map and return a handle to this object.
The solution was to avoid creating new entries in that map on every access from a foreign language and instead cache created objects by a unique identifier
and hand out already-created objects when re-accessed.
This fix &lt;a href=&quot;https://github.com/mozilla/glean/commit/499309475f4f002bdd6c19db4aa051634760efe1#diff-fe013beaf77cb562dae30dd3e639f386b9c9f01d6bc6800538ccd72eb89ad68cR77-R107&quot;&gt;was implemented in a few lines&lt;/a&gt;, accompanied by an extensive commit message as well as tests in all of the 3 major foreign-language Glean SDKs.&lt;/p&gt;
&lt;p&gt;That fix was released in &lt;a href=&quot;https://github.com/mozilla/glean/releases/tag/v42.0.1&quot;&gt;Glean v42.0.1&lt;/a&gt;, and shortly after in Fenix Nightly and Beta.&lt;/p&gt;
&lt;p&gt;The bug was fixed and the crash prevented, but that wasn&#39;t the end of it.
The code leading to the bug has been in Glean since at least March 2020
and yet we only started seeing crashes with the GeckoView change.
What was happening before? Did we miss these crashes for more than a year or were there simply no crashes?&lt;/p&gt;
&lt;p&gt;To get a satisfying answer to these questions I had to retrace the issue in older Glean versions.
I took older versions of Glean &amp;amp; Fenix from just before the GeckoView-Glean changes,
added logging and built myself a Fenix to run in the emulator.
And as quickly as that&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; &lt;code&gt;logcat&lt;/code&gt; spit out the following lines repeatedly:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;E  ffi_support::error: Caught a panic calling rust code: &amp;quot;called `Result::unwrap()` on an `Err` value: \&amp;quot;PoisonError { inner: .. }\&amp;quot;&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;E  glean_ffi::handlemap_ext: Glean failed (ErrorCode(-1)): called `Result::unwrap()` on an `Err` value: &amp;quot;PoisonError { inner: .. }&amp;quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No crashes! It panics, but it doesn&#39;t crash in old Fenix versions.
So why does it crash in new versions?
It&#39;s a combination of things.&lt;/p&gt;
&lt;p&gt;First Glean data recording happens in a thread to avoid blocking the main thread.
Right now that thread is handled on the Kotlin side.
A panic in the Rust code base will bubble up the stack and crash the thread, thus poisoning the internal lock of the map,
but it will not abort the whole application by itself.
Subsequent calls will run on a new thread, handled by the Kotlin side.
When using a labeled counter again it will try to acquire the lock,
detect that it is poisoned and panic once more.
That panic is caught by the FFI layer of Glean and turned into a log message.&lt;/p&gt;
&lt;p&gt;Second the standalone Glean library is compiled with &lt;a href=&quot;https://doc.rust-lang.org/cargo/reference/profiles.html#panic&quot;&gt;&lt;code&gt;panic=unwind&lt;/code&gt;&lt;/a&gt;, the default in Rust,
which unwinds the stack on panics.
If not caught the runtime will abort the current thread, writing a panic message to the error output.
&lt;code&gt;ffi-support&lt;/code&gt; however catches it, logs it and returns without crashing or aborting.
Gecko on the other hand sets &lt;a href=&quot;https://searchfox.org/mozilla-central/rev/a9e0a3f5e5f7cde941d419db967997aaa1f06b0f/Cargo.toml#63&quot;&gt;&lt;code&gt;panic=abort&lt;/code&gt;&lt;/a&gt;.
In this mode a panic will immediately terminate the current process (after writing the crash message to the error output),
without ever trying to unwind the stack, giving no chance for the support library to catch it.
The Gecko crash reporter is able to catch those hard aborts and send them as crash reports.
As Glean is now part of the overall Gecko build all of Gecko&#39;s build flags will transitively apply to Glean and its dependencies, too.
So when Glean is shipped as part of GeckoView it runs in &lt;code&gt;panic=abort&lt;/code&gt; mode, leading to internal panics aborting the whole application.&lt;/p&gt;
&lt;p&gt;That behavior by itself is fine: Glean should only panic in exceptional cases and we&#39;d like to know about them.
It&#39;s good to know that an application could continue running without Glean working correctly;
we won&#39;t be able to record and send telemetry data, but at least we&#39;re not interrupting someone using the application.
However unless we engineers run into those bugs and see the log we will not notice them and thus can&#39;t fix them.
So ultimately this change in (crashing) behavior is acceptable (and wanted) going forward.&lt;/p&gt;
&lt;p&gt;After fixing the initial bug and being able to answer why it only started crashing recently my work was still not done.
We were likely not recording data in exceptional cases for quite some time, which is not acceptable for a telemetry library.
I had to explore our data, estimate how many metrics for how many clients were affected, inform relevant stakeholders and plan further mitigations.
But that part of the investigation is a story for another time.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This bug investigation had help from a lot of people.
Thanks to Mike Droettboom for coordination,
Marissa Gorlick for pushing me to evaluate the impact on data &amp;amp; reaching the right people,
Travis Long for help with the Glean code &amp;amp; speedy reviews,
Alessio Placitelli for reviews on the Gecko side,
Delia Pop for the initial steps to reproduce the bug
&amp;amp; Christian Sadilek for help on the Android Components &amp;amp; Fenix side.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Except that it panics at a slightly different place than the explicit check in the code base would suggest. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;That meant I could also &lt;em&gt;tune&lt;/em&gt; how quickly it crashed. A smaller maximum capacity means its reached more quickly, reducing my bug reproduction time significantly. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;#fr-2-2&quot; class=&quot;footnotes-backref&quot;&gt;↩2&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;No, not after 9 minutes, but in just under 3 minutes after tuning the maximum map capacity, see &lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-2&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. &lt;a href=&quot;#fr-3-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2021/11/01/crashes-and-a-buggy-glean</guid>
      <pubDate>Mon, 01 Nov 2021 15:00:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Glean &amp; GeckoView</title>
      <link>https://fnordig.de/2021/09/17/glean-geckoview</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2021/09/17/this-week-in-glean-glean-geckoview/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;This is a followup post to &lt;a href=&quot;/2021/07/26/shipping-glean-with-geckoview/&quot;&gt;Shipping Glean with GeckoView&lt;/a&gt;.&lt;/p&gt;
&lt;center&gt;
&lt;h2&gt;It landed!&lt;/h2&gt;
&lt;/center&gt;
&lt;p&gt;It took us several more weeks to put everything into place, but we&#39;re finally shipping the Rust parts of the Glean Android SDK with GeckoView
and consume that in &lt;a href=&quot;https://github.com/mozilla-mobile/android-components/pull/10828&quot;&gt;Android Components&lt;/a&gt; and &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/pull/20889&quot;&gt;Fenix&lt;/a&gt;.
And it still all works, collects data and is sending pings!
Additionally this results in a slightly smaller APK as well.&lt;/p&gt;
&lt;p&gt;This unblocks further work now.
Currently Gecko simply stubs out all calls to Glean when compiled for Android,
but we will enable recording Glean metrics within Gecko and exposing them in pings sent from Fenix.
We will also start work on moving other Rust components into mozilla-central in order for them to use the Rust API of Glean directly.
Changing how we deliver the Rust code also made testing Glean changes across these different components a bit more challenging,
so I want to invest some time to make that easier again.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2021/09/17/glean-geckoview</guid>
      <pubDate>Fri, 17 Sep 2021 13:00:00 +0200</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Shipping Glean with GeckoView</title>
      <link>https://fnordig.de/2021/07/26/shipping-glean-with-geckoview</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2021/07/26/this-week-in-glean-shipping-glean-with-geckoview&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Glean SDK&lt;/h2&gt;
&lt;p&gt;The Glean SDK is Mozilla&#39;s telemetry library, used in most mobile products and now for Firefox Desktop as well.
By now it has grown to a sizable code base with a lot of functionality beyond just storing some metric data.
Since its first release as a Rust crate in 2019 we managed to move more and more logic from the language SDKs
(previously also known as &quot;language bindings&quot;) into the core Rust crate.
This allows us to maintain business logic only once and can easily share that across different implementations and platforms.
The Rust core is shipped precompiled for multiple target platforms, with the language SDK distributed through the respective package manager.&lt;/p&gt;
&lt;p&gt;I talked about how this all works in more detail
&lt;a href=&quot;https://www.youtube.com/watch?v=j5rczOF7pzg&quot;&gt;last year&lt;/a&gt;,
&lt;a href=&quot;https://www.youtube.com/watch?v=j5rczOF7pzg&quot;&gt;this year&lt;/a&gt;
and blogged about it &lt;a href=&quot;/2020/09/01/leveraging-rust-to-build-cross-platform-mobile-libraries/&quot;&gt;in a previous TWiG&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;GeckoView&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://mozilla.github.io/geckoview/&quot;&gt;GeckoView&lt;/a&gt; is Mozilla&#39;s alternative implementation for WebViews on Android, based on Gecko, the web engine that also powers Firefox Desktop.
It is used as the engine behind &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/&quot;&gt;Firefox for Android&lt;/a&gt; (also called Fenix).
The visible parts of what makes up Firefox for Android is written in Kotlin, but it all delegates to the underlying Gecko engine,
written in a combination of C++, Rust &amp;amp; JavaScript.&lt;/p&gt;
&lt;p&gt;The GeckoView code resides in the mozilla-central repository, next to all the other Gecko code.
From there releases are pushed to Mozilla&#39;s own &lt;a href=&quot;https://maven.mozilla.org/maven2/&quot;&gt;Maven repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;One Glean too many&lt;/h2&gt;
&lt;p&gt;Initially Firefox for Android was the only user of the Glean SDK.
Up until today it consumes Glean through its release as part of &lt;a href=&quot;https://github.com/mozilla-mobile/android-components/&quot;&gt;Android Components&lt;/a&gt;, a collection of libraries to build browser-like applications.&lt;/p&gt;
&lt;p&gt;But the Glean SDK is also available outside of Android Components, as its own package.
And additionally it&#39;s available for other languages and platforms too, including a &lt;a href=&quot;https://crates.io/crates/glean&quot;&gt;Rust crate&lt;/a&gt;.
&lt;a href=&quot;https://blog.mozilla.org/data/2020/10/06/this-week-in-glean-fog-progress-report/&quot;&gt;Over the past year we&#39;ve been busy&lt;/a&gt; getting Gecko to use Glean through the Rust crate to build its own telemetry on top.&lt;/p&gt;
&lt;p&gt;With the Glean SDK used in all these applications we&#39;re in a difficult position:
There&#39;s a Glean in Firefox for Android that&#39;s reporting data.
Firefox for Android is using Gecko to render the web.
And Gecko is starting to use Glean to report data.&lt;/p&gt;
&lt;p&gt;That&#39;s one Glean too many if we want coherent data from the full application.&lt;/p&gt;
&lt;h2&gt;Shipping it all together, take one&lt;/h2&gt;
&lt;p&gt;Of course we knew about this scenario for a long time.
It&#39;s been one of the goals of Project FOG to transparently collect data from Gecko and the embedding application!&lt;/p&gt;
&lt;p&gt;We set out to find a solution so that we can connect both sides and have only one Glean be responsible for the data collection &amp;amp; sending.&lt;/p&gt;
&lt;p&gt;We started with more detailed planning all the way back in August of last year
and agreed on a design in October.
Due to changed priorities &amp;amp; availability of people we didn&#39;t get into the implementation phase until earlier this year.&lt;/p&gt;
&lt;p&gt;By February I had a first rough prototype in place.
When Gecko was shipped as part of GeckoView it would automatically look up the Glean library that is shipped as a dynamic library with the Android application.
All function calls to record data from within Gecko would thus ultimately land in the Glean instance that is controlled by Fenix.
Glean and the abstraction layer within Gecko would do the heavy work, but users of the Glean API would notice no difference,
except their data would now show up in pings sent from Fenix.&lt;/p&gt;
&lt;p&gt;This integration was brittle.
It required finding the right dynamic library, looking up symbols at runtime as well as reimplementing all metric types to switch to the FFI API in a GeckoView build.
We abandoned this approach and started looking for a better one.&lt;/p&gt;
&lt;h2&gt;Shipping it all together, take two&lt;/h2&gt;
&lt;p&gt;After the first failed approach the issue was acknowledged by other teams, including the GeckoView and Android teams.&lt;/p&gt;
&lt;p&gt;Glean is not the only Rust project shipped for mobile,
the &lt;a href=&quot;https://github.com/mozilla/application-services&quot;&gt;application-services team&lt;/a&gt; is also shipping components written in Rust.
They bundle all components into a single library, dubbed the &lt;a href=&quot;https://github.com/mozilla/application-services/blob/main/docs/design/megazords.md&quot;&gt;megazord&lt;/a&gt;.
This reduces its size (dependencies &amp;amp; the Rust standard library are only linked once) and simplifies shipping, because there&#39;s only one library to ship.
We always talked about pulling in Glean as well into such a megazord, but ultimately didn&#39;t do it (except for &lt;a href=&quot;https://github.com/mozilla/application-services/tree/main/megazords/ios&quot;&gt;iOS builds&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;With that in mind we decided it&#39;s now the time to design a solution, so that eventually we can bundle multiple Rust components in a single build.
We came up with the following plan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Glean Kotlin SDK will be split into 2 packages: a &lt;code&gt;glean-native&lt;/code&gt; package, that only exists to ship the compiled Rust library, and a &lt;code&gt;glean&lt;/code&gt; package,
that contains the Kotlin code and has a dependency on &lt;code&gt;glean-native&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The GeckoView-provided &lt;code&gt;libxul&lt;/code&gt; library (that&#39;s &quot;Gecko&quot;) will bundle the Glean Rust library and export the C-compatible FFI symbols,
that are used by the Glean Kotlin SDK to call into Glean core.&lt;/li&gt;
&lt;li&gt;The GeckoView Kotlin package will then use Gradle capabilities to replace the &lt;code&gt;glean-native&lt;/code&gt; package with itself (this is actually handle by the Glean Gradle plugin).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Consumers such as Fenix will depend on both GeckoView and Glean.
At build time the Glean Gradle plugin will detect this and will ensure the &lt;code&gt;glean-native&lt;/code&gt; package, and thus the Glean library, is not part of the build.
Instead it assumes &lt;code&gt;libxul&lt;/code&gt; from GeckoView will take that role.&lt;/p&gt;
&lt;p&gt;This has some advantages.
First off everything is compiled together into one big library.
Rust code gets linked together and even Rust consumers within Gecko can directly use the Glean Rust API.
Next up we can ensure that the version of the Glean core library matches the Glean Kotlin package used by the final application.
It is important that the code matches, otherwise calling native functions could lead to memory or safety issues.&lt;/p&gt;
&lt;p&gt;Glean is running ahead here, paving the way for more components to be shipped the same way.
Eventually the experimentation SDK called Nimbus and other application-services components will start using the Rust API of Glean.
This will require compiling Glean alongside them and that&#39;s the exact case that is handled in mozilla-central for GeckoView then.&lt;/p&gt;
&lt;p&gt;Now the unfortunate truth is: these changes have not landed yet.
It&#39;s been implemented for both the Glean SDK and mozilla-central,
but also requires changes for the build system of mozilla-central.
Initially that looked like simple changes to adopt the new bundling,
but it turned into bigger changes across the board.
Some of the infrastructure used to build and test Android code from mozilla-central was untouched for years and thus is very outdated
and not easy to change.
With everything else going on for Firefox it&#39;s been a slow process to update the infrastructure, prepare the remaining changes and finally getting this landed.&lt;/p&gt;
&lt;p&gt;But we&#39;re close now!&lt;/p&gt;
&lt;p&gt;Big thanks to &lt;a href=&quot;https://github.com/agi/&quot;&gt;Agi&lt;/a&gt; for connecting the right people, driving the initial design and helping me with the GeckoView changes.
He also took on the challenge of changing the build system.
And also thanks to &lt;a href=&quot;https://github.com/chutten&quot;&gt;chutten&lt;/a&gt; for his reviews and input. He&#39;s driving the FOG work forward and thus really really needs us to ship GeckoView support.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2021/07/26/shipping-glean-with-geckoview</guid>
      <pubDate>Mon, 26 Jul 2021 12:00:00 +0200</pubDate>
    </item>
    <item>
      <title>This Week in Glean: rustc, iOS and an M1</title>
      <link>https://fnordig.de/2021/04/16/rustc-ios-and-an-m1</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2021/04/16/this-week-in-glean-rustc-ios-and-an-m1/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Back in February I got an M1 MacBook.
That&#39;s Apple&#39;s new ARM-based hardware.&lt;/p&gt;
&lt;p&gt;I got it with the explicit task to ensure that we are able to develop and build &lt;a href=&quot;https://github.com/mozilla/glean&quot;&gt;Glean&lt;/a&gt; on it.
We maintain a &lt;a href=&quot;https://github.com/mozilla/glean/tree/main/glean-core/ios&quot;&gt;Swift language binding&lt;/a&gt;, targeting iOS, and that one is used in &lt;a href=&quot;https://github.com/mozilla-mobile/firefox-ios&quot;&gt;Firefox iOS&lt;/a&gt;.
Eventually these iOS developers will also have M1-based machines and want to test their code, thus Glean needs to work.&lt;/p&gt;
&lt;p&gt;Here&#39;s what we need to get to work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Compile the Rust portions of Glean natively on an M1 machine&lt;/li&gt;
&lt;li&gt;Build &amp;amp; test the Kotlin &amp;amp; Swift language bindings on an M1 machine, even if non-native (e.g. Rosetta 2 emulation for x86_64)&lt;/li&gt;
&lt;li&gt;Build &amp;amp; test the Swift language bindings natively and in the iPhone simulator on an M1 machine&lt;/li&gt;
&lt;li&gt;Stretch goal: Get iOS projects using Glean running as well&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Rust on an M1&lt;/h2&gt;
&lt;p&gt;Work on getting Rust compiled on M1 hardware started last year in June already, with the availability of the first developer kits.
See &lt;a href=&quot;https://github.com/rust-lang/rust/issues/73908&quot;&gt;Rust issue 73908&lt;/a&gt; for all the work and details.
First and foremost this required a new target: &lt;code&gt;aarch64-apple-darwin&lt;/code&gt;.
This landed in August and was promoted to Tier 2&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; with the &lt;a href=&quot;https://blog.rust-lang.org/2020/12/31/Rust-1.49.0.html#64-bit-arm-macos-and-windows-reach-tier-2&quot;&gt;December release of Rust 1.49.0&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;By the time I got my MacBook compiling Rust code on it was as easy as on an Intel MacBook.
Developers on Intel MacBooks can cross-compile just as easily:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;rustup target add aarch64-apple-darwin
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo build --target aarch64-apple-darwin
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Glean Python &amp;amp; Kotlin on an M1&lt;/h2&gt;
&lt;p&gt;Glean Python just ... worked.
We use &lt;code&gt;cffi&lt;/code&gt; to load the native library into Python.
It gained &lt;code&gt;aarch64&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; macOS support in &lt;a href=&quot;https://cffi.readthedocs.io/en/latest/whatsnew.html#v1-14-1&quot;&gt;v14.4.1&lt;/a&gt;.
My colleague glandium later &lt;a href=&quot;https://github.com/mozilla/glean/pull/1534&quot;&gt;contributed support code&lt;/a&gt; so we build release wheels for that target too.
So it&#39;s both possible to develop &amp;amp; test Glean Python, as well as use it as a dependency without having a full Rust development environment around.&lt;/p&gt;
&lt;p&gt;Glean Android is not that straight forward.
Some of our transitive dependencies are based on years-old pre-built binaries of SQLite
and of course there&#39;s not much support behind updating those Java libraries.
It&#39;s possible. A friend managed to compile and run that library on an M1.
But for Glean development we simply recommend relying on Rosetta 2 (the x86_64 compatibility layer) for now.
It&#39;s as easy as:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;arch -x86_64 $SHELL
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;make build-kotlin
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At least if you have Java set up correctly...
The default Android emulator isn&#39;t usable on M1 hardware yet, but Google is working on a compatible one: &lt;a href=&quot;https://github.com/google/android-emulator-m1-preview&quot;&gt;Android M1 emulator preview&lt;/a&gt;.
It&#39;s usable enough for some testing, but for that part I most often switch back to my Linux Desktop (that has the additional CPU power on top).&lt;/p&gt;
&lt;h2&gt;Glean iOS on an M1&lt;/h2&gt;
&lt;p&gt;Now we&#39;re getting to the interesting part: Native iOS development on an M1.
Obviously for Apple this is a priority:
Their new machines should become the main machine people do iOS development on.
Thus Xcode gained &lt;code&gt;aarch64&lt;/code&gt; support in version 12 long before the hardware was available.
That caused quite some issues with existing tooling, such as the &lt;a href=&quot;https://github.com/Carthage/Carthage/issues/3019&quot;&gt;dependency manager Carthage&lt;/a&gt;.
Here&#39;s the issue:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When compiling for iOS hardware you would pick a target named &lt;code&gt;aarch64-apple-ios&lt;/code&gt;,
because ... iPhones and iPads are ARM-based since forever.&lt;/li&gt;
&lt;li&gt;When compiling for the iOS simulator you would pick a target named &lt;code&gt;x86_64-apple-ios&lt;/code&gt;,
because conveniently the simulator uses the host&#39;s CPU (that&#39;s what makes it fast)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So when the compiler saw &lt;code&gt;x86_64&lt;/code&gt; and &lt;code&gt;iOS&lt;/code&gt; it knew &quot;Ah, simulator target&quot;
and when it saw &lt;code&gt;aarch64&lt;/code&gt; and &lt;code&gt;ios&lt;/code&gt; it knew &quot;Ah, hardware&quot;.
And everyone went with this, Xcode happily built both targets and, if asked to, was able to bundle them into one package.&lt;/p&gt;
&lt;p&gt;With the introduction of Apple Silicion&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;
the iOS simulator run on these machines would &lt;em&gt;also&lt;/em&gt; be &lt;code&gt;aarch64&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;,
and also contain &lt;code&gt;ios&lt;/code&gt;, but not be for the iOS hardware.&lt;/p&gt;
&lt;p&gt;Now Xcode and the compiler will get confused what to put where when building on M1 hardware for both iOS hardware and the host architecture.&lt;/p&gt;
&lt;p&gt;So the compiler toolchain gained knowledge of a new thing: &lt;code&gt;arm64-apple-ios14.0-simulator&lt;/code&gt;,
explicitly marking the simulator target.
The compiler knows from where to pick the libraries and other SDK files when using that target.
You still can&#39;t put code compiled for &lt;code&gt;arm64-apple-ios&lt;/code&gt; and &lt;code&gt;arm64-apple-ios14.0-simulator&lt;/code&gt; into the same universal binary&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;,
because you can have each architecture only once (the &lt;code&gt;arm64&lt;/code&gt; part in there).
That&#39;s what Carthage and others stumbled over.&lt;/p&gt;
&lt;p&gt;Again Apple prepared for that and for a long time they have wanted you to use &lt;a href=&quot;https://developer.apple.com/documentation/swift_packages/distributing_binary_frameworks_as_swift_packages&quot;&gt;XCFramework bundles&lt;/a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-6-1&quot;&gt;&lt;a href=&quot;#fn-6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.
Carthage just didn&#39;t used to support that.
The &lt;a href=&quot;https://github.com/Carthage/Carthage/releases/tag/0.37.0&quot;&gt;0.37.0 release&lt;/a&gt; fixed that.&lt;/p&gt;
&lt;p&gt;That still leaves Rust behind, as it doesn&#39;t know the new &lt;code&gt;-simulator&lt;/code&gt; target.
But as always the Rust community is ahead of the game and &lt;a href=&quot;https://github.com/deg4uss3r&quot;&gt;deg4uss3r&lt;/a&gt; started adding a new target in &lt;a href=&quot;https://github.com/rust-lang/rust/pull/81966/&quot;&gt;Rust PR #81966&lt;/a&gt;.
He got half way there when I jumped in to push it over the finish line.
How these targets work and how LLVM picks the right things to put into the compiled artifacts is severly underdocumented,
so I had to go the trial-and-error route in combination with looking at LLVM source code to find the missing pieces.
Turns out: the &lt;code&gt;14.0&lt;/code&gt; in &lt;code&gt;arm64-apple-ios14.0-simulator&lt;/code&gt; is actually important.&lt;/p&gt;
&lt;p&gt;With the last missing piece in place, the new Rust target landed in February and is available in Nightly.
Contrary to the main &lt;code&gt;aarch64-apple-darwin&lt;/code&gt; or &lt;code&gt;aarch64-apple-ios&lt;/code&gt; target, the simulator target is not Tier 2 yet
and thus no prebuilt support is available.
&lt;code&gt;rustup target add aarch64-apple-darwin&lt;/code&gt; does &lt;em&gt;not&lt;/em&gt; work right now.
I am now in discussions to &lt;a href=&quot;https://github.com/rust-lang/rust/issues/82412&quot;&gt;promote it to Tier 2&lt;/a&gt;,
but it&#39;s currently blocked by the &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2803&quot;&gt;RFC: Target Tier Policy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It works on nightly however and in combination with another &lt;a href=&quot;https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std&quot;&gt;cargo capability&lt;/a&gt; I&#39;m able to build libraries for the M1 iOS simulator:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo +nightly build -Z build-std --target aarch64-apple-ios-sim
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For now Glean iOS development on an M1 is possible, but &lt;a href=&quot;https://github.com/mozilla/glean/pull/1498&quot;&gt;requires Nightly&lt;/a&gt;.
Goal achieved, I can actually work with this!&lt;/p&gt;
&lt;p&gt;In a future blog post I want to explain in more detail how to teach Xcode about all the different targets it should build native code for.&lt;/p&gt;
&lt;h2&gt;All The Other Projects&lt;/h2&gt;
&lt;p&gt;This was marked a stretch goal for a reason.
This involves all the other teams with Rust code and the iOS teams too.
We&#39;re not there yet and there&#39;s currently no explicit priority to make development of Firefox iOS on M1 hardware possible.
But when it comes to it, Glean will be ready for it and the team can assist others to get it over the finish line.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Want to hear more about Glean and our cross-platform Rust development?
Come to next week&#39;s &lt;a href=&quot;https://www.meetup.com/Rust-Linz/events/276521001/&quot;&gt;Rust Linz meetup&lt;/a&gt;, where I will be talking about this.&lt;/p&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;https://doc.rust-lang.org/nightly/rustc/platform-support.html&quot;&gt;Platform Support&lt;/a&gt; for what the Tiers means. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;The other name for that target. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;&quot;Apple Silicon&quot; is yet another name for what is essentially the same as &quot;M1&quot; or &quot;macOS aarch64&quot; &lt;a href=&quot;#fr-3-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;Or &lt;code&gt;arm64&lt;/code&gt; for that matter. Yes, yet another name for the same thing. &lt;a href=&quot;#fr-4-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary&quot;&gt;&quot;Universal Binaries&quot;&lt;/a&gt; have existed for a long time now and allow for one binary to include the compiled artifacts for multiple targets. It&#39;s how there&#39;s only one Firefox for Mac download which runs natively on either Mac platform. &lt;a href=&quot;#fr-5-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-6&quot;&gt;
&lt;p&gt;Yup, the main documentation they link to is a &lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2019/416/&quot;&gt;WWDC 2019 talk recording video&lt;/a&gt;. &lt;a href=&quot;#fr-6-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2021/04/16/rustc-ios-and-an-m1</guid>
      <pubDate>Fri, 16 Apr 2021 15:00:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Glean in 2021</title>
      <link>https://fnordig.de/2020/12/18/glean-in-2021</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)&lt;/p&gt;
&lt;p&gt;All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2020/12/18/this-week-in-glean-glean-in-2021/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;A year ago the Glean project was different.
We had just released &lt;a href=&quot;https://github.com/mozilla/glean/releases/tag/v22.1.0&quot;&gt;Glean v22.1.0&lt;/a&gt;
and &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/&quot;&gt;Fenix&lt;/a&gt; (aka Firefox for Android aka Firefox Daylight) was not released yet,
Project FOG was &lt;a href=&quot;https://chuttenblog.wordpress.com/2019/10/17/this-week-in-glean-glean-on-desktop-project-fog/&quot;&gt;just an idea&lt;/a&gt; for the year to come.&lt;/p&gt;
&lt;p&gt;2020 changed that, but 2020 changed a lot.
What didn&#39;t change was my main assignment: I kept working all throughout the year on the Glean SDK, fixing bugs, expanding its capabilities,
enabling more platforms and integrating it into more products.
Of course this was only possible because the whole team did that as well.&lt;/p&gt;
&lt;p&gt;In September I took over the tech lead role for the SDK from &lt;a href=&quot;https://twitter.com/dexterp37/&quot;&gt;Alessio&lt;/a&gt;.
One part of this role includes thinking bigger and sketching out the future for the Glean SDK.&lt;/p&gt;
&lt;p&gt;Let&#39;s look at this future and what ideas we have for 2021.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(One note: right now these are ideas more than a plan. It neither includes a timeline nor does it include all the other things maintenance includes.)&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;The vision&lt;/h2&gt;
&lt;p&gt;The Glean SDK is a fully self-servable telemetry SDK, usable across different platforms.
It enables product owners and engineers to instrument their products and rely on their data collection, while following Mozilla policies &amp;amp; privacy standards.&lt;/p&gt;
&lt;h2&gt;The ideas&lt;/h2&gt;
&lt;p&gt;In the past weeks I started a list of things I want the Glean SDK to do next.
This is a short and incomplete list of not-yet-proposed or accepted ideas.
For 2021 we will need to fit this in with the larger Glean project, including plans and ideas for the pipeline and tooling.
Oh, and I need to talk with my team to actually decide on the plan and allocate who does what when.&lt;/p&gt;
&lt;h3&gt;Metric types&lt;/h3&gt;
&lt;p&gt;When we set out to revamp our telemetry system we build it with the idea of offering higher-level metric types,
that give more meaning to individual data points, allowing more correct data collection and better aggregation, analysis and visualisation of this data.
We&#39;re not there yet.
We currently support &lt;a href=&quot;https://mozilla.github.io/glean/book/user/metrics/index.html&quot;&gt;more than a dozen metric types&lt;/a&gt; across all platforms equally,
with the same user-friendly APIs in all supported languages.
We also know that this still does not cover all intended use cases that, for example, Firefox Desktop wants.
In 2021 we will probably need to work on a few more types, better ergonomics and especially documentation on when which metric type is appropriate.&lt;/p&gt;
&lt;h3&gt;Revamped testing APIs&lt;/h3&gt;
&lt;p&gt;Engineers should instrument their code where appropriate and use the collected data to analysis behavior and performance in the wild.
The Glean SDK ensures their data is reliably collected and sent to our pipeline.
But we cannot ensure that the way the data is collected is correct or whether the metric even makes sense.
That&#39;s why we encourage that each metric recording is accompanied by tests to ensure data is collected under the right circumstances and that its the right data under the given test case.
Only that way folks will be able to verify and analyse the incoming data later and rely on their results.&lt;/p&gt;
&lt;p&gt;The available testing APIs in the Glean SDK provide a bare minimum.
For each metric type one can check which data it currently holds.
That&#39;s probably easy to validate for simpler metrics such as strings, booleans and counters,
but as soon as you have more complex one like any of the distributions or a timespan it gets a bit more complex.
Additionally we offer a way to check if any errors occured during recording, which are usually also reported in the data.
But here again developers need to know which errors can happen under what circumstances for which metric type.&lt;/p&gt;
&lt;p&gt;And at last we want developers to reach for &lt;a href=&quot;https://mozilla.github.io/glean/book/user/pings/custom.html&quot;&gt;custom pings&lt;/a&gt; when the default pings are not sufficient.
Testing these is currently near impossible.&lt;/p&gt;
&lt;p&gt;Testing these different usages of the SDK can and should be improved.
We already have the first proposals and bugs for this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.google.com/document/d/18JSwvz2HFDHfVB3MrJh_ON3gnMfTF-nHFxaBzXqPR_I/&quot;&gt;Custom Ping Unit Tests&lt;/a&gt; proposes a simple callback-like API to validate data in custom pings&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.google.com/document/d/1RrN3JoXVLMV5wwS56WXMqT35DhNfFkf5taRvU0WJlUA/&quot;&gt;Testing parameter in Glean metric definitions&lt;/a&gt; proposes to make existing tests/testing documentation for metrics more visible&lt;/li&gt;
&lt;li&gt;Improvements to Glinter, the Glean linter (e.g. &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1682980&quot;&gt;opinions on naming of things&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(Note: as of writing these document might be inaccessible to the wider public, but they will be made public once we gather wider feedback)&lt;/p&gt;
&lt;p&gt;For sure we will have more ideas on this in 2021.&lt;/p&gt;
&lt;h3&gt;UniFFI - generate all the code&lt;/h3&gt;
&lt;p&gt;The Glean SDK is cross-platform by shipping a core library written in Rust with language bindings on top that connect it with the target platform.
This has the advantage that most of the logic is written once and works across all the targets we have.
But this also has the downside that each language binding sort of duplicates the user-visible API in their target language again.
Currently all metric type implementations need to happen in Rust first, followed by implementations in the language bindings.&lt;/p&gt;
&lt;p&gt;All of the implementation work today is mostly manual, but usually follows the same approach.
The language binding implementations should not hold additional state, but currently some still do.&lt;/p&gt;
&lt;p&gt;Implementation of new metric types and fixing bugs or improving the recording APIs of existing ones results in a lot of busy work replicating the same code patterns in all the languages
(of which we now have have 7: Kotlin, Swift, Python, C#, Rust, JavaScript and C++).
If we also come up with new metric types next year this becomes worse.&lt;/p&gt;
&lt;p&gt;A while ago some of my colleagues started the &lt;a href=&quot;https://github.com/mozilla/uniffi-rs&quot;&gt;UniFFI&lt;/a&gt; project, a multi-language bindings generator for Rust.
For a couple of reasons the Glean SDK cannot rely on that yet.&lt;/p&gt;
&lt;p&gt;In 2021 I want us to work towards the goal of using UniFFI (or something like it) to reduce the manual work required on each language binding.
This should reduce our general workload supporting several languages and help us avoid accidental bugs on implementing (and maintaining) metric types.&lt;/p&gt;
&lt;p&gt;This is a rather short list of things that only focus on the SDK.
Let&#39;s see what we get tackled in 2021.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;End of 2020&lt;/h2&gt;
&lt;p&gt;The This Week in Glean series is going into winter hiatus until the second week of January 2021.
Thanks to everyone who contributed to 25 This Week in Glean blog posts in 2020:&lt;/p&gt;
&lt;p&gt;Alessio, Travis, Mike, Chutten, Bea, Raphael, Anthony, Will &amp;amp; Daosheng&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2020/12/18/glean-in-2021</guid>
      <pubDate>Fri, 18 Dec 2020 15:00:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: FOG progress report</title>
      <link>https://fnordig.de/2020/10/06/fog-progress-report</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)&lt;/p&gt;
&lt;p&gt;All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2020/10/06/this-week-in-glean-fog-progress-report/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;About a year ago chutten started the &quot;This Week in Glean&quot; series with an initial
&lt;a href=&quot;https://chuttenblog.wordpress.com/2019/10/17/this-week-in-glean-glean-on-desktop-project-fog/&quot;&gt;blog post about Glean on Desktop&lt;/a&gt;.
Back then we were just getting started to bring Glean to Firefox Desktop.
No code had been written for Firefox Desktop, no proposals had been written to discuss how we even do it.&lt;/p&gt;
&lt;p&gt;Now, 12 months later, after four completed milestones, a dozen or so proposal and quite a bit of code,
the Project Firefox on Glean (FOG) is finally getting into a stage where we can actually use and test it.
It&#39;s not ready for prime time yet, but FOG is enabled in Firefox Nightly already.&lt;/p&gt;
&lt;p&gt;Over the past 4 weeks I&#39;ve been on and off working on building out our support for a C++ and a JavaScript API.
Soon Firefox engineers will be able to instrument their code using Glean.
In C++ this will look like:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;mozilla::glean::test_only::count_something.Add(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;42&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;JavaScript developers will use it like this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Glean&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.test_only.count_something.&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;My work is done in &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1646165&quot;&gt;bug 1646165&lt;/a&gt;.
It&#39;s still under review and needs some fine-tuning before that, but I hope to land it by next week.
We will then gather some data from Nightly and validate that it works as expected (&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1651110&quot;&gt;bug 1651110&lt;/a&gt;),
before we let it ride the trains to land in stable (&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1651111&quot;&gt;bug 1651111&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Our work won&#39;t end there.
With my initial API work landing we can start supporting all metric types,
we still need to figure out some details of how FOG will handle IPC,
and then there&#39;s the whole process of convincing other people to use the new system.&lt;/p&gt;
&lt;p&gt;2020 will be the year of Glean on the Desktop.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2020/10/06/fog-progress-report</guid>
      <pubDate>Tue, 06 Oct 2020 16:00:00 +0200</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Leveraging Rust to build cross-platform mobile libraries</title>
      <link>https://fnordig.de/2020/09/01/leveraging-rust-to-build-cross-platform-mobile-libraries</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)&lt;/p&gt;
&lt;p&gt;All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2020/09/01/twig-leveraging-rust/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;A couple of weeks ago I gave a talk titled &lt;a href=&quot;https://www.youtube.com/watch?v=j5rczOF7pzg&quot;&gt;&quot;Leveraging Rust to build cross-platform mobile libraries&quot;&lt;/a&gt;.
You can find my &lt;a href=&quot;https://fnordig.de/talks/2020/rustydays/slides.pdf&quot;&gt;slides as a PDF&lt;/a&gt;.
It was part of the &lt;a href=&quot;https://rusty-days.org/&quot;&gt;Rusty Days&lt;/a&gt; Webference, an online conference that was initially planned to happen in Poland, but had to move online.
Definitely check out &lt;a href=&quot;https://www.youtube.com/watch?v=QaCvUKrxNLI&amp;amp;list=PLf3u8NhoEikhTC5radGrmmqdkOK-xMDoZ&quot;&gt;the other talks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One thing I wanted to achieve with that talk is putting that knowledge out there.
While multiple teams at Mozilla are already building cross-platform libraries, with a focus on mobile integration,
the available material and documentation is lacking.
I&#39;d like to see better guides online, and I probably have to start with what we have done.
But that should also be encouragement for those out there doing similar things to blog, tweet &amp;amp; speak about it.&lt;/p&gt;
&lt;h3&gt;Who else is using Rust to build cross-platform libraries, targetting mobile?&lt;/h3&gt;
&lt;p&gt;I&#39;d like to hear about it.
Find me on Twitter (&lt;a href=&quot;https://twitter.com/badboy_&quot;&gt;@badboy_&lt;/a&gt;) or drop me &lt;a href=&quot;mailto:janerik@fnordig.de&quot;&gt;an email&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The Glean SDK&lt;/h2&gt;
&lt;p&gt;I won&#39;t reiterate the full talk (&lt;a href=&quot;https://www.youtube.com/watch?v=j5rczOF7pzg&quot;&gt;go watch it&lt;/a&gt;, really!), so this is just a brief overview of the Glean SDK itself.&lt;/p&gt;
&lt;p&gt;The Glean SDK is our approach to build a modern Telemetry library, used in Mozilla&#39;s mobile products and soon in Firefox on Desktop as well.&lt;/p&gt;
&lt;p&gt;The SDK consists of multiple components, spanning multiple programming languages for different implementations.
All of the Glean SDK lives in the GitHub repository at &lt;a href=&quot;https://github.com/mozilla/glean&quot;&gt;mozilla/glean&lt;/a&gt;.
This is a rough diagram of the Glean SDK tech stack:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2020/glean-stack.png&quot; alt=&quot;Glean SDK Stack&quot; /&gt;&lt;/p&gt;
&lt;p&gt;On the very bottom we have &lt;code&gt;glean-core&lt;/code&gt;, a pure Rust library that is the heart of the SDK.
It&#39;s responsible for controlling the database, storing data and handling additional logic (e.g. assembling pings, clearing data, ..).
As it is pure Rust we can rely on all Rust tooling for its development.
We can write tests that &lt;code&gt;cargo test&lt;/code&gt; picks up. We can generate the full API documentation thanks to &lt;code&gt;rustdoc&lt;/code&gt;
and we rely on &lt;code&gt;clippy&lt;/code&gt; to tell us when our code is suboptimal.
Working on &lt;code&gt;glean-core&lt;/code&gt; should be possible for everyone that knows some Rust.&lt;/p&gt;
&lt;p&gt;On top of that sits &lt;code&gt;glean-ffi&lt;/code&gt;.
This is the FFI layer connecting &lt;code&gt;glean-core&lt;/code&gt; with everything else.
While glean-core is pure Rust, it doesn&#39;t actually provide the &lt;em&gt;nice API&lt;/em&gt; we intend for users of Glean.
That one is later implemented on top of it all.
glean-ffi doesn&#39;t contain much logic.
It&#39;s a translation between the proper Rust API of glean-core and C-compatible functions exposed into the dynamic library.
In it we rely on the excellent &lt;a href=&quot;https://docs.rs/ffi-support/&quot;&gt;&lt;code&gt;ffi-support&lt;/code&gt; crate&lt;/a&gt;.
ffi-support knows how to translate between Rust and C types, offers a nice (and safer) abstraction for C strings.
glean-ffi holds &lt;em&gt;some&lt;/em&gt; state: the instantiated global Glean object and metric objects.
We don&#39;t need to pass pointers back and forth. Instead we use opaque handles that index into a map held inside the FFI crate.&lt;/p&gt;
&lt;p&gt;The top layer of the Glean SDK are the different &lt;a href=&quot;https://mozilla.github.io/glean/book/dev/core/internal/implementations.html&quot;&gt;language implementations&lt;/a&gt;.
Language implementations expose a nice ergonomic API to initialize Glean and record metrics in the respective language.
Additionally each implementation handles some special cases for the platform they are running on, like gathering application and platform data or hooking into system events.
The nice API calls into the Glean SDK using the exposed FFI functions of &lt;code&gt;glean-ffi&lt;/code&gt;.
Unfortunately at the moment different language implementations carry different amounts of actual logic in them.
Sometimes metric implementations require this (e.g. we rely on the clock source of Kotlin for timing metrics),
in other parts we just didn&#39;t move the logic out of the implementations yet.
We&#39;re actively working on &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1651382&quot;&gt;moving logic into the Rust part where we can&lt;/a&gt; and might eventually use some code generation to unify the other parts.
&lt;a href=&quot;https://github.com/mozilla/uniffi-rs&quot;&gt;uniffi&lt;/a&gt; is a current experiment for a multi-language bindings generator for Rust we might end up using.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2020/09/01/leveraging-rust-to-build-cross-platform-mobile-libraries</guid>
      <pubDate>Tue, 01 Sep 2020 15:00:00 +0200</pubDate>
    </item>
    <item>
      <title>Build your project</title>
      <link>https://fnordig.de/2020/06/19/build-your-project</link>
      <description>&lt;p&gt;What if you could build a Rust project without Cargo?
It&#39;s not an actual problem I encountered.
It&#39;s still a problem I looked into.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Cargo is the Rust package manager.
Cargo downloads your Rust package’s dependencies, compiles your packages, makes distributable packages,
and uploads them to crates.io, the Rust community’s package registry.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(from the &lt;a href=&quot;https://doc.rust-lang.org/cargo/index.html&quot;&gt;Cargo Book&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&#39;s a lot of work this tool does and it&#39;s very good at doing it.&lt;/p&gt;
&lt;p&gt;I wanted to understand just the bit where it takes your Rust code and builds that into a binary that you can execute and run on your machine.
I didn&#39;t really want to read all of Cargo, so instead I turned to what Cargo itself tells me.
So I took the output of &lt;code&gt;cargo build --verbose&lt;/code&gt; and turned that into simple build instructions.&lt;/p&gt;
&lt;p&gt;What does it look like?&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ cargo build --verbose
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[...]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;   Compiling smallvec v1.4.0
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;   Compiling matches v0.1.8
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;   Compiling libc v0.2.71
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;     Running `rustc --crate-name smallvec --edition=2018 /Users/jer/.cargo/registry/src/github.com-1ecc6299db9ec823/smallvec-1.4.0/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts --crate-type lib --emit=dep-info,metadata,link -C debuginfo=2 -C metadata=d85954c5ff803feb -C extra-filename=-d85954c5ff803feb --out-dir /Users/jer/projects/rust/bygge/target/debug/deps -L dependency=/Users/jer/projects/rust/bygge/target/debug/deps --cap-lints allow`
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;     Running `rustc --crate-name libc /Users/jer/.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.71/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts --crate-type lib --emit=dep-info,metadata,link -C debuginfo=2 --cfg &amp;#39;feature=&amp;quot;default&amp;quot;&amp;#39; --cfg &amp;#39;feature=&amp;quot;std&amp;quot;&amp;#39; -C metadata=bbaef975a82234c8 -C extra-filename=-bbaef975a82234c8 --out-dir /Users/jer/projects/rust/bygge/target/debug/deps -L dependency=/Users/jer/projects/rust/bygge/target/debug/deps --cap-lints allow --cfg freebsd11 --cfg libc_priv_mod_use --cfg libc_union --cfg libc_const_size_of --cfg libc_align --cfg libc_core_cvoid --cfg libc_packedN`
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[...]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;     Running `rustc --crate-name bygge --edition=2018 src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=c1c12e33a54c5b24 -C extra-filename=-c1c12e33a54c5b24 --out-dir /Users/jer/projects/rust/bygge/target/debug/deps -C incremental=/Users/jer/projects/rust/bygge/target/debug/incremental -L dependency=/Users/jer/projects/rust/bygge/target/debug/deps --extern cargo_lock=/Users/jer/projects/rust/bygge/target/debug/deps/libcargo_lock-43ce509885ad1aff.rlib --extern cargo_toml=/Users/jer/projects/rust/bygge/target/debug/deps/libcargo_toml-5b6fff58e6c9a546.rlib --extern dirs=/Users/jer/projects/rust/bygge/target/debug/deps/libdirs-4eb870f2ccf6ed43.rlib --extern petgraph=/Users/jer/projects/rust/bygge/target/debug/deps/libpetgraph-7cb995dcfae4c1f7.rlib --extern pico_args=/Users/jer/projects/rust/bygge/target/debug/deps/libpico_args-03badf8072a773d9.rlib`
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    Finished dev [unoptimized + debuginfo] target(s) in 30.82s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I removed a bunch of the output, but it all boils down to the same.
You can re-run these commands and you should end up with the same binary as the one Cargo puts into &lt;code&gt;target/debug/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You could put them all in a Makefile and use that to re-run them, but you would have gained nothing.
Changing your own code or adding, removing or updating dependencies won&#39;t be picked up unless you carefully specify all these dependencies in the Makefile
and update them when something changes.&lt;/p&gt;
&lt;p&gt;We can automate that part.&lt;/p&gt;
&lt;p&gt;Lately (again) I&#39;ve been also reading about other build systems, such as &lt;a href=&quot;https://www.aosabook.org/en/posa/ninja.html&quot;&gt;Ninja&lt;/a&gt; and was intrigued to rebuild that.
I haven&#39;t done that yet, but I decided to generate Ninja configuration to see how it behaves.&lt;/p&gt;
&lt;p&gt;Let&#39;s combine these two things.&lt;/p&gt;
&lt;h2&gt;The basic manual version&lt;/h2&gt;
&lt;p&gt;Let&#39;s work from a basic binary crate, with no dependencies and a single file.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ cargo new --bin hello-world
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;     Created binary (application) `hello-world` package
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ cat
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;fn main() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    println!(&amp;quot;Hello, world!&amp;quot;);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Building just that is easy:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ rustc src/main.rs -o hello-world
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ ./hello-world
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Hello, world!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we rerun &lt;code&gt;rustc&lt;/code&gt; it will re-build the code and generate a new file &lt;code&gt;hello-world&lt;/code&gt; (that should be the same as the one from the first invocation).
That&#39;s a bit of extra work; if nothing changed we shouldn&#39;t need to rebuild.
Let&#39;s create a Ninja configuration file &lt;code&gt;build.ninja&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;# The build rule to invoke rustc.
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;# $in and $out are variables provided by ninja.
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;rule rustc
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  command = rustc $in -o $out
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  description = RUSTC $out
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;# Specifying dependencies:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;# For `hello-world` to be build we invoke the above `rustc` rule with `src/main.rs` as $in
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;build hello-world: rustc src/main.rs
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With &lt;a href=&quot;https://ninja-build.org/&quot;&gt;Ninja&lt;/a&gt; installed we can build and run this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ ninja
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[1/1] RUSTC hello-world
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ ./hello-world
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Hello, world!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Re-running Ninja won&#39;t build it again:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ ninja
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;ninja: no work to do.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ninja knows that nothing changed and thus skips extra work.
If we modify the source it rebuilds:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ echo &amp;gt;&amp;gt; src/main.rs
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ ninja
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[1/1] RUSTC hello-world
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ ./hello-world
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Hello, world!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We don&#39;t gain anything if we keep continuing writing a Ninja build configuration from hand.
Especially not once we add more files and some external crates.&lt;/p&gt;
&lt;h2&gt;Bygge - build your project&lt;/h2&gt;
&lt;p&gt;Instead of writing out the whole Ninja file,
or coming up with some rules for Make that expand to the right files,
we can generate the build configuration once and then not touch it again until something changes.
That&#39;s exactly what Ninja was designed for:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;it is designed to have its input files generated by a higher-level build system, [...]&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(from the &lt;a href=&quot;https://ninja-build.org/&quot;&gt;Ninja Website&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;After some more exploration with Cargo and the command lines it produces and the files it creates I managed to more-or-less auto-generate a Ninja configuration for a crate.&lt;/p&gt;
&lt;p&gt;I&#39;ve published this experiment as &lt;a href=&quot;https://github.com/badboy/bygge&quot;&gt;bygge&lt;/a&gt;, the crate to build your crates (and itself).&lt;/p&gt;
&lt;h3&gt;What it does&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;bygge create&lt;/code&gt; generates a Ninja build configuration (in &lt;code&gt;build.ninja&lt;/code&gt; by default),
listing all the targets a binary crate depends on, including all crate dependencies.
&lt;code&gt;ninja&lt;/code&gt; can then take this configuration and assemble the final binary.
The result should be about the same as an invocation of &lt;code&gt;cargo build&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;What it doesn&#39;t&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;bygge&lt;/code&gt; is and never will be an alternative to Cargo.
Cargo is a full-fledged build system, aware of different build targets, allowing to enable features per dependency,
easily cross-compile to different targets and run the built programs as well as tests and generate documentation.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bygge&lt;/code&gt; ... builds.&lt;/p&gt;
&lt;h3&gt;Features&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Builds cargo dependencies as listed in a project&#39;s Cargo.toml&lt;/li&gt;
&lt;li&gt;Can build only crates with a single binary target&lt;/li&gt;
&lt;li&gt;Runs on (at least) macOS and Linux&lt;/li&gt;
&lt;li&gt;No support for &lt;code&gt;build.rs&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;No support for linking non-Rust libraries&lt;/li&gt;
&lt;li&gt;Hard-coded Cargo features for its dependencies&lt;/li&gt;
&lt;li&gt;Uses &lt;code&gt;cargo fetch&lt;/code&gt; to download your project&#39;s dependencies&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Building bygge&lt;/h3&gt;
&lt;p&gt;Bygge is able to create a Ninja build configuration to build itself.
But first you need a compiled &lt;code&gt;bygge&lt;/code&gt;.
It comes with a pre-generated configuration for that, that only works on my machine unless you change the paths to the local checkouts of the dependencies.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ ninja -f manual.ninja
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[29/29] RUSTC build/bygge
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It builds a &lt;code&gt;build/bygge&lt;/code&gt; file that is able to create the build configuration and run Ninja:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ build/bygge create
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;==&amp;gt; Creating build file: build.ninja
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;==&amp;gt; Package: bygge
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ build/bygge build
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[29/29] RUSTC build/bygge
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ build/bygge -V
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;bygge v0.1.0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also build it using &lt;code&gt;cargo build&lt;/code&gt; and use &lt;code&gt;cargo run create&lt;/code&gt; (or &lt;code&gt;target/debug/bygge create&lt;/code&gt;) to create the &lt;code&gt;build.ninja&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;And there you have it: a 300-line Ninja build configuration to build bygge.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2020/06/19/build-your-project</guid>
      <pubDate>Fri, 19 Jun 2020 13:46:00 +0200</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Bytes in Memory (on Android)</title>
      <link>https://fnordig.de/2020/05/04/this-week-in-glean</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)&lt;/p&gt;
&lt;p&gt;Last week&#39;s blog post: &lt;a href=&quot;https://blog.mozilla.org/data/2020/04/27/this-week-in-glean-glean-for-python-on-windows/&quot;&gt;This Week in Glean: Glean for Python on Windows&lt;/a&gt;
by Mike Droettboom.
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2020/05/04/this-week-in-glean-bytes-in-memory-on-android/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;With the Glean SDK we follow in the footsteps of &lt;a href=&quot;https://github.com/mozilla/application-services&quot;&gt;other teams&lt;/a&gt; to build a cross-platform library to be used in both mobile and desktop applications alike.
In this blog post we&#39;re taking a look at how we transport some rich data across the FFI boundary to be reused on the Kotlin side of things.
We&#39;re using a recent example of a new API in Glean that will &lt;a href=&quot;https://github.com/mozilla/glean/blob/8e0599b4df6c1a08f985e4ad5328fcf81a56a084/docs/dev/core/internal/upload.md&quot;&gt;drive the HTTP upload of pings&lt;/a&gt;,
but the concepts I&#39;m explaining here apply more generally.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; This blog post is not a good introduction on doing Rust on Android, but I do plan to write about that in the future as well.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Most of this implementation was done by &lt;a href=&quot;https://brizental.github.io/&quot;&gt;Bea&lt;/a&gt; and I have been merely a reviewer,
around for questions and currently responsible for running final tests on this feature.&lt;/p&gt;
&lt;h2&gt;The problem&lt;/h2&gt;
&lt;p&gt;The Glean SDK provides an &lt;a href=&quot;https://github.com/mozilla/glean/tree/master/glean-core/ffi&quot;&gt;FFI API&lt;/a&gt; that can be consumed by what we call language bindings.
For the most part we pass &lt;abbr title=&quot;Plain Old Data&quot;&gt;POD&lt;/abbr&gt; over that API boundary:
integers of various sizes (a problem in and of itself if the sides disagree about certain integer sizes and signedness),
bools (but actually encoded as an 8-bit integer&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;),
but also strings as pointers to null-terminated UTF-8 strings in memory (for test APIs we encode data into JSON and pass that over as strings).&lt;/p&gt;
&lt;p&gt;However for some internal mechanisms we needed to communicate a bit more data back and forth.
We wanted to have different &lt;em&gt;tasks&lt;/em&gt;, where each task variant could have additional data.
Luckily this additional data is either some integers or a bunch of strings only and not further nested data.&lt;/p&gt;
&lt;p&gt;So this is the data we have on the Rust side:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;enum &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Task {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    Upload(Request),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    Wait,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    Done,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;struct &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Request {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    id: String,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    url: String,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(This code is simplified for the sake of this blog post.
You can find the full code online &lt;a href=&quot;https://github.com/mozilla/glean/blob/8e0599b4df6c1a08f985e4ad5328fcf81a56a084/glean-core/src/upload/mod.rs#L38-L48&quot;&gt;in the Glean repository&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;And this is the API a user would call:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;get_next_task&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() -&amp;gt; Task
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;The solution&lt;/h2&gt;
&lt;p&gt;Before we can expose a task through FFI we need to transform it into something C-compatible:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::os::raw::&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;c_char&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[repr(u8)]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub enum &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    Upload {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        id: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;*mut c_char&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        url: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;*mut c_char&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    Wait,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    Done,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We define a new enum that&#39;s going to be represent its variant as an 8-bit integer plus the additional data for &lt;code&gt;Upload&lt;/code&gt;.
The other variants stay data-less.&lt;/p&gt;
&lt;p&gt;We also provide conversion from the proper Rust type to the FFI-compatible type:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;From&amp;lt;Task&amp;gt; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;for &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(task: Task) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;Self &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; task {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            Task::Upload(request) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;CString::new(request.id).&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; url &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;CString::new(request.url).&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                FfiTask::Upload {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                    id: document_id.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;into_raw&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                    url: path.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;into_raw&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            Task::Wait &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask::Wait,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            Task::Done &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask::Done,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The FFI API becomes:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[no_mangle]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;extern &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;C&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;glean_get_next_task&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() -&amp;gt; FfiTask
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this all set we can throw &lt;a href=&quot;https://github.com/eqrion/cbindgen&quot;&gt;cbindgen&lt;/a&gt; at our code to generate the C header, which will produce this snippet of code:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;enum &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask_Tag {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  FfiTask_Upload,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  FfiTask_Wait,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  FfiTask_Done,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;};
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;typedef &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;uint8_t &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask_Tag;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;typedef struct &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  FfiTask_Tag tag;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;char *&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;id;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;char *&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;url;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;} FfiTask_Upload_Body;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;typedef union &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  FfiTask_Tag tag;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  FfiTask_Upload_Body upload;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;} FfiTask;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the C representation of a &lt;a href=&quot;https://en.wikipedia.org/wiki/Tagged_union&quot;&gt;tagged union&lt;/a&gt;.
The layout of these tagged unions has been formally defined in &lt;a href=&quot;https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md&quot;&gt;Rust RFC 2195&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Each variant&#39;s first element is the &lt;code&gt;tag&lt;/code&gt;, allowing us to identify which variant we have.
cbindgen automatically inlined the &lt;code&gt;Wait&lt;/code&gt; and &lt;code&gt;Done&lt;/code&gt; variants: they are nothing more than a &lt;code&gt;tag&lt;/code&gt;.
The &lt;code&gt;Upload&lt;/code&gt; variant however gets its own struct.&lt;/p&gt;
&lt;p&gt;On the Kotlin side of things we use &lt;a href=&quot;https://github.com/java-native-access/jna&quot;&gt;JNA (Java Native Access)&lt;/a&gt; to call C-like functions and interact with C types.
After some research by Bea we found that it already provides abstractions over C unions and structs
and we could implement the equivalent parts for our &lt;code&gt;Task&lt;/code&gt; in Kotlin.&lt;/p&gt;
&lt;p&gt;First some imports and replicating the variants our tag takes.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;import &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;com.sun.jna.Structure
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;import &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;com.sun.jna.Pointer
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;import &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;com.sun.jna.Union
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;enum &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;class TaskTag &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Upload&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Wait&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Done
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next is the body of our &lt;code&gt;Upload&lt;/code&gt; variant. It&#39;s a structure with two pointers to strings.
Kotlin requires some annotations to specify the order of fields in memory.
We also  inherit from &lt;code&gt;Structure&lt;/code&gt;, a class provided by JNA, that will take care of reading from memory and making the data accessible in Kotlin.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;@Structure.FieldOrder(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;tag&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;UploadBody&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    @&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;JvmField&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; val tag&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Byte &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;TaskTag.Done&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.ordinal.toByte(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    @&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;JvmField&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; val id&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Pointer&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;? = &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    @&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;JvmField&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; val url&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Pointer&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;? = &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Structure() { }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And at last we define our union.
We don&#39;t need a field order, it&#39;s a union afterall, only one of the fields is valid at a time.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;open &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;FfiTask&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    @&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;JvmField&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; var tag&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Byte &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;TaskTag.Done&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.ordinal.toByte(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    @&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;JvmField&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; var upload&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;UploadBody &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;UploadBody()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Union() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    class &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;ByValue &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask(), &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Structure.ByValue
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    fun toTask()&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        this.readField(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;tag&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;when (this.tag.toInt()) {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;TaskTag.Upload&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.ordinal &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                this.readField(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;upload&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                val request &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Request(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                    this.upload.id.getRustString(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                    this.upload.url.getRustString()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                )
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task.Upload&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(request)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;TaskTag.Wait&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.ordinal &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task.Wait
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            else &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task.Done
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This also defines the conversion to a new Kotlin type that eases usage on the Kotlin side.
&lt;code&gt;getRustString&lt;/code&gt; is a &lt;a href=&quot;https://github.com/mozilla/glean/blob/da1e014e378660f243b92ce6012b7b29188d72d8/glean-core/android/src/main/java/mozilla/telemetry/glean/rust/LibGleanFFI.kt#L40-L42&quot;&gt;small helper&lt;/a&gt;
to copy the null-terminated C-like string to a Kotlin string.&lt;/p&gt;
&lt;p&gt;The FFI function on the Kotlin side is defined as:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;fun glean_get_next_task()&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;FfiTask.ByValue
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The types we convert to and then work with in Kotlin are small classes around the data.
If there&#39;s no attached data it&#39;s an object.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Request&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    val id&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    val url&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) { }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;sealed &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Upload&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(val request: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Request&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) : &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;Task&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    object &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Wait&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;Task&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    object &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Done&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;Task&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As the final piece of this code on the Kotlin side we can now fetch new tasks, convert it to more convenient Kotlin objects and work with them:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;val incomingTask &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;LibGleanFFI.INSTANCE&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.glean_get_next_task()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;when (val action &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; incomingTask.toTask()) {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    is &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task.Upload &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;upload(action.request.id, action.request.url)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task.Wait &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&amp;gt; return &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Result&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.retry()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task.Done &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&amp;gt; return &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Result&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.success()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;What&#39;s next?&lt;/h2&gt;
&lt;p&gt;Currently our new upload mechanism is under testing.
We&#39;re reasonably sure that our approach of passing rich data across the FFI boundary is sound and not causing memory safety issues for now.&lt;/p&gt;
&lt;p&gt;The advantage of going the way of encoding Rust enums into tagged unions for us is that we can use this API in all our current API consumers.
C structs and unions are supported in Kotlin (for Android), Swift (for our iOS users) and Python (e.g. Desktop apps such as &lt;a href=&quot;https://wlach.github.io/blog/2020/04/mozregression-for-macos/&quot;&gt;mozregression&lt;/a&gt;).
It didn&#39;t require new tooling or dependencies to get it working and it&#39;s reasonably cheap in terms of processing cost (it&#39;s copying around a few bytes of data in memory).&lt;/p&gt;
&lt;p&gt;The disadvantage however is that it requires quite a bit of coordination of the different pieces of code.
As you&#39;ve seen above for Kotlin we need to be careful to replicate the exact layout of data and all of this is (currently) hand-written.
Any change on the Rust side might break this easily.
Swift is a bit easier on this front as it has direct C translation.&lt;/p&gt;
&lt;p&gt;The application-services team faced the same problem of how to transport rich data across the FFI boundary.
They decided to go with protocol buffers and generate code for both sides of the FFI. They wrote about it in &lt;a href=&quot;https://hacks.mozilla.org/2019/04/crossing-the-rust-ffi-frontier-with-protocol-buffers/&quot;&gt;Crossing the Rust FFI frontier with Protocol Buffers&lt;/a&gt;.
We decided against this way (for now), as it requires a bit more of a heavy-handed setup initially.
We might reconsider this if we need to expand this API further.&lt;/p&gt;
&lt;p&gt;My dream solution is still a &lt;code&gt;*-bindgen&lt;/code&gt; crate akin to &lt;a href=&quot;https://crates.io/crates/wasm-bindgen&quot;&gt;wasm-bindgen&lt;/a&gt; that creates all this code.&lt;/p&gt;
&lt;br&gt;
&lt;hr /&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Don&#39;t use a bool with JNA. JNA doesn&#39;t handle it well and has its own conception of the size of a bool that differs from what C and Rust think. See &lt;a href=&quot;https://mozilla.github.io/glean/book/dev/ffi/when-to-use-what-in-the-ffi.html#primitives&quot;&gt;When to use what method of passing data between Rust and Java/Swift&lt;/a&gt; in the Glean SDK book. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2020/05/04/this-week-in-glean</guid>
      <pubDate>Mon, 04 May 2020 15:30:00 +0200</pubDate>
    </item>
    <item>
      <title>Rust in an instant</title>
      <link>https://fnordig.de/2020/05/02/rust-in-an-instant</link>
      <description>&lt;p&gt;So I &lt;a href=&quot;https://twitter.com/badboy_/status/1255802731241050112&quot;&gt;tweeted&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This happened in an instant.
I am not even sorry.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It included this snippet of Rust code:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::os::raw::{&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;c_int&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;c_void&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;};
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::sync::atomic::{AtomicU64, Ordering::SeqCst};
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::time::Instant;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[repr(C)]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;struct &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;timespec {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    tv_sec: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    tv_nsec: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;static &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;TIME_COUNTER&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: AtomicU64 &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;AtomicU64::new(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[no_mangle]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;extern &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;C&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;clock_gettime&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(clk_id: *&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; c_void, tp: *&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; timespec) -&amp;gt; c_int {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;unsafe &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; next_tick &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;TIME_COUNTER&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;fetch_add&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, SeqCst);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        (&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;tp).tv_sec &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; next_tick;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        (&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;tp).tv_nsec &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Instant::now();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; b &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Instant::now();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; diff &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; b.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;duration_since&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(a);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    println!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;{:?}&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, diff);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(&lt;a href=&quot;https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=37b788bbf396aed5ffdaf765ba76a780&quot;&gt;Playground link&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;And I was then asked what that piece of code does:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;@varjmes: what am i seeing here? started reading the rust book yesterday :)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(&lt;a href=&quot;https://twitter.com/varjmes/status/1255803145013342208&quot;&gt;Tweet&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;So let me explain.&lt;/p&gt;
&lt;p&gt;First let&#39;s take this from a tweet-worthy piece of code to be more production ready with cross-platform support.
I&#39;m on macOS most of the day. Let&#39;s add support for it:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[cfg(all(unix, not(target_os &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;macos&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)))]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::os::raw::{&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;c_int&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;c_void&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;};
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::sync::atomic::{AtomicU64, Ordering::SeqCst};
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::time::Instant;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[cfg(all(unix, not(target_os &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;macos&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)))]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[repr(C)]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;struct &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;timespec {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    tv_sec: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    tv_nsec: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;static &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;TIME_COUNTER&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: AtomicU64 &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;AtomicU64::new(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[cfg(all(unix, not(target_os &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;macos&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)))]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[no_mangle]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;extern &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;C&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;clock_gettime&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(_clk_id: *&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; c_void, tp: *&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; timespec) -&amp;gt; c_int {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;unsafe &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; next_tick &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;TIME_COUNTER&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;fetch_add&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, SeqCst);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        (&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;tp).tv_sec &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; next_tick;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        (&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;tp).tv_nsec &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[cfg(target_os &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;macos&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[no_mangle]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;extern &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;C&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;mach_absolute_time&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() -&amp;gt; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u64 &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;const &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;NANOSECONDS_IN_A_SECOND&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u64 = &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1_000_000_000&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;TIME_COUNTER&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;fetch_add&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, SeqCst) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;* &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;NANOSECONDS_IN_A_SECOND
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Instant::now();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; b &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Instant::now();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; diff &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; b.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;duration_since&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(a);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    println!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;{:?}&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, diff);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can compile that:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;rustc instant.rs
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then run it:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;gt; ./instant
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;1s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What is happening here?&lt;/p&gt;
&lt;h2&gt;Time is an illusion&lt;/h2&gt;
&lt;p&gt;Computers provide clock sources that allow a program to make assumptions about time passed.
If all you need is measure the time passed between some instant &lt;code&gt;a&lt;/code&gt; and instant &lt;code&gt;b&lt;/code&gt; the Rust libstd provides you with &lt;a href=&quot;https://doc.rust-lang.org/std/time/struct.Instant.html&quot;&gt;Instant&lt;/a&gt;, a measurement of a monotonically nondecreasing clock
(I&#39;m sorry to inform you that guarantees about &lt;a href=&quot;https://github.com/rust-lang/rust/blob/08dfbfb61871a83f720c6e97a3b737076e89fe3e/src/libstd/time.rs#L205-L232&quot;&gt;monotonically increasing clocks are lacking&lt;/a&gt;).
&lt;code&gt;Instant&lt;/code&gt;s are an opaque thing and only good for getting you the difference between two of them, resulting in a &lt;a href=&quot;https://doc.rust-lang.org/std/time/struct.Duration.html&quot;&gt;Duration&lt;/a&gt;.
Good enough if you can rely on the operating system to not lie to you.&lt;/p&gt;
&lt;p&gt;How is &lt;code&gt;Instant&lt;/code&gt; implemented?
That depends on the operating system your running your code on.
Luckily the documentation lists the (currently) used system calls to get time information.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Platform[^1]&lt;/th&gt;&lt;th&gt;System Call&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;UNIX&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://linux.die.net/man/3/clock_gettime&quot;&gt;&lt;code&gt;clock_gettime&lt;/code&gt;&lt;/a&gt; (Monotonic Clock)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Darwin&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;&quot;&gt;&lt;code&gt;mach_absolute_time&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;([^1]: Trimmed down to the platforms I work on.)&lt;/p&gt;
&lt;p&gt;So that&#39;s where Rust gets its time from.&lt;/p&gt;
&lt;h2&gt;The operating system is an illusion&lt;/h2&gt;
&lt;p&gt;But how do we replace operating system functionality?
Turns out functions are merely a name and the linker tries to figure out where the code behind them is and then points to that.&lt;/p&gt;
&lt;p&gt;If we look at a simpler version of our code without any &lt;code&gt;#[no_mangle] extern &quot;C&quot;&lt;/code&gt; functions we can see where these come from:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(macOS) ❯ nm -a ./instant | rg mach_absolute_time
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                 U _mach_absolute_time
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(linux) ❯ nm -a instant | rg clock_gettime
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                 U clock_gettime@@GLIBC_2.17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;nm&lt;/code&gt; lists symbols from object files.
That &lt;code&gt;U&lt;/code&gt; right there stands for &lt;em&gt;undefined&lt;/em&gt;: The binary doesn&#39;t have knowledge where it comes from
(though in the case of Linux it gave it a slightly different name letting us guess what to expect).
Details about this symbol are later filled in, once your program is loaded and symbols to dynamic libaries are resolved
(and I&#39;m sure the &lt;a href=&quot;https://fasterthanli.me/blog/2020/whats-in-a-linux-executable/&quot;&gt;&quot;Making our own executable packer&quot; series&lt;/a&gt; by &lt;a href=&quot;https://twitter.com/fasterthanlime&quot;&gt;@fasterthanlime&lt;/a&gt; will have lots more details on it, I should go read it).&lt;/p&gt;
&lt;p&gt;What if we do that work before even running the program?&lt;/p&gt;
&lt;h2&gt;Strings are strings, no matter what order&lt;/h2&gt;
&lt;p&gt;So now let&#39;s try to expose a function under the same name from our code.&lt;br /&gt;
&lt;em&gt;Note: I&#39;m only doing the macOS part here, it works the same for Linux.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If we start with the plain function like this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;mach_absolute_time&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() -&amp;gt; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u64 &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;it will not turn up in the final binary at all and &lt;code&gt;rustc&lt;/code&gt; right fully complains:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;warning: function is never used: `mach_absolute_time`
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Even making it &lt;code&gt;pub&lt;/code&gt; won&#39;t work.
By default symbols such as function names get &lt;em&gt;mangled&lt;/em&gt;; some additional information is encoded into the name as well and at the same time this ensures uniqueness of names
(see also &lt;a href=&quot;https://en.wikipedia.org/wiki/Name_mangling&quot;&gt;Name Mangling&lt;/a&gt;).
One can disable that in Rust using the &lt;code&gt;#[no_mangle]&lt;/code&gt; attribute. So we apply that.&lt;/p&gt;
&lt;p&gt;We&#39;re trying to override a function that is defined in terms of C.
C has slightly different calling conventions than Rust.
It&#39;s part of their respective ABIs: how data is passed in and out of functions.
In Rust one can define the used ABI with the &lt;code&gt;extern &quot;name&quot;&lt;/code&gt; tag.
So we add that.&lt;/p&gt;
&lt;p&gt;And thus we end up with&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[no_mangle]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;extern &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;C&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;mach_absolute_time&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() -&amp;gt; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u64 &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we compile our code again and look at the symbols we get this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(macOS) ❯ nm -a ./instant | rg mach_absolute_time
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0000000100000c20 T _mach_absolute_time
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(linux) ❯ nm -a instant | rg clock_gettime
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0000000000005250 T clock_gettime
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we know that the symbol is defined somewhere in the binary (&quot;T - The symbol is in the text (code) section.&quot;)
and also the location (&lt;em&gt;0000000100000c20&lt;/em&gt; / &lt;em&gt;0000000000005250&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;If this program is run it will still need to resolve undefined symbols ... but this time our functions are not undefined anymore.
As the stdlib just calls whatever is behind that respective name it now calls our code instead!&lt;/p&gt;
&lt;p&gt;And yes, this works for pretty much all the functions defined by other libraries or libc:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::fs::File;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::os::raw::{&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;c_char&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;c_int&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;};
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[no_mangle]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;extern &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;C&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;open&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(_path: *&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; c_char, _flag: c_int) -&amp;gt; c_int {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    File::open(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;/etc/passwd&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;❯ rustc file.rs
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;❯ ./file
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;thread &amp;#39;main&amp;#39; panicked at &amp;#39;called `Result::unwrap()` on an `Err` value: Os { code: 0, kind: Other, message: &amp;quot;Undefined error: 0&amp;quot; }&amp;#39;, file.rs:10:5
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Please don&#39;t do this.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;If you liked this you might also like &lt;a href=&quot;https://github.com/badboy/stdshout&quot;&gt;STDSHOUT!!!1!&lt;/a&gt;, I even &lt;a href=&quot;https://www.youtube.com/watch?v=YF6-g4YkyNY&quot;&gt;gave a talk about it&lt;/a&gt;.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2020/05/02/rust-in-an-instant</guid>
      <pubDate>Sat, 02 May 2020 14:43:00 +0200</pubDate>
    </item>
    <item>
      <title>&quot;Edit this file on GitHub&quot;</title>
      <link>https://fnordig.de/2020/02/06/edit-this-file-on-github</link>
      <description>&lt;p&gt;At work I help with maintaining two large documentation books:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.telemetry.mozilla.org/&quot;&gt;Firefox Data Docs&lt;/a&gt; aka docs.telemetry.mozilla.org aka dtmo&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mozilla.github.io/glean/book/index.html&quot;&gt;The Glean SDK book&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Back in 2018 I migrated dtmo from gitbook to &lt;a href=&quot;https://github.com/rust-lang/mdBook&quot;&gt;mdbook&lt;/a&gt; (see &lt;a href=&quot;https://github.com/mozilla/firefox-data-docs/pull/187&quot;&gt;the pull request&lt;/a&gt;).
mdbook is maintained by the Rust project and hosts the &lt;a href=&quot;https://doc.rust-lang.org/book/&quot;&gt;Rust book&lt;/a&gt; as well as a multitude of other community projects.
It provided all we need, plus a way to extend it with some small things, I blogged about &lt;a href=&quot;http://localhost:8000/2019/07/11/mdbook-toc-and-mermaid-preprocessors/&quot;&gt;ToC and mermaid&lt;/a&gt; before.&lt;/p&gt;
&lt;p&gt;During the Mozilla All Hands last week my colleague Mike casually asked why we don&#39;t have links to quickly edit the documentation.
When someone discovers a mistake or inaccuracy in the book the current process involves finding the repository of the book, then finding the right file, then edit that file (through the GitHub UI or by cloning the repository),
then push changes, open a pull request, wait for review and finally get it merged and deployed.&lt;/p&gt;
&lt;p&gt;I immediately set out to build this feature.&lt;/p&gt;
&lt;p&gt;I present to you: &lt;strong&gt;&lt;a href=&quot;https://github.com/badboy/mdbook-open-on-gh/&quot;&gt;mdbook-open-on-gh&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It&#39;s another preprocessor for mdbook, that adds a link to the edit dialog on GitHub (if your book is actually hosted on GitHub).
And that&#39;s how it looks:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2020/open-on-gh-gleanbook.png&quot; alt=&quot;Screenshot of a Glean SDK book site showing the &amp;quot;Edit this file on GitHub&amp;quot; link&quot; /&gt;&lt;/p&gt;
&lt;p&gt;It&#39;s already deployed on dtmo and the Glean SDK book and simplifies the workflow to: click the link, edit the file on GitHub, commit and open a PR, get a review and merge it to deploy.&lt;/p&gt;
&lt;p&gt;If you want to use this preprocessor, install it:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo install mdbook-open-on-gh
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add it as a preprocessor to your &lt;code&gt;book.toml&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[preprocessor.open-on-gh]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;command = &amp;quot;mdbook-open-on-gh&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;renderer = [&amp;quot;html&amp;quot;]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add a repository URL to use as a base in your &lt;code&gt;book.toml&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[output.html]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;git-repository-url = &amp;quot;https://github.com/mozilla/glean&amp;quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To style the footer add a custom CSS file for your HTML output:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[output.html]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;additional-css = [&amp;quot;open-in.css&amp;quot;]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And in &lt;code&gt;open-in.css&lt;/code&gt; style the &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt; element or directly the CSS element id &lt;code&gt;open-on-gh&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;footer &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;font-size&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0.8&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;em&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;text-align&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: center;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;border-top&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;px &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;solid black;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;padding&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;px &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This code block shrinks the text size, center-aligns it under the rest of the content
and adds a small horizontal bar above the text to separate it from the page content.&lt;/p&gt;
&lt;p&gt;Finally, build your book as normal:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;mdbook path/to/book
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</description>
      <guid>https://fnordig.de/2020/02/06/edit-this-file-on-github</guid>
      <pubDate>Thu, 06 Feb 2020 16:38:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Cargo features - an investigation</title>
      <link>https://fnordig.de/2020/02/03/this-week-in-glean</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean. You can find an &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;index of all TWiG posts online&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;The last blog post: &lt;a href=&quot;https://brizental.github.io/2020/01/10/this-week-in-glean-glossary.html&quot;&gt;This Week in Glean: Glossary&lt;/a&gt; by Bea.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;As :chutten outlined in the first &lt;a href=&quot;https://chuttenblog.wordpress.com/2019/10/17/this-week-in-glean-glean-on-desktop-project-fog/&quot;&gt;TWiG blog post&lt;/a&gt; we&#39;re currently prototyping Glean on Desktop.
After a couple rounds of review, some adjustements and some learnings from doing Rust on mozilla-central, we were ready to land the first working prototype code earlier this year (&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1591564#c25&quot;&gt;Bug 1591564&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Unfortunately the patch set was &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1591564#c27&quot;&gt;backed out nearly immediately&lt;/a&gt; &lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; for 2 failures.
The first one was a &quot;leak&quot; (we missed cleaning up memory in a way to satisfy the rigorous Firefox test suite, that was fixed in &lt;a href=&quot;https://phabricator.services.mozilla.com/D59531&quot;&gt;another patch&lt;/a&gt;).
The second one was a build failure on a Windows platform.&lt;/p&gt;
&lt;p&gt;This is what the log had to say about it (shortened to the relevant parts here, &lt;a href=&quot;https://treeherder.mozilla.org/logviewer.html#/jobs?job_id=283842210&amp;amp;repo=autoland&amp;amp;lineNumber=93915&quot;&gt;see the full log output&lt;/a&gt;):&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;lld-link: error: undefined symbol: __rbt_backtrace_pcinfo
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; referenced by gkrust_gtest.lib(backtrace-5286ea09b9822175.backtrace.3kzojw1m-cgu.3.rcgu.o)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;lld-link: error: undefined symbol: __rbt_backtrace_create_state
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; referenced by gkrust_gtest.lib(backtrace-5286ea09b9822175.backtrace.3kzojw1m-cgu.3.rcgu.o)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;lld-link: error: undefined symbol: __rbt_backtrace_syminfo
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; referenced by gkrust_gtest.lib(backtrace-5286ea09b9822175.backtrace.3kzojw1m-cgu.3.rcgu.o)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;clang-9: error: linker command failed with exit code 1 (use -v to see invocation)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;/builds/worker/workspace/build/src/config/rules.mk:608: recipe for target &amp;#39;xul.dll&amp;#39; failed]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I set out to investigate this error.
While I had not seen that particular error before, I knew about the &lt;a href=&quot;https://docs.rs/backtrace/0.3.43/backtrace/&quot;&gt;&lt;code&gt;backtrace&lt;/code&gt;&lt;/a&gt; crate. It caused me some trouble before (it depends on a C library, and won&#39;t work on all targets easily).
I knew that the Glean SDK doesn&#39;t really depend on its functionality&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; and thus removing it from our dependency graph would probably solve the issue.
But first I had to find out why we depend on it somewhere and why it is causing these linker errors to begin with.&lt;/p&gt;
&lt;p&gt;The first thing I noticed is that we didn&#39;t include anything new in the patch set that was now rejected.
Through some experimentation and use &lt;a href=&quot;https://crates.io/crates/cargo-tree&quot;&gt;&lt;code&gt;cargo-tree&lt;/code&gt;&lt;/a&gt; I could tell that &lt;code&gt;backtrace&lt;/code&gt; was included in the build before our Glean patch&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, as a transitive dependency of another crate: &lt;a href=&quot;https://docs.rs/failure/0.1.6/failure/&quot;&gt;&lt;code&gt;failure&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So why didn&#39;t it fail the build before?
As per the errors above, the build failed only during linking, not compilation, which makes me believe those functions were never linked in previously, because no one passed around any errors that would cause these functions to be used.&lt;/p&gt;
&lt;p&gt;As said before, the Glean SDK doesn&#39;t really need failure&#39;s backtrace feature, so I tried disabling its default features.
Due to how cargo currently works, this needs to be done across all transitive dependencies (the final feature set a crate is compiled with is the union across everything).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mozilla/application-services/pull/2448&quot;&gt;Disabling it in ffi-support in application-services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mozilla/glean/commit/eed8f16f6afdbf8599301bf1a95d745c1eeab4b9&quot;&gt;Disabling it in Glean (and depending on that changed ffi-support&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I then changed mozilla-central to use the crates from git directly for testing.&lt;/p&gt;
&lt;p&gt;Turns out that still fails with the same issue on the Windows target.
Something was re-enabling the &quot;std&quot; feature of &lt;code&gt;failure&lt;/code&gt; in tree.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://crates.io/crates/cargo-feature-set&quot;&gt;&lt;code&gt;cargo-feature-set&lt;/code&gt;&lt;/a&gt; was able to show me all enabled features for all dependencies I tracked it down further&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Turns out the &lt;code&gt;quantum_render&lt;/code&gt; feature enables the &lt;a href=&quot;https://searchfox.org/mozilla-central/source/gfx/webrender_bindings/&quot;&gt;webrender_bindings&lt;/a&gt; crate,
which then somehow pulls in &lt;code&gt;failure&lt;/code&gt; through transitive dependencies again.
More trial-and-error revealed its a dependency of &lt;a href=&quot;https://searchfox.org/mozilla-central/rev/a92ed79b0bc746159fc31af1586adbfa9e45e264/gfx/webrender_bindings/Cargo.toml#31&quot;&gt;the dirs crate&lt;/a&gt;, only used on Windows.
Except dirs doesn&#39;t &lt;em&gt;need&lt;/em&gt; &lt;code&gt;failure&lt;/code&gt; for the target we&#39;re building for (&lt;code&gt;x86_64-pc-windows-gnu&lt;/code&gt; or Mac or Linux).
It&#39;s again a transitive dependency for a crate called &lt;code&gt;redox_users&lt;/code&gt;, which is &lt;a href=&quot;https://github.com/soc/dirs-rs/blob/3c3b61ff9611762bece3fc66fd6612b125819e3f/Cargo.toml#L15-L16&quot;&gt;only pulled in when compiled for Redox&lt;/a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Except that&#39;s not how Cargo works.
Cargo always pulls in all dependencies, merges all features and only later ignores the crates it doesn&#39;t actually need.
That&#39;s a long standing issue:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rust-lang/cargo/issues/1796&quot;&gt;cargo#1796&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rust-lang/cargo/issues/2589&quot;&gt;cargo#2589&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rust-lang/cargo/issues/4361&quot;&gt;cargo#4361&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So now we identified who&#39;s pulling in the backtrace crate and maybe even identified why it was not a problem before.
How do we fix this?&lt;/p&gt;
&lt;p&gt;As shown before, just disabling the backtrace feature in crates we use directly doesn&#39;t solve it, so one quick workaround was to force &lt;code&gt;failure&lt;/code&gt; itself to not have that feature ever.
Easily done:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#ffecec;font-weight:bold;font-style:italic;color:#bd2c00;&quot;&gt;---&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt; Cargo.toml
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;font-style:italic;color:#55a532;&quot;&gt;+++&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt; Cargo.toml
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;font-style:italic;color:#969896;&quot;&gt;@@ -23,5 +23,5 @@&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; members = [&amp;quot;.&amp;quot;, &amp;quot;failure_derive&amp;quot;]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; [features]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; default = [&amp;quot;std&amp;quot;, &amp;quot;derive&amp;quot;]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; #small-error = [&amp;quot;std&amp;quot;]
&lt;/span&gt;&lt;span style=&quot;background-color:#ffecec;color:#323232;&quot;&gt;-std = [&amp;quot;backtrace&amp;quot;]
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;color:#55a532;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;color:#323232;&quot;&gt;std = []
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; derive = [&amp;quot;failure_derive&amp;quot;]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I &lt;a href=&quot;https://github.com/badboy/failure/commit/64af847bc5fdcb6d2438bec8a6030812a80519a5&quot;&gt;forked failure and commited that patch&lt;/a&gt;, then made mozilla-central use &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1608157&quot;&gt;my forked version&lt;/a&gt; instead.
Later I also removed &lt;code&gt;failure&lt;/code&gt; from both Glean and application-services&#39; &lt;code&gt;ffi-support&lt;/code&gt;, as the small functionality we got from it was easily reimplemented manually.&lt;/p&gt;
&lt;p&gt;Both approaches are short-term fixes for getting Glean into Firefox and it&#39;s clear that this issue might easily come up in some form soon again for either us or another team.
It&#39;s also a major hassle for lots of people outside of Mozilla, for example people working on embedded Rust frequently run into problems with &lt;code&gt;no_std&lt;/code&gt; libraries suddenly linking in &lt;code&gt;libstd&lt;/code&gt; again.&lt;/p&gt;
&lt;p&gt;Initially I also planned to figure out a way forward for Cargo and come up with a fix for it, but as it turns out: Someone is already doing that!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ehuss&quot;&gt;@ehuss&lt;/a&gt; started working on &lt;a href=&quot;https://github.com/rust-lang/cargo/pull/7820&quot;&gt;adding a new feature resolver&lt;/a&gt;.
While not yet final, it will bring a new &lt;code&gt;-Zfeatures&lt;/code&gt; flag initially:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;itarget&lt;/code&gt; — Ignores features for target-specific dependencies for targets that don&#39;t match the current compile target.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;build_dep&lt;/code&gt; — Prevents features enabled on build dependencies from being enabled for normal dependencies.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dev_dep&lt;/code&gt; — Prevents features enabled on dev dependencies from being enabled for normal dependencies.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&#39;m excited to see this being worked on and can&#39;t wait to try it out.
It will take longer for mozilla-central to rely on this of course, but I hope this will eventually solve one of the long standing issues with cargo.&lt;/p&gt;
&lt;br&gt;
&lt;hr /&gt;
&lt;br&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo tree --features bitsdownload,cranelift_x86,cubeb-remoting,fogotype,gecko_debug,gecko_profiler,gecko_refcount_logging,moz_memory,moz_places,new_cert_storage,new_xulstore,quantum_render
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;When patches are merged, a full set of tests are run on the Mozilla CI servers. If these tests fail the patch is reverted (&quot;backed out&quot;) and the initial committer informed. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Glean&#39;s error handling is pretty simplistic. We mostly only log errors on the FFI boundary and don&#39;t propagate them over this boundary. So far we didn&#39;t need a backtrace for errors there. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;The exact command enabling all the same features as the build I run in &lt;code&gt;toolkit/library/rust/shared&lt;/code&gt; was (on the parent commit of my later patch to fix it: &lt;a href=&quot;https://hg.mozilla.org/integration/autoland/rev/7a3be2bbce032721ec01a9b75d88cc7c6b089825&quot;&gt;7a3be2bbc&lt;/a&gt;): &lt;a href=&quot;#fr-3-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;Same feature set as above, just running &lt;code&gt;cargo feature-set&lt;/code&gt; this time. &lt;a href=&quot;#fr-4-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;&quot;&lt;a href=&quot;https://www.redox-os.org/&quot;&gt;Redox&lt;/a&gt; is a Unix-like Operating System written in Rust, aiming to bring the innovations of Rust to a modern microkernel and full set of applications&quot;. Firefox doesn&#39;t build on Redox. &lt;a href=&quot;#fr-5-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2020/02/03/this-week-in-glean</guid>
      <pubDate>Mon, 03 Feb 2020 15:00:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: A Release</title>
      <link>https://fnordig.de/2019/10/24/this-week-in-glean</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)&lt;/p&gt;
&lt;p&gt;Last week&#39;s blog post: &lt;a href=&quot;https://chuttenblog.wordpress.com/2019/10/17/this-week-in-glean-glean-on-desktop-project-fog/&quot;&gt;This Week in Glean: Glean on Desktop (Project FOG)&lt;/a&gt; by chutten.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Back in June when &lt;a href=&quot;https://blog.mozilla.org/futurereleases/2019/06/27/reinventing-firefox-for-android-a-preview/&quot;&gt;Firefox Preview shipped&lt;/a&gt;, it also shipped with Glean, our new Telemetry library, initially targeting mobile platforms.
Georg recently blogged about the design principles of Glean in &lt;a href=&quot;https://medium.com/georg-fritzsche/introducing-glean-telemetry-for-humans-4e8b4788b8ad&quot;&gt;Introducing Glean — Telemetry for humans&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Plans for improving mobile telemetry for Mozilla go back as as far as December 2017.
The first implementation of the Glean SDK was started around August 2018, all written in Kotlin (though back then it was mostly ideas in a bunch of text documents).
This implementation shipped in &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/&quot;&gt;Firefox Preview&lt;/a&gt; and was used up until now.&lt;/p&gt;
&lt;p&gt;On March 18th I &lt;a href=&quot;https://github.com/mozilla/glean/commit/95b6bcc03616c8d7c3e3e64e99ee9953aa06a474&quot;&gt;created an initial Rust workspace&lt;/a&gt;.
This kicked of a rewrite of Glean using Rust to become a cross-platform telemetry SDK to be used on Android, iOS and eventually coming back to desktop platforms again.&lt;/p&gt;
&lt;p&gt;1382 commits later&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; I tagged &lt;a href=&quot;https://github.com/mozilla/glean/commit/1ac00bf63daea97f6e2d6fa36980279eecf5a800&quot;&gt;v19.0.0&lt;/a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Obviously that doesn&#39;t make people use it right away, but given all consumers of Glean right now are Mozilla products, it&#39;s up on us to get them to use it.
So &lt;a href=&quot;https://github.com/mozilla-mobile/android-components/pull/4620&quot;&gt;Alessio did just that&lt;/a&gt; by upgrading Android Components, a collection of Android libraries to build browsers or browser-like applications, to this new version.&lt;/p&gt;
&lt;p&gt;This will soon roll out to nightly releases of Firefox Preview and, given we don&#39;t hit any larger bugs, hit the release channel in about 2 weeks.
Additionally, that finally unblocks the Glean team to work on new features, ironing out some sharp edges and bringing Glean to Firefox on Desktop.
Oh, and of course we still need to actually release it for iOS.&lt;/p&gt;
&lt;h2&gt;Thanks&lt;/h2&gt;
&lt;p&gt;Glean in Rust is the project I&#39;ve been constantly working on since March.
But getting it to a release was a team effort with help from a multitude of people and teams.&lt;/p&gt;
&lt;p&gt;Thanks to everyone on the Glean SDK team:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dexterp37/&quot;&gt;Alessio Placitelli&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mdboom/&quot;&gt;Michael Droettboom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/travis79/&quot;&gt;Travis Long&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/georgf/&quot;&gt;Georg Fritzsche&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/chutten&quot;&gt;Chris Hutten-Czapski&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/brizental&quot;&gt;Beatriz Rizental&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://github.com/fbertsch&quot;&gt;Frank Bertsch&lt;/a&gt; for a ton of backend work as well as the larger Glean pipeline team led by &lt;a href=&quot;https://github.com/mreid-moz&quot;&gt;Mark Reid&lt;/a&gt;, to ensure we can handle the incoming telemetry data and also reliably analyse it.
Thanks to the Data Engineering team led by Katie Parlante.
Thanks to &lt;a href=&quot;https://github.com/MihaiTabara&quot;&gt;Mihai Tabara&lt;/a&gt;, the Release Engineering team and the Cloud Operations team, to help us with the release on short notice.
Thanks to the &lt;a href=&quot;https://github.com/mozilla/application-services&quot;&gt;Application Services&lt;/a&gt; team for paving the way of developing mobile libraries with Rust and to the &lt;a href=&quot;https://github.com/mozilla/application-services&quot;&gt;Android Components&lt;/a&gt; team for constant help with Android development.&lt;/p&gt;
&lt;hr /&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Not all of which are just code for the Android version. There&#39;s &lt;a href=&quot;https://mozilla.github.io/glean/docs/glean_core/index.html&quot;&gt;a&lt;/a&gt; &lt;a href=&quot;https://mozilla.github.io/glean/javadoc/glean/&quot;&gt;lot&lt;/a&gt; &lt;a href=&quot;https://mozilla.github.io/glean/swift/&quot;&gt;of&lt;/a&gt; &lt;a href=&quot;https://mozilla.github.io/glean/book/index.html&quot;&gt;documentation&lt;/a&gt; too. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;This is the first released version. This is just the version number that follows after the Kotlin implementation. Version numbers are cheap. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2019/10/24/this-week-in-glean</guid>
      <pubDate>Thu, 24 Oct 2019 17:30:00 +0200</pubDate>
    </item>
    <item>
      <title>Rust - 4+ years later</title>
      <link>https://fnordig.de/2019/05/15/rust-4-years-later</link>
      <description>&lt;p&gt;Exactly 4 years ago, on May 15th 2015, the Rust Core Team &lt;a href=&quot;https://blog.rust-lang.org/2015/05/15/Rust-1.0.html&quot;&gt;announced the first stable version, Version 1.0&lt;/a&gt;, of the Rust Programming language.&lt;/p&gt;
&lt;p&gt;I started my Rust journey even earlier than that, somewhere around &lt;a href=&quot;/2014/08/12/first-experience-with-rust/&quot;&gt;August 2014&lt;/a&gt;, in parallel to my Bachelor thesis.
Shortly after my first blog post, I gave a last minute talk titled &lt;a href=&quot;/talks/2014/froscon/rust-for-rubyists/#/&quot;&gt;&quot;Rust for Rubyists&quot;&lt;/a&gt; &lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; at RedFrogConf, a (Ruby-focused) subconf of &lt;a href=&quot;https://www.froscon.de/en/&quot;&gt;FrOSCon&lt;/a&gt;.
Back then Rust had &quot;lightweight green tasks&quot;!&lt;/p&gt;
&lt;p&gt;Two months before the 1.0 release I spoke at CCCAC about &lt;a href=&quot;/talks/2015/cccac/rust-intro/#0&quot;&gt;Rust&lt;/a&gt; (those slides were built on minimal JavaScript so it could run in Servo).
I remember that I spent a lot of time on explaining the (safe) thread API.
Not only did I make a mistake in the explanation (and the code), but also shortly after the &lt;a href=&quot;https://github.com/rust-lang/rust/issues/24292&quot;&gt;scoped thread API was found to be unsound&lt;/a&gt; and subsequently removed
(use &lt;a href=&quot;https://docs.rs/crossbeam/0.7.1/crossbeam/thread/fn.scope.html&quot;&gt;crossbeam&#39;s &lt;code&gt;thread::scope&lt;/code&gt; API&lt;/a&gt; if you need something similar but safe and sound now).&lt;/p&gt;
&lt;p&gt;Then 1.0 came, more stuff was ripped out just before that and we got the first edition of &lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/index.html&quot;&gt;The Rust Programming Language&lt;/a&gt; book.
Work obviously didn&#39;t stop there.&lt;/p&gt;
&lt;p&gt;In 2016 we created the first ever &lt;a href=&quot;https://2016.rustfest.eu/&quot;&gt;RustFest&lt;/a&gt;, a community conference dedicated to Rust.
Due to luck and enthusiasm of many more people we managed to pull of another RustFest just half a year later and &lt;a href=&quot;https://blog.rustfest.eu/past_events/&quot;&gt;then four more editions after that&lt;/a&gt; (I missed only the Zurich one).
The sixth edition, &lt;a href=&quot;https://barcelona.rustfest.eu/&quot;&gt;RustFest Barcelona&lt;/a&gt;, is already announced.&lt;/p&gt;
&lt;p&gt;In 2014 Florian and Johann founded the &lt;a href=&quot;https://berline.rs/2014/11/04/hacking.html&quot;&gt;Rust Berlin Hack and Learn&lt;/a&gt;.
Last year, when I joined Mozilla and moved to Berlin, I became a co-organizer of that&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;br /&gt;
Today &lt;a href=&quot;https://berline.rs/2019/05/15/rust-hack-and-learn.html&quot;&gt;we&#39;re celebrating&lt;/a&gt;, but not just Rust&#39;s birthday, but also over 100 events under the Rust Berlin label (that includes our bi-weekly Hack and Learn, infrequent Rust Berlin talk meetups and the Rust &amp;amp; Tell).&lt;/p&gt;
&lt;p&gt;A month after I joined Mozilla, the first ever &lt;a href=&quot;https://internals.rust-lang.org/t/rust-2018-all-hands/7141&quot;&gt;Rust All-Hands&lt;/a&gt; happened in the Berlin office and,
as so much about my involvement with Rust,
I stumbled into being the responsible on-site person during that week. It &lt;a href=&quot;https://blog.rust-lang.org/2018/04/06/all-hands.html&quot;&gt;went pretty well&lt;/a&gt;.
We repeated the &lt;a href=&quot;https://blog.mozilla.org/berlin/rust-all-hands-2019/&quot;&gt;Rust All-Hands this year&lt;/a&gt; (German article), now with me being &lt;em&gt;officially&lt;/em&gt; the on-site organizer, but also attendee.&lt;/p&gt;
&lt;p&gt;In 2017 I shipped my first piece of Rust code used in production (an actual &lt;a href=&quot;https://www.theaterdo.de/detail/event/einstein-on-the-beach/&quot;&gt;opera production&lt;/a&gt;): &lt;a href=&quot;https://github.com/rrbone/midioscar&quot;&gt;midioscar&lt;/a&gt;.
A couple of weeks ago I started my first Mozilla project using Rust (more about that in a future blog post).&lt;/p&gt;
&lt;p&gt;Not only did Rust become a community I invest my time and resources in, it is now also officially part of my job.&lt;/p&gt;
&lt;p&gt;We&#39;re at &lt;a href=&quot;https://www.whatrustisit.com/&quot;&gt;Rust 1.34.2&lt;/a&gt; now (that&#39;s over &lt;strike&gt;34&lt;/strike&gt; 36 releases in 4 years!), with even more improvements, bug fixes, community conferences, hack fests and All Hands ahead of us.
Rust is here to stay.&lt;/p&gt;
&lt;center&gt;
&lt;h2&gt;🎉 To the next 4+ years! 🎉&lt;/h2&gt;
&lt;/center&gt;
&lt;hr /&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Based on &lt;a href=&quot;https://twitter.com/steveklabnik&quot;&gt;@steveklabnik&lt;/a&gt;&#39;s &quot;&lt;a href=&quot;http://www.rustforrubyists.com/&quot;&gt;Rust for Rubyists&lt;/a&gt;&quot; tutorial. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Fun fact: by accident I kinda was the one responsible for a Hack&#39;n&#39;Learn one night when I was in Berlin for other work, but none of the dedicated organizers was able to make it to the meetup. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2019/05/15/rust-4-years-later</guid>
      <pubDate>Wed, 15 May 2019 14:00:00 +0200</pubDate>
    </item>
    <item>
      <title>What Rust is it?</title>
      <link>https://fnordig.de/2018/11/28/what-rust-is-it</link>
      <description>&lt;p&gt;A while ago (sometime in August) I built a small service called &lt;a href=&quot;http://www.whatrustisit.com/&quot;&gt;What Rust is it?&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2018-11-28-what-rust-is-it.png&quot; alt=&quot;What Rust is it? - Screenshot of the website&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Based on what &lt;a href=&quot;http://whattrainisitnow.com/&quot;&gt;What Train is it now?&lt;/a&gt; is for Firefox, this small service lists the three trains of Rust: release, beta &amp;amp; nightly as well as their respective versions.
It&#39;s updated every day and actually checks what &lt;code&gt;rustup&lt;/code&gt; installed.
Additionally it shows the (planned) date of the next release.&lt;/p&gt;
&lt;p&gt;Similar information is available on the &lt;a href=&quot;https://forge.rust-lang.org/&quot;&gt;Rust Lang Forge&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See it live:&lt;/p&gt;
&lt;center&gt;
## [www.whatrustisit.com](http://www.whatrustisit.com)
&lt;/center&gt;
</description>
      <guid>https://fnordig.de/2018/11/28/what-rust-is-it</guid>
      <pubDate>Wed, 28 Nov 2018 20:09:00 +0100</pubDate>
    </item>
    <item>
      <title>How I made a useless tool and the reactions made my sunday better</title>
      <link>https://fnordig.de/2018/09/30/how-i-made-a-useless-tool-and-the-reactions-made-my-sunday-better</link>
      <description>&lt;p&gt;Last night I had an idea, which made me stay up two hours longer than I wanted.
I built a useless tool: &lt;a href=&quot;https://github.com/badboy/lysbilder/&quot;&gt;lysbilder&lt;/a&gt;, the slide system no one needed.&lt;/p&gt;
&lt;p&gt;Today I tweeted about it and then went out to enjoy the day a bit:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/badboy_/status/1046378708527976449&quot;&gt;@badboy_&lt;/a&gt;:
I might have built a very useless slideshow tool on top of rustdoc, generated from code documentation, linked by trait implementations.&lt;/p&gt;
&lt;p&gt;Please don’t use it¹.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://badboy.github.io/lysbilder/&quot;&gt;https://badboy.github.io/lysbilder/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;¹: however, I will use it once.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Quickly I got some responses:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/myriamjessier/status/1046382236013129729&quot;&gt;@myriamjessier&lt;/a&gt;:
I laughed. It was good enough to retweet just because of that.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/QuietMisdreavus/status/1046411069529477121&quot;&gt;@QuietMisdreavus&lt;/a&gt;:
i love this so much&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Those made me smile and made my sunday a bit better. :)&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2018/09/30/how-i-made-a-useless-tool-and-the-reactions-made-my-sunday-better</guid>
      <pubDate>Sun, 30 Sep 2018 23:00:00 +0200</pubDate>
    </item>
    <item>
      <title>Ideas for Rust Meetups</title>
      <link>https://fnordig.de/2018/08/08/ideas-for-rust-meetups</link>
      <description>&lt;p&gt;Not every meetup follows the same structure. Not every meetup needs to have 75+ attendees.
If you find a room and 3 people, it&#39;s a meetup.&lt;/p&gt;
&lt;p&gt;LLogiq, organizer of the &lt;a href=&quot;https://www.meetup.com/Rust-Rhein-Main/&quot;&gt;Rhein-Main Rust meetup&lt;/a&gt;,
published a list with some &lt;a href=&quot;https://llogiq.github.io/2018/08/08/meetup-ideas.html&quot;&gt;Ideas for Rust Meetups&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here are 2 more:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RFC Lightning talks - Attendees sign up before the meetup to present one open RFC. Allocate some time to discuss it in more detail afterwards. Rust Cologne had &lt;a href=&quot;http://rust.cologne/2017/09/06/lightning-rfcs.html&quot;&gt;such a meetup&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Hack&#39;n&#39;Learn - Open the door, have some desks and let people work on their projects. This works very well for the Berlin Hack&#39;n&#39;Learn. We usually start with a quick introduction round, where everyone also states what they plan to work on. Later that evening people get a couple more minutes to present their results if they want.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;Another that &lt;a href=&quot;https://twitter.com/killercup/status/1027153953174302720&quot;&gt;@killercup&lt;/a&gt; brought up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Open Space Meetups - Imagine a bazaar, where you can suggest topics and spontaneously join any discussion you find interesting. Collect topics at the beginning, assign 30 minute slots. Start discussing in small groups. Hop between discussions when you think it&#39;s finished. Based on &lt;a href=&quot;https://github.com/Rustaceans/rust-cologne/blob/gh-pages/meetup-orga/Rust%20Cologne%20Open%20Space.pdf&quot;&gt;4 simple principles&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description>
      <guid>https://fnordig.de/2018/08/08/ideas-for-rust-meetups</guid>
      <pubDate>Wed, 08 Aug 2018 12:45:00 +0200</pubDate>
    </item>
    <item>
      <title>DOH everything</title>
      <link>https://fnordig.de/2018/02/09/doh-everything</link>
      <description>&lt;p&gt;Two days ago &lt;a href=&quot;/2018/02/07/d-oh-dns-over-https-in-rust/&quot;&gt;I wrote about a new small utility crate&lt;/a&gt; for doing DNS over HTTPS.
When I started with the code on Monday I had an actual use case in mind.&lt;/p&gt;
&lt;p&gt;Due to some combination of &lt;a href=&quot;https://www.joyent.com/smartos&quot;&gt;SmartOS&lt;/a&gt;, Ubuntu 17.04 and glibc my server currently has problems resolving DNS.
It turns out a server without a working DNS resolver is kind of a pain, adding hostnames and their IPs to &lt;code&gt;/etc/hosts&lt;/code&gt; gets tiring pretty fast.&lt;/p&gt;
&lt;p&gt;Luckily, glibc&#39;s &lt;a href=&quot;http://man7.org/linux/man-pages/man3/gethostbyname.3.html&quot;&gt;&lt;code&gt;gethostbyname&lt;/code&gt;&lt;/a&gt; makes us of external plugins to do the actual resolving.
That&#39;s how &lt;code&gt;/etc/hosts&lt;/code&gt; and an external resolver work in the first place.
The &lt;a href=&quot;http://www.gnu.org/software/libc/manual/html_node/NSS-Modules-Interface.html#NSS-Modules-Interface&quot;&gt;documentation on the exact plugin mechanism&lt;/a&gt; is quite sparse, but luckily &lt;em&gt;systemd&lt;/em&gt; comes with its own resolve plugin: &lt;a href=&quot;https://github.com/systemd/systemd/blob/master/src/nss-resolve/nss-resolve.c&quot;&gt;nss-resolve.c&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All it takes to build a resolver plugin is to implement two functions&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;enum nss_status _nss_$plugin_gethostbyname4_r(...)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;enum nss_status _nss_$plugin_gethostbyname3_r(...)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Both take a bunch of arguments, but it boils down to this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get the hostname (and optionally the address family to look for)&lt;/li&gt;
&lt;li&gt;Resolve this hostname to its IP addresses&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;Copy the data into the provided buffer&lt;/li&gt;
&lt;li&gt;Let the result point somewhere into this buffer&lt;/li&gt;
&lt;li&gt;Clear the error values and return a success value&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If at any point an error is encountered, several error values are set and the function returns a failure.&lt;/p&gt;
&lt;p&gt;If all goes right, the requesting application will receive a data structure to read the different IP addresses from, which it can then use to establish a connection.&lt;/p&gt;
&lt;p&gt;Equipped with &lt;a href=&quot;https://crates.io/crates/dnsoverhttps&quot;&gt;dnsoverhttps&lt;/a&gt; the resolving part is suprisingly easy.
First turn the passed name into a string, then call into the library and collect the results.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;unsafe &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; slice &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;CStr::from_ptr(orig_name);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; name &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; slice.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;to_string_lossy&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; addrs &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= match &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;dnsoverhttps::resolve_host(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;name) {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Ok&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(a) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; a,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Err&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;errnop &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;EINVAL&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;h_errnop &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;NO_RECOVERY&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;NSS_STATUS_UNAVAIL&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    };
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;// ...
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Filling the appropiate data structures and memory buffer is a bit more complex and involves some pointer trickery.
Instead of trying to find the right (unsafe) approach in Rust to do it correctly I opted to copy the &lt;code&gt;systemd&lt;/code&gt;-code for now.&lt;/p&gt;
&lt;p&gt;In the Rust part we can forward the received arguments and add an array of results&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; addrs : Vec&amp;lt;&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; addrs.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;into_iter&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(ip_addr_to_tuple).&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;collect&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;write_addresses4&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(orig_name, pat, buffer, buflen, errnop, h_errnop, ttlp,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  addrs.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;as_ptr&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(), addrs.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;())
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This calls into a function &lt;a href=&quot;https://github.com/badboy/libnss_dnsoverhttps/blob/a3f25c92881ec1d1100ea4e7f7d399d1c51b80b6/src/write_addr.c#L13-L19&quot;&gt;written in C&lt;/a&gt; and &lt;a href=&quot;https://github.com/badboy/libnss_dnsoverhttps/blob/a3f25c92881ec1d1100ea4e7f7d399d1c51b80b6/build.rs&quot;&gt;compiled just before the Rust code is compiled&lt;/a&gt;.
It&#39;s also statically linked into the resulting shared object, ready to be deployed.&lt;/p&gt;
&lt;p&gt;In order to use it, the library has to be copied into a directory where the system can find it:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cp target/release/libnss_dnsoverhttps.so /usr/lib/libnss_dnsoverhttps.so.2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then it can finally be used by adding it to &lt;code&gt;/etc/nsswitch.conf&lt;/code&gt; like this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;hosts: dnsoverhttps files mymachines dns myhostname
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;curl&lt;/code&gt; and other processes calling &lt;code&gt;gethostbyname&lt;/code&gt; will from now on get addresses resolved by this small module.&lt;/p&gt;
&lt;br&gt;
&lt;hr /&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;And forward &lt;code&gt;_nss_$plugin_gethostbyname2_r&lt;/code&gt; and &lt;code&gt;_nss_$plugin_gethostbyname_r&lt;/code&gt; to &lt;code&gt;_nss_$plugin_gethostbyname3_r&lt;/code&gt;. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Remember that you can&#39;t use &lt;code&gt;gethostbyname&lt;/code&gt; here, because you &lt;em&gt;are&lt;/em&gt; &lt;code&gt;gethostbyname&lt;/code&gt;. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;In between turning our vector of addresses into a simpler structure. &lt;a href=&quot;#fr-3-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2018/02/09/doh-everything</guid>
      <pubDate>Fri, 09 Feb 2018 14:52:00 +0100</pubDate>
    </item>
    <item>
      <title>D&#39;oh! - DNS over HTTPS in Rust</title>
      <link>https://fnordig.de/2018/02/07/d-oh-dns-over-https-in-rust</link>
      <description>&lt;p&gt;Last weekend I met &lt;a href=&quot;https://twitter.com/bagder&quot;&gt;Daniel Stenberg&lt;/a&gt;, author of curl, at FOSDEM and we talked a bit about curl, Firefox and also Rust.
One recent project he was working on was &lt;em&gt;DNS over HTTPS&lt;/em&gt; &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1434852&quot;&gt;support for Firefox&lt;/a&gt; and &lt;a href=&quot;https://github.com/curl/curl/wiki/DNS-over-HTTPS&quot;&gt;eventually for curl&lt;/a&gt; as well.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;DNS over HTTPS&lt;/em&gt;, short &lt;em&gt;DOH&lt;/em&gt;, is a recent idea to do DNS queries over HTTPS for privacy, performance and security reasons. There&#39;s an &lt;a href=&quot;https://tools.ietf.org/html/draft-ietf-doh-dns-over-https-02&quot;&gt;RFC draft in version 3&lt;/a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; at the IETF describing it in more detail.&lt;br /&gt;
The &lt;em&gt;tl;dr&lt;/em&gt;: Send the DNS protocol in an HTTP POST request or base64-encoded in a GET request,
get back the DNS protocol in the response body and parse it.&lt;/p&gt;
&lt;p&gt;Given how simple that sounds, I decided to implement a minimal DOH client in Rust.
I present to you:&lt;/p&gt;
&lt;center&gt;
&lt;h3&gt;&lt;a href=&quot;https://github.com/badboy/dnsoverhttps&quot;&gt;dnsoverhttps&lt;/a&gt;&lt;/h3&gt;
&lt;/center&gt;
&lt;p&gt;It exports one function to resolve a hostname to its IPv6 and IPv4 addresses:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;extern crate&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; dnsoverhttps;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; name &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;example.com&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; addr &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;dnsoverhttps::resolve_host(name);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; addr {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        println!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt; has address &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, name, a);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It currently uses &lt;code&gt;dns.google.com&lt;/code&gt; (or to be exact one of its IPs: &lt;code&gt;172.217.21.110&lt;/code&gt;) and skips TLS certificate checks (because the underlying HTTP request library has no option to pass in the hostname yet).
It will also always query for both IPv6 and IPv4 addresses (&lt;code&gt;AAAA&lt;/code&gt; and &lt;code&gt;A&lt;/code&gt; records respectively).
&lt;code&gt;CNAME&lt;/code&gt; records will work as well by the mere fact that the server recursively resolves it and &lt;code&gt;dnsoverhttps&lt;/code&gt; simply takes the found IP address.
Other records are not supported at the moment.&lt;/p&gt;
&lt;p&gt;For a quick try you can install the bundled CLI tool to replace the &lt;code&gt;host&lt;/code&gt; tool to resolve hostnames.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo install dnsoverhttps
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then execute it:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ ~/.cargo/bin/host example.com
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;example.com has address 2606:2800:220:1:248:1893:25c8:1946
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;example.com has address 93.184.216.34
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.rs/dnsoverhttps/0.1.0/dnsoverhttps/&quot;&gt;Documentation is available online&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;&lt;code&gt;dnsoverhttps&lt;/code&gt; currently implements Version 2, because that&#39;s what &lt;code&gt;dns.google.com&lt;/code&gt; supports. Version 3 changes the query parameter from &lt;code&gt;body&lt;/code&gt; to &lt;code&gt;dns&lt;/code&gt;. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2018/02/07/d-oh-dns-over-https-in-rust</guid>
      <pubDate>Wed, 07 Feb 2018 09:05:00 +0100</pubDate>
    </item>
    <item>
      <title>Retrospective: Rust Cologne in January</title>
      <link>https://fnordig.de/2018/01/10/retrospective-rust-cologne-in-january</link>
      <description>&lt;p&gt;Last monday, 8th of January, we had the first &lt;a href=&quot;http://rust.cologne&quot;&gt;Rust Cologne&lt;/a&gt; meetup this year.
We opted for a Open Space-style meetup, allowing for broad discussion rounds in small groups, which worked reasonably well this time (it&#39;s the second time we did it). More on that later.&lt;/p&gt;
&lt;h2&gt;News&lt;/h2&gt;
&lt;p&gt;We usually start off the meeting with a short round of news since the last meetup (usually 4-6 weeks).
This time we did it a bit adhoc:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.rust-lang.org/2018/01/04/Rust-1.23.html&quot;&gt;Rust 1.23 was released&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/diesel-rs/diesel/releases/tag/v1.0.0&quot;&gt;Diesel 1.0 was released&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rust-lang/rust/pull/46862&quot;&gt;NLL (non-lexical lifetimes) are in nightly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.rust-lang.org/2018/01/03/new-years-rust-a-call-for-community-blogposts.html&quot;&gt;Call for #Rust2018 community input&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Open Space&lt;/h2&gt;
&lt;p&gt;Open Space follows &lt;a href=&quot;https://github.com/Rustaceans/rust-cologne/blob/gh-pages/meetup-orga/Rust%20Cologne%20Open%20Space.pdf&quot;&gt;4 simple principles&lt;/a&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Whoever comes are the right people.&lt;/li&gt;
&lt;li&gt;Whatever happens is the only thing that could have.&lt;/li&gt;
&lt;li&gt;When it starts is the right time.&lt;/li&gt;
&lt;li&gt;When it&#39;s over, it&#39;s over.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This time around we had a couple of new attendees, which is very encouraging for everyone involved.
With a dozen people around, we managed to have between two and four concurrently running small discussion rounds.&lt;/p&gt;
&lt;p&gt;We collected some topics upfront:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Learning Rust&lt;/li&gt;
&lt;li&gt;Favourite not-yet-stable feature&lt;/li&gt;
&lt;li&gt;Embedded Rust&lt;/li&gt;
&lt;li&gt;Realtime programming&lt;/li&gt;
&lt;li&gt;Tokio / async programming&lt;/li&gt;
&lt;li&gt;Rust for the Web&lt;/li&gt;
&lt;li&gt;Miri&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Obviously, I was not able to take part in all discussions, but I collected some rough notes from the things I was in.
In the following are some rough notes regarding each topic. There are not necessarily clear outcomes of the discussions or steps to take.&lt;/p&gt;
&lt;h3&gt;Learning Rust&lt;/h3&gt;
&lt;p&gt;With a couple beginners and some more seasoned Rustaceans around, we discussed what it takes to learn Rust, (missing) material and projects.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;High-level docs on Cargo were requested: what does it do, why are dependencies not that bad, what to look out for in dependencies, drawbacks of too many dependencies&lt;/li&gt;
&lt;li&gt;A book on patterns in Rust: not everything in Rust is as easy to write as in other languages, sometimes a whole other pattern is necessary. These should be collected (also a &quot;X in C++ will become Y in Rust&quot;).&lt;br /&gt;
&lt;strong&gt;Edit&lt;/strong&gt;: The &lt;a href=&quot;https://github.com/rust-unofficial/patterns&quot;&gt;Rust Design Patterns repository&lt;/a&gt; exists.&lt;/li&gt;
&lt;li&gt;Confusion about split between 1st and 2nd version of &lt;a href=&quot;https://doc.rust-lang.org/book/&quot;&gt;The Rust Programming Language (the book)&lt;/a&gt;. Old links are obviously sometimes broken, not all content is in both books. Some links in official documentation are broken due to the split (we didn&#39;t find a example that night, but it&#39;s worth triaging this)&lt;/li&gt;
&lt;li&gt;Better crate caching: A global per-system/per-user cache of compiled crates could go a long way to improve compile times (in theory). Why is it not done? Drawbacks? We should look up the current status and discussions.&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;https://rust-lang-nursery.github.io/rust-cookbook/&quot;&gt;Rust Cookbook&lt;/a&gt; might be a good idea, but can easily become overwhelming. In the end it needs to be easily findable through a quick Google search.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the end this discussion spun off into the embedded discussion and I left.&lt;/p&gt;
&lt;h3&gt;Tokio / async programming&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Tokio is undocumented, which definitely hinders adoption&lt;/li&gt;
&lt;li&gt;We discussed/explained what an event reactor (like Tokio) even is and how it ties in with futures&lt;/li&gt;
&lt;li&gt;We discussed why futures in Tokio are tied to the Tokio event reactor and can&#39;t easily be re-used for another event reactor&lt;/li&gt;
&lt;li&gt;Briefly discussed the coming async/await/Generator features&lt;/li&gt;
&lt;li&gt;Someone requested a larger guide on how to structure a large server with asynchronous network I/O. How to handle state? How to deal with disconnects/reconnects?&lt;/li&gt;
&lt;li&gt;We discussed trade-offs between async I/O and just relying on threads for server applications and when the latter makes more sense&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Rust for the Web&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;I talked a bit about the story of Rust for web servers and also about the frontend part.&lt;/li&gt;
&lt;li&gt;Lots of interest in doing Rust in the frontend and not need to deal with JavaScript for most of the time&lt;/li&gt;
&lt;li&gt;The state of current web frameworks: there&#39;s a lot of work to do; Rocket might be promising, but it&#39;s bound to nightly and a lot of code rewriting, which I don&#39;t necessarily like; Iron and Nickel, the earliest frameworks, are on their way out&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;After 3 hours of lively discussions we brought the evening to an end.
This was (most likely) my last meetup as an official part of the organizer team.
&lt;a href=&quot;https://github.com/Rustaceans/rust-cologne/issues/46&quot;&gt;Plans for the February meetup&lt;/a&gt; are started and I might join that one again if I&#39;m around. Please jump into the conversation and propose ideas, talks or projects!&lt;/p&gt;
&lt;p&gt;Thanks to Colin (who also left the organizer team, but took care of invitations for the January meetup one last time), Pascal &amp;amp; Florian.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2018/01/10/retrospective-rust-cologne-in-january</guid>
      <pubDate>Wed, 10 Jan 2018 12:25:00 +0100</pubDate>
    </item>
    <item>
      <title>Hello, Rust! Hello, WebAssembly!</title>
      <link>https://fnordig.de/2017/11/18/hello-rust-hello-webassembly</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.hellorust.com/&quot;&gt;hellorust.com&lt;/a&gt; is live!&lt;/p&gt;
&lt;p&gt;This site will collect resources, guides, articles and links around Rust &amp;amp; WebAssembly.
If you want to help or have more resources we should add, &lt;a href=&quot;https://github.com/badboy/hellorust/issues/new&quot;&gt;open an issue&lt;/a&gt; or send a Pull Request to &lt;a href=&quot;https://github.com/badboy/hellorust&quot;&gt;github.com/badboy/hellorust&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To get started, head over to the &lt;a href=&quot;https://www.hellorust.com/setup/&quot;&gt;Setup section&lt;/a&gt; or take a look at &lt;a href=&quot;https://www.hellorust.com/demos/&quot;&gt;some example code&lt;/a&gt;.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2017/11/18/hello-rust-hello-webassembly</guid>
      <pubDate>Sat, 18 Nov 2017 16:26:57 +0100</pubDate>
    </item>
    <item>
      <title>novemb.rs Code Sprint Weekend 2016 - Retrospective</title>
      <link>https://fnordig.de/2016/11/29/novemb-rs-code-sprint-weekend-2016-retrospective</link>
      <description>&lt;p&gt;&lt;em&gt;This post is a tiny bit late, but better late than never.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So on 19th and 20th of November, just over a week ago, we had the very first &lt;a href=&quot;http://novemb.rs/&quot;&gt;novemb.rs Code Sprint&lt;/a&gt;.
In 10 locations in Europe and the US as well as online, people gathered to hack on projects, start new ones or just to learn Rust.
Bringing people together is one goal of the Rust community and coding, learning and having fun together is a lot of fun as well.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src=&quot;//tmp.fnordig.de/novemb.rs/th-novembrs-sign.jpg&quot; alt=&quot;novemb.rs @ C4&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We opened doors at Chaos Computer Club Cologne&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;I was part of the &lt;a href=&quot;http://rust.cologne/2016/11/19/novemb-rs.html&quot;&gt;novemb.rs Event in Cologne&lt;/a&gt;.
On both days about a dozen people showed up, from noon to late in the evening.&lt;/p&gt;
&lt;p&gt;In Cologne, we had several different projects and ideas being worked on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some audio/midi processing. I don&#39;t have much to show here, but I hope we will see (and hear) more of this soon, maybe even a talk at our meetup next year.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/panicbit&quot;&gt;@panicbit&lt;/a&gt; and &lt;a href=&quot;https://github.com/killercup&quot;&gt;@killercup&lt;/a&gt; tried to port &lt;a href=&quot;http://flif.info/&quot;&gt;FLIF&lt;/a&gt;, a &quot;Free Lossless Image Format&quot; to Rust. This kept everyone on-site entertained for quite a bit.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Florob/rust-xmpp&quot;&gt;@Florob&lt;/a&gt; worked on a problem with buffering, when mixing &lt;a href=&quot;https://github.com/sfackler/rust-openssl&quot;&gt;rust-openssl&lt;/a&gt; with a &lt;a href=&quot;https://doc.rust-lang.org/stable/std/io/struct.BufReader.html&quot;&gt;&lt;code&gt;BufReader&lt;/code&gt;&lt;/a&gt;. No code to show sadly either.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/colin-kiegel&quot;&gt;@colin-kiegel&lt;/a&gt; followed up on my &lt;a href=&quot;https://github.com/colin-kiegel/rust-derive-builder/pull/28&quot;&gt;Pull Request on &lt;code&gt;rust-derive-builder&lt;/code&gt;&lt;/a&gt;, diving deep into Macros 1.1. We decided to move forward with some of the ideas to make that crate use the new way of doing things, once they hit stable.&lt;/li&gt;
&lt;li&gt;As part of my &quot;job&quot; as a community team member I took a look at &lt;a href=&quot;http://rustaceans.org/&quot;&gt;rustaceans.org&lt;/a&gt;, a website is for finding Rustaceans. We will soon extend it to make it easier to find potential speakers for your meetup or event.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/sangyye&quot;&gt;@sangyye&lt;/a&gt; dropped by to learn some more Rust. He&#39;s one of the organisators behind &lt;a href=&quot;http://cologne.onruby.de/&quot;&gt;Cologne.rb&lt;/a&gt; and &lt;strong&gt;*hint* *hint*&lt;/strong&gt; &lt;a href=&quot;https://github.com/Rustaceans/rust-cologne/issues/19&quot;&gt;there might be a joint meetup next year&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Personally, I wanted to work on &lt;a href=&quot;https://github.com/semantic-rs/semantic-rs/&quot;&gt;semantic-rs&lt;/a&gt;. but didn&#39;t get to write a single line of code for that project.
Though I fixed a few other projects and wrote another few hundred lines for a (not yet published) project.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks to our attendees and thanks to my co-organizers Colin, Flo &amp;amp; Pascal.
And another big thanks to Mozilla for sponsoring the pizza and the C4 for offering the space.&lt;/p&gt;
&lt;h3&gt;Things that worked well&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;We got people together! About a dozen of people per day in Cologne and another handful at other locations as well.&lt;/li&gt;
&lt;li&gt;We got some things coded. See above.&lt;/li&gt;
&lt;li&gt;We learned and discussed Rust and had fun the whole weekend.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Things that we should improve&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Organization in other locations was a bit ad-hoc and on short-term, which is why we might have missed out on a few people.&lt;/li&gt;
&lt;li&gt;With a bit more time ahead it might be easier to get people involved. We also lacked in communication and (in the beginning) didn&#39;t make it clear what the event was supposed to be in.&lt;/li&gt;
&lt;li&gt;novemb.rs tried to focus on people in UTC-1 to UTC+4, which covers most of Europe, but also the African continent.
People from the US jumped in and opened their offices or other locations as well, but we were unable to get anything going on the African continent.
We should try harder to get people from everywhere involved.&lt;/li&gt;
&lt;li&gt;Online Communication between locations wasn&#39;t used that much. The whole idea was to have a distributed code sprint, so working together on projects across locations would have been nice. Maybe we should offer to have ad-hoc video calls as well?&lt;/li&gt;
&lt;/ul&gt;
&lt;center&gt;
&lt;p&gt;&lt;a href=&quot;//tmp.fnordig.de/novemb.rs/2016-11-20_14.36.28.jpg&quot;&gt;&lt;img src=&quot;//tmp.fnordig.de/novemb.rs/th-2016-11-20_14.36.28.jpg&quot; alt=&quot;Rust @ Whiteboard&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Coding on the whiteboard (only half of the attendees in the picture)&lt;/p&gt;
&lt;/center&gt;
&lt;h3&gt;Try again?&lt;/h3&gt;
&lt;p&gt;Definitely! Given that the overall organization effort is low I&#39;d like to make this a more regular thing.
With the experience from this year we have enough points to improve and we can plan this in advance. Plus, we already have the domain anyway ;)&lt;/p&gt;
&lt;p&gt;Until then, there are of course other opportunities to get in contact with fellow Rustaceans.
We have a monthly meetup in Cologne, with a Christmas-themed &lt;a href=&quot;http://rust.cologne/2016/12/07/christmas-maket.html&quot;&gt;&lt;code&gt;impl Glühwein for RustCologne&lt;/code&gt;&lt;/a&gt; happening next week.
Feel free to join us on the Weihnachtsmarkt or in January at another more regular meetup.
If you are not from the Rhein area, take a look if there&#39;s a &lt;a href=&quot;https://www.rust-lang.org/en-US/user-groups.html&quot;&gt;Rust User Group&lt;/a&gt; near you.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;a href=&quot;//tmp.fnordig.de/novemb.rs/2016-11-20_12.11.20.jpg&quot;&gt;&lt;img src=&quot;//tmp.fnordig.de/novemb.rs/th-2016-11-20_12.11.20.jpg&quot; alt=&quot;Rust&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Signs showed the way&lt;/p&gt;
&lt;/center&gt;
</description>
      <guid>https://fnordig.de/2016/11/29/novemb-rs-code-sprint-weekend-2016-retrospective</guid>
      <pubDate>Tue, 29 Nov 2016 11:55:00 +0100</pubDate>
    </item>
    <item>
      <title>Signify - Ed25519 signatures for your files (in Rust)</title>
      <link>https://fnordig.de/2016/09/28/signify-ed25519-signatures-for-your-files</link>
      <description>&lt;p&gt;From time to time I try to write a piece of code or port some existing library or application just for fun.
So a while back in June I had some free time again and I came across &lt;a href=&quot;https://github.com/aperezdc/signify&quot;&gt;signify&lt;/a&gt;.
I ported it to rust: &lt;a href=&quot;https://github.com/badboy/signify-rs&quot;&gt;signify-rs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;signify&lt;/code&gt; is a small command line utility to create &lt;a href=&quot;https://ed25519.cr.yp.to/&quot;&gt;Ed25519&lt;/a&gt; signatures of files.
It was developed to cryptographically sign and verify OpenBSD releases. Read &lt;a href=&quot;https://www.openbsd.org/papers/bsdcan-signify.html&quot;&gt;&quot;Securing OpenBSD From Us To You&quot;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;Now all you need to create signatures and verify them is a private &amp;amp; a public key.
Both parts are super short, so it is no problem to embed or print them.
This is what a public key would look like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;RWR/JMX+u3pyzGSyTSnOFINVcHJycZE/o6UTUshxvpcp6S4annmJK4DB&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The corresponding private key is this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;RWRCSwAAAAASfh0v1XJS4FYg59ntf4d7zYS9GR848h1/JMX+u3pyzIFNjvCMxLUgurelzAWTCSd9y6ghUcbcPVMuwnlDJy4WZLJNKc4Ug1VwcnJxkT+jpRNSyHG+lynpLhqeeYkrgME=&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(&lt;strong&gt;Warning: Do NOT use above keys for anything! I included both for demonstration only&lt;/strong&gt;)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;signify&lt;/code&gt; will add an additional comment to the key files, but they are not used for any verification (besides making sure they are actually in the file).&lt;/p&gt;
&lt;p&gt;Whereas pure Ed25519 keys are just 32 bytes, above keys already include some additional information used by signify to create and verify signatures. The private key can also be protected by a passphrase.&lt;/p&gt;
&lt;p&gt;When I started porting this small application I knew nothing about Ed25519 or signify.
I more or less translated the existing C code into Rust.
Back then, I used &lt;a href=&quot;https://crates.io/crates/rust-crypto&quot;&gt;rust-crypto&lt;/a&gt;, a pure Rust implementation various common cryptographic algorithms.
It provided all I needed: Ed25519 key generation, signing &amp;amp; verification and bcrypt for the passphrase handling.
In just one day I had a working application and less than 2 weeks later I also implemented proper passphrase-protection.&lt;/p&gt;
&lt;p&gt;In August then the most promising Rust crypto library, &lt;a href=&quot;https://crates.io/crates/ring&quot;&gt;*ring*&lt;/a&gt;, was released on crates.io as well (before that it could only be used as a git dependency).
I used *ring* before for &lt;a href=&quot;https://github.com/badboy/nobsign&quot;&gt;nobsign&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/BRIAN_____&quot;&gt;Brian Smith&lt;/a&gt;, the author of *ring*, already helped out with some code review &amp;amp; helping me use the API properly.&lt;br /&gt;
So I was not too surprised when Brian reached out to me asking if I would be willing to port &lt;code&gt;signify-rs&lt;/code&gt; over to *ring* as well.&lt;/p&gt;
&lt;p&gt;I was (however, it was shortly before &lt;a href=&quot;http://www.rustfest.eu/&quot;&gt;RustFest&lt;/a&gt;, so I couldn&#39;t dedicate much time to it).&lt;/p&gt;
&lt;p&gt;I took a look at the &lt;a href=&quot;https://briansmith.org/rustdoc/ring/&quot;&gt;*ring* documentation&lt;/a&gt; and immediately realised I had a completely wrong understanding of Ed25519.
Whereas in &lt;code&gt;signify&lt;/code&gt; the public key is stored in 32 byte and the private key is stored in 64 byte,
*ring* had both keys as only 32 byte long.
With feedback from Brian I realised that the longer private key as used in &lt;code&gt;signify&lt;/code&gt;
is actually just the 32-byte public key concatenated to the (real) 32-byte private key, resulting in 64 byte total.&lt;/p&gt;
&lt;p&gt;Equipped with this information (and after the first RustFest day was over), it was easy to port over &lt;code&gt;signify-rs&lt;/code&gt; to *ring*.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;signify-rs&lt;/code&gt; still depends on &lt;code&gt;rust-crypto&lt;/code&gt; though, as it provides the necessary &lt;code&gt;bcrypt_pbkdf&lt;/code&gt; for encrypting the private key with a user-chosen passphrase. *ring* does not provide &lt;code&gt;bcrypt&lt;/code&gt; and probably won&#39;t do so anytime soon.
If anyone wants to implement a really good &lt;code&gt;bcrypt&lt;/code&gt; crate, please contact me or Brian for feedback.&lt;/p&gt;
&lt;h2&gt;Use &lt;code&gt;signify-rs&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;First you need to install it, do so with &lt;code&gt;cargo&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo install signify
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Generate a key pair:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;signify -G -p public-key -s secret-key
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will ask you for a passphrase to protect the secret key. Remember that.
Now you can sign a file:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;signify -S -s secret-key -m README.md
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will create &lt;code&gt;README.md.sig&lt;/code&gt; containing the signature.
To verify it:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;signify -V -p public-key -m README.md
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If it prints &lt;code&gt;Signature Verified&lt;/code&gt; it went well. Otherwise it will show an error.&lt;/p&gt;
&lt;h2&gt;A signature&lt;/h2&gt;
&lt;p&gt;This is the signature using above private key on the &lt;a href=&quot;https://github.com/badboy/signify-rs/blob/177717053fb155d554cb1f697310bda1143edba4/README.md&quot;&gt;README.md&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;untrusted comment: signature from signify secret key&lt;br /&gt;
RWR/JMX+u3pyzIDv+Gt4JwMbWsb+dt0R/9tYDEjVw7zmBQoQR06Pcd2yr03XqvTSqaJBTbUhm74iUxB98BQVAZemq692g5Xv0gs=&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you put that signature in a file, put the public key from above into another, you can verify it!&lt;/p&gt;
&lt;h2&gt;Future plans&lt;/h2&gt;
&lt;p&gt;I still have todos left for this project.
First I want this to be fully compatbile with the original implemenation.
The original implementation can embed signatures into the signed file and also verify an embedded signature. I want to add that.
I also want to distribute pre-compiled binaries for various platforms (hello, &lt;a href=&quot;https://github.com/japaric/rust-everywhere&quot;&gt;rust-everywhere&lt;/a&gt;)
and provide proper Ed25519 signatures on all those releases.&lt;/p&gt;
&lt;p&gt;If you want to help with any of that, jump over &lt;a href=&quot;https://github.com/badboy/signify-rs&quot;&gt;to the GitHub repository&lt;/a&gt; and start hacking.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2016/09/28/signify-ed25519-signatures-for-your-files</guid>
      <pubDate>Wed, 28 Sep 2016 13:16:00 +0200</pubDate>
    </item>
    <item>
      <title>Rust from the Back to the Front (Rust Sthlm)</title>
      <link>https://fnordig.de/2016/08/31/rust-from-the-back-to-the-front</link>
      <description>&lt;center&gt;
&lt;p&gt;&lt;a href=&quot;//tmp.fnordig.de/rust-sthlm/2016-08-29_18.23.59.jpg&quot;&gt;&lt;img src=&quot;//tmp.fnordig.de/rust-sthlm/th-2016-08-29_18.23.59.jpg&quot; alt=&quot;Rust on the Web&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;Last monday I attended the &lt;a href=&quot;https://www.meetup.com/ruststhlm/events/232054490/&quot;&gt;Rust Sthlm&lt;/a&gt; Meetup and gave a talk about using Rust for web development.
About 60 people attended, had pizza and listened to the two talks of the evening.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;a href=&quot;//tmp.fnordig.de/rust-sthlm/th-2016-08-29_18.59.00.jpg&quot;&gt;&lt;img src=&quot;//tmp.fnordig.de/rust-sthlm/th-2016-08-29_18.59.00.jpg&quot; alt=&quot;Meetup&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;I started off with my talk &lt;em&gt;Rust from the Back to the Front&lt;/em&gt;, giving an overview of the ecosystem around all things related to web programming in Rust.
This was an updated talk of the one I gave in Budapest last year (&lt;a href=&quot;https://www.youtube.com/watch?v=L9sTIi7wFPo&quot;&gt;video online&lt;/a&gt;).
I had some technical difficulties this time in the beginning (yeah, computers…), but otherwise the talk went well.
People showed interest in the presented topics.
Sadly I only briefly touched the new way of doing asynchronous I/O using &lt;a href=&quot;https://github.com/alexcrichton/futures-rs&quot;&gt;futures&lt;/a&gt; and &lt;a href=&quot;https://github.com/tokio-rs&quot;&gt;tokio&lt;/a&gt;.
I definitely need to look deeper into this topic, as I think it can bring huge improvements to existing web frameworks and libraries as well.
This has to wait a bit though, as I will first dive deeper into Emscripten (and present that &lt;a href=&quot;http://rustaceans.cologne/2016/09/05/compile-to-js.html&quot;&gt;next week in Cologne&lt;/a&gt; and in &lt;a href=&quot;http://www.rust-belt-rust.com/&quot;&gt;Pittsburgh in October&lt;/a&gt;).
My slides are &lt;a href=&quot;https://badboy.github.io/rust-sthlm/&quot;&gt;online&lt;/a&gt; and I will try to collect more &lt;a href=&quot;https://gist.github.com/badboy/ba039333b8716c29d6038ef211ccd8e3&quot;&gt;resources in a Gist&lt;/a&gt;.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;a href=&quot;//tmp.fnordig.de/rust-sthlm/2016-08-29_20.03.47.jpg&quot;&gt;&lt;img src=&quot;//tmp.fnordig.de/rust-sthlm/th-2016-08-29_20.03.47.jpg&quot; alt=&quot;Rust and openSUSE&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;The second talk that evening was by &lt;a href=&quot;https://github.com/krig&quot;&gt;Kristoffer Grönlund&lt;/a&gt;, giving us a quick introduction to some of Rust&#39;s features,
followed by an overview of his work trying to get Rust into the openSUSE package repositories.
Turns out it is not that easy, especially if everything has to be built from source and offline, but at least there are some improvements
that might help make this easier.
His slides are &lt;a href=&quot;http://www.kri.gs/presentation-rust-obs-sthlm-meetup/#/4/5&quot;&gt;online as well&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Even after the talks some of the people stuck around and we discussed several more things around Rust, how it is still evolving,
fast moving and a bit unstable from time to time.&lt;/p&gt;
&lt;p&gt;All in all I had a great time, talked to a number of people about differen topics and I hope I could convince some to actually try Rust.
With such a large and interested tech community in Stockholm, I&#39;m sure the Meetup will live on.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2016/08/31/rust-from-the-back-to-the-front</guid>
      <pubDate>Wed, 31 Aug 2016 16:30:00 +0200</pubDate>
    </item>
    <item>
      <title>Quick check: does your code work?</title>
      <link>https://fnordig.de/2016/05/12/quickcheck-does-your-code-work</link>
      <description>&lt;p&gt;… because mine didn&#39;t. At least not correctly in all cases.
I&#39;m talking about my Rust library &lt;a href=&quot;https://crates.io/crates/lzf&quot;&gt;lzf-rs&lt;/a&gt;,
a port of the small compression library &lt;a href=&quot;http://software.schmorp.de/pkg/liblzf.html&quot;&gt;LibLZF&lt;/a&gt;.
It started as a wrapper around the C library, but I rewrote it in Rust for v0.3.
I now found three major bugs and I want to tell you how (tl;dr: Bug fixes and tests: &lt;a href=&quot;https://github.com/badboy/lzf-rs/pull/1&quot;&gt;PR #1&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;For a university paper I&#39;m currently looking into different methods for automatic test generation,
such as &lt;em&gt;symbolic execution&lt;/em&gt;, &lt;em&gt;fuzzing&lt;/em&gt; and &lt;em&gt;random test generation&lt;/em&gt;.
One of the popular methods is property-based testing, with QuickCheck being the best known application of this method.
QuickCheck started as a Haskell library (see the &lt;a href=&quot;http://www.eecs.northwestern.edu/~robby/courses/395-495-2009-fall/quick.pdf&quot;&gt;original paper&lt;/a&gt;),
but is ported to several other languages, including C (see &lt;a href=&quot;https://github.com/silentbicycle/theft&quot;&gt;theft&lt;/a&gt;)
and of course Rust: &lt;a href=&quot;https://github.com/BurntSushi/quickcheck&quot;&gt;QuickCheck&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I knew this library for some time now, but never used it.
So today I decided to use it for my &lt;a href=&quot;https://crates.io/crates/lzf&quot;&gt;lzf&lt;/a&gt; crate.
Let me walk you through the process on how to use it.&lt;/p&gt;
&lt;p&gt;First, you need to add the dependency and load it in your code.
Add it to your &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[dev-dependencies]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;quickcheck = &amp;quot;0.2&amp;quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add this to your &lt;code&gt;src/lib.rs&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[cfg(test)]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;extern crate&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; quickcheck;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, you need to decide what property to test.
As the compression library needs data to compress and &lt;em&gt;valid&lt;/em&gt; data to decompress,
I decided the easiest way to go through everything would be to test the round trip:
Compress some random input, then decompress the compressed data and check that it maches the initial input.
This should hold for all inputs, that can be compressed.
Everything that cannot be compressed can be ignored at this point (a first test allowing &lt;em&gt;all&lt;/em&gt; input turned up too many false-positives).&lt;/p&gt;
&lt;p&gt;The property function looks like this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;quickcheck::{quickcheck, TestResult};
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;compress_decompress_round&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(data: Vec&amp;lt;&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;gt;) -&amp;gt; TestResult {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; compr &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= match &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;compress&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;data) {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Ok&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(compr) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; compr,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Err&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(LzfError::NoCompressionPossible) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; return &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;TestResult::discard(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Err&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(LzfError::DataCorrupted) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; return &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;TestResult::discard(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        e &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;@ _ =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;panic!(e),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    };
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; decompr &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;decompress&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;compr, data.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;()).&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    TestResult::from_bool(data &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; decompr)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course we need to test this.
QuickCheck handles the heavy part for us:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[test]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;qc_roundtrip&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;quickcheck&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(compress_decompress_round &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;as fn&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running the tests immediately turned up a bug:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ cargo test
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;running 13 tests
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;...
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;thread &amp;#39;safe&amp;#39; panicked at &amp;#39;index out of bounds: the len is 67 but the index is 67&amp;#39;, ../src/libcollections/vec.rs:1187
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;test quickcheck_test::qc_roundtrip ... FAILED
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;failures:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;---- quickcheck_test::qc_roundtrip stdout ----
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    thread &amp;#39;quickcheck_test::qc_roundtrip&amp;#39; panicked at &amp;#39;[quickcheck] TEST FAILED (runtime error). Arguments: ([0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, 4, 0, 0, 5, 0, 0, 6, 0, 0, 7, 0, 0, 8, 0, 0, 9, 0, 0, 10, 0, 0, 11, 0, 1, 5, 0, 1, 6, 0, 1, 7, 0, 1, 8, 0, 1, 9, 0, 1, 10, 0, 0])
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Error: &amp;quot;index out of bounds: the len is 67 but the index is 67&amp;quot;&amp;#39;, /home/jer/.cargo/registry/src/github.com-88ac128001ac3a9a/quickcheck-0.2.27/src/tester.rs:116
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It would be okay to return an error, but out-of-bounds indexing (and thus panicing) is a clear bug in the library.
Luckily, QuickCheck automatically collects the input the test failed on, tries to shrink it down to a minimal example and then displays it.
I figured this bug is happening in the compress step, so I added an explicit test case for that:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[test]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;quickcheck_found_bug&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; inp &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;vec![&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;11&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;];
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    assert_eq!(LzfError::NoCompressionPossible, &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;compress&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;inp).&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap_err&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;());
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Taking a look at the full stack trace (run &lt;code&gt;RUST_BACKTRACE=1 cargo test&lt;/code&gt;) lead to the exact location of the bug.
Turns out I was checking the bounds on the wrong variable.
I fixed it in &lt;a href=&quot;https://github.com/badboy/lzf-rs/commit/88242ffef3b00423572db66318becd5206880d94&quot;&gt;88242ffe&lt;/a&gt;.
After this fix, I re-run the QuickCheck tests and it discovered a second bug (&lt;code&gt;[0]&lt;/code&gt; lead to another out-of-bounds access) and I fixed it in &lt;a href=&quot;https://github.com/badboy/lzf-rs/pull/1/commits/5b2e81506e83a797519d5d85c776de296769fdd3&quot;&gt;5b2e8150&lt;/a&gt;.
I found a third bug, which I (hopefully) fixed, but I don&#39;t fully understand how it&#39;s happening yet.&lt;/p&gt;
&lt;p&gt;Additionally to the above I added QuickCheck tests comparing the Rust functions to the output of the C library.
The full changeset is in &lt;a href=&quot;https://github.com/badboy/lzf-rs/pull/1&quot;&gt;PR #1&lt;/a&gt; (currently failing tests, because of a broken Clippy on newest nightly).&lt;/p&gt;
&lt;p&gt;Now quick, check your own code!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2016-05-13:&lt;/strong&gt; QuickCheck can be added as a dev dependency, instead of making it optional and activating it with a feature. Additionally it&#39;s necessary to &lt;code&gt;use&lt;/code&gt; names from the crate (or specify the full path). Thanks to RustMeUp and burntsushi in the &lt;a href=&quot;https://www.reddit.com/r/rust/comments/4j2va3/quick_check_does_your_code_work/&quot;&gt;reddit thread&lt;/a&gt;.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2016/05/12/quickcheck-does-your-code-work</guid>
      <pubDate>Thu, 12 May 2016 23:00:00 +0200</pubDate>
    </item>
    <item>
      <title>Releasing Rust projects, the automatic way</title>
      <link>https://fnordig.de/2016/03/29/releasing-rust-projects-the-automatic-way</link>
      <description>&lt;p&gt;One of the strength of the Rust ecosystem is its package manager &lt;a href=&quot;https://github.com/rust-lang/cargo&quot;&gt;Cargo&lt;/a&gt; and the package system &lt;a href=&quot;https://crates.io/&quot;&gt;crates.io&lt;/a&gt;.
Pulling in some dependencies is as easy as adding it to your projects&#39; &lt;code&gt;Cargo.toml&lt;/code&gt; and running &lt;code&gt;cargo build&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Releasing your own project is nearly as easy. Make sure you got everything working, add a version number in your &lt;code&gt;Cargo.toml&lt;/code&gt; and run &lt;code&gt;cargo publish&lt;/code&gt;.
It will package the code and upload it.&lt;/p&gt;
&lt;p&gt;Of course that&#39;s not the whole story.
For a proper release that people will like to use you want to follow some good practices:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Have tests and make sure they are green. Most people already use &lt;a href=&quot;https://travis-ci.org&quot;&gt;Travis CI&lt;/a&gt;. The &lt;a href=&quot;https://github.com/huonw/travis-cargo&quot;&gt;travis-cargo&lt;/a&gt; project makes it easy to test all channels (stable, beta, nightly, maybe a specific version), run documentation tests and upload coverage info and documentation.&lt;/li&gt;
&lt;li&gt;Keep a changelog. Your software is not done with the first release. It changes, bugs get fixed, new features get introduced. Keeping a changelog helps users to understand what changed from version to version.&lt;/li&gt;
&lt;li&gt;Pick a version number. This is not nearly as easy as it sounds. Your project&#39;s version number carries a lot of information. Often more than we&#39;d like. The Rust ecosystem recommends to strictly follow &lt;a href=&quot;http://semver.org/&quot;&gt;semver&lt;/a&gt;, but even that has ambiguities and requires a lot of thinking to do the right thing.&lt;/li&gt;
&lt;li&gt;Release on the right platforms. Even though &lt;a href=&quot;https://crates.io/&quot;&gt;crates.io&lt;/a&gt; is the package system you want your project in, having a GitHub release is a nice to have. Maybe your project is an application and you want to distributed pre-compiled binaries.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At the moment a lot of people process each of these steps manually.
Maybe they have a few scripts lying around that help in reducing the number of errors that can happen.
All in all there&#39;s still to much manual work required.
It does not have to be that way.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/boennemann&quot;&gt;Stephan Bönnemann&lt;/a&gt; build &lt;a href=&quot;https://github.com/semantic-release/semantic-release&quot;&gt;semantic-release&lt;/a&gt; for the npm eco system a while ago.
It allows for fully automated package publishing by relying on a few conventions and a lot of automatisation.&lt;/p&gt;
&lt;p&gt;I wanted to have a similar thing for the Rust eco system. That&#39;s why Jan aka &lt;a href=&quot;https://twitter.com/neinasaservice&quot;&gt;@neinasaservice&lt;/a&gt; and I sat down at last year&#39;s 32c3 and started hacking on a tool to achieve that.&lt;/p&gt;
&lt;p&gt;It took us a while to get something working, but now I can present to you:&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;https://github.com/semantic-rs/semantic-rs&quot;&gt;&lt;center&gt;🚀 semantic-rs 🚀&lt;/center&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h2&gt;What is it?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/semantic-rs/semantic-rs&quot;&gt;semantic-rs&lt;/a&gt; gives you fully automatic crate publishing.
It runs after your tests are finished, analyzes the latest commits, picks out a version number, creates a commit and git tag, creates a release on GitHub and publishes your crate on crates.io.&lt;/p&gt;
&lt;p&gt;All you have to do is follow the &lt;a href=&quot;https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit?pref=2&amp;amp;pli=1#heading=h.uyo6cb12dt6w&quot;&gt;Angular.js commit message conventions&lt;/a&gt;, which are really easy.
Your commit message consists of a type, an optional scope, a subject and an optional body.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;lt;type&amp;gt;(&amp;lt;scope&amp;gt;): &amp;lt;subject&amp;gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;lt;BLANK LINE&amp;gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The type should be one of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;feat&lt;/strong&gt;:     A new feature&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fix&lt;/strong&gt;:      A bug fix&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;docs&lt;/strong&gt;:     Documentation only changes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;style&lt;/strong&gt;:    White-space, formatting, missing semi-colons, etc&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;refactor&lt;/strong&gt;: A code change that neither fixes a bug nor adds a feature&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;perf&lt;/strong&gt;:     A code change that improves performance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;test&lt;/strong&gt;:     Adding missing tests&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;chore&lt;/strong&gt;:    Changes to the build process or auxiliary tools/libraries/documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The next version number is decided depending on type of commits since the last release.
A &lt;strong&gt;feat&lt;/strong&gt; will trigger a minor version bump, a &lt;strong&gt;fix&lt;/strong&gt; a patch version bump.
The other types don&#39;t cause a release.&lt;/p&gt;
&lt;p&gt;However, should you make a breaking change, you need to document this in the commit message as well.
Include &lt;strong&gt;BREAKING CHANGE&lt;/strong&gt; in the body of the commit message and add information what changed
and how to change existing code to make it work again (if possible).
This will then trigger a major version bump.&lt;/p&gt;
&lt;h2&gt;What works?&lt;/h2&gt;
&lt;p&gt;The &lt;strong&gt;Happy Path&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If everything is configured properly and the tests succeed, semantic-rs will correctly pick a version,
add changes to a &lt;code&gt;Changelog.md&lt;/code&gt;, create a release commit, tag it, create a GitHub release and publish on crates.io.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://crates.io/crates/test-project&quot;&gt;test-project&lt;/a&gt; crate is published completely automatically now.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;semantic-rs&lt;/code&gt; already has some safety features integrated.
It will only run when the build is on the master branch (or the branch you configure),
and it will make sure that it only runs once on the build leader (which is always the first job in your build matrix).
It also waits for the other jobs to finish and succeed before trying to do a release.&lt;/p&gt;
&lt;h2&gt;What&#39;s missing?&lt;/h2&gt;
&lt;p&gt;In case of problems, semantic-rs will just bail out.
That might leave you with changes pushed to GitHub, but not published on crates.io (at worst),
or with no visible changes but no new release (at best).
We&#39;re working hard on making this safer to use with better error reporting.&lt;/p&gt;
&lt;p&gt;Installing &lt;code&gt;semantic-rs&lt;/code&gt; from source each time your tests run adds significant overhead to the build time, as it must be compiled again and again.
In the future we will provide binary releases that you can simpy drop into Travis and it will work.&lt;/p&gt;
&lt;p&gt;It&#39;s not released on crates.io yet, because we&#39;re using a dependency from GitHub. That one should soon be fixed once they push out a release as well.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Now that we got that out of the way, let&#39;s see how to actually use it.&lt;/p&gt;
&lt;h2&gt;How to use it&lt;/h2&gt;
&lt;p&gt;Right now usage of &lt;code&gt;semantic-rs&lt;/code&gt; is not as straight-forward as it can be, we&#39;re working on that.
To run it on Travis you have to follow these manual steps.&lt;/p&gt;
&lt;p&gt;The first job of your build matrix will be used to do the publish, so make sure it is a full build.
Make it your stable build to be on the safe side.
Your &lt;code&gt;.travis.yml&lt;/code&gt; should contain this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;rust&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;stable
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;beta
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;nightly
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, install &lt;code&gt;semantic-rs&lt;/code&gt; on Travis by adding this to your &lt;code&gt;.travis.yml&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;before_script&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;|
&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;      cargo install --git https://github.com/semantic-rs/semantic-rs --debug &amp;amp;&amp;amp;
&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;      export PATH=$HOME/.cargo/bin:$PATH &amp;amp;&amp;amp;
&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;      git config --global user.name semantic-rs &amp;amp;&amp;amp;
&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;      git config --global user.email semantic@rs
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(This installs &lt;code&gt;semantic-rs&lt;/code&gt; in debug mode, which is quite a lot faster to compile without significant runtime impact at the moment)&lt;/p&gt;
&lt;p&gt;This will also set a git user and mail address, which will be used to create the git tag.
You can change this to your own name and email address.&lt;/p&gt;
&lt;p&gt;Now add a &lt;a href=&quot;https://github.com/settings/tokens&quot;&gt;personal access token&lt;/a&gt; from GitHub.
It only needs the &lt;code&gt;public_repo&lt;/code&gt; permission (unless of course your repository is private).&lt;/p&gt;
&lt;p&gt;Add it to your &lt;code&gt;.travis.yml&lt;/code&gt; encrypted:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ travis encrypt GH_TOKEN=&amp;lt;your token here&amp;gt; --add env.global
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To release on &lt;a href=&quot;https://crates.io/&quot;&gt;crates.io&lt;/a&gt; you need a token as well. Get it &lt;a href=&quot;https://crates.io/me&quot;&gt;from your account settings&lt;/a&gt; and add it to your &lt;code&gt;.travis.yml&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ travis encrypt CARGO_TOKEN=&amp;lt;your token here&amp;gt; --add env.global
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At last make sure &lt;code&gt;semantic-rs&lt;/code&gt; runs after the tests succeeds. Add this to the &lt;code&gt;.travis.yml&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;after_success&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;semantic-rs
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure to follow the &lt;a href=&quot;https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit?pref=2&amp;amp;pli=1#heading=h.uyo6cb12dt6w&quot;&gt;AngularJS Git Commit Message Conventions&lt;/a&gt;.
&lt;code&gt;semantic-rs&lt;/code&gt; will use this convention to decide which should be the next release version.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&quot;https://github.com/badboy/test-project/blob/34246077dbf375d144f86a01711cbd9e527b11ea/.travis.yml&quot;&gt;the full &lt;code&gt;.travis.yml&lt;/code&gt;&lt;/a&gt; of our test project.&lt;/p&gt;
&lt;h2&gt;What&#39;s next?&lt;/h2&gt;
&lt;p&gt;We still have some plans for semantic-rs.&lt;/p&gt;
&lt;p&gt;First we need to make it more safe and easy to integrate into a project&#39;s workflow.&lt;/p&gt;
&lt;p&gt;We also want to look into how we can determine more information about a project to assist the developers.
Ideas we have include running integration tests from the previous version to detect breaking changes
and statically analyzing code changes to determine their impact. Rust&#39;s &lt;a href=&quot;https://github.com/rust-lang/rfcs/issues/1105&quot;&gt;RFC 1105&lt;/a&gt; already defines the impact certain changes should have. Maybe it is possible to automatically check some of these things.&lt;/p&gt;
&lt;p&gt;We would be happy to hear from you. If semantic-rs breaks or otherwise does not fit into your workflow, let us know. &lt;a href=&quot;https://github.com/semantic-rs/semantic-rs/issues/new&quot;&gt;Open an issue&lt;/a&gt; to discuss this.
If you want to use it and have more ideas what is necessary or could be improved, talk to us!&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2016/03/29/releasing-rust-projects-the-automatic-way</guid>
      <pubDate>Tue, 29 Mar 2016 20:47:00 +0200</pubDate>
    </item>
    <item>
      <title>Load your config into your environment</title>
      <link>https://fnordig.de/2016/03/04/load-your-config-into-your-environment</link>
      <description>&lt;p&gt;It became quite popular to store certain configuration variables in your environment, to be later loaded by your aplication.
This way of &lt;a href=&quot;http://12factor.net/config&quot;&gt;having all configuration&lt;/a&gt; available is part of the &lt;a href=&quot;http://12factor.net/&quot;&gt;twelve-factor app definition&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The idea is to place your variables in a &lt;code&gt;.env&lt;/code&gt; file and load this as environment variables to be accessed by your application.
Most of the time you can just plug in one of the dozens of libraries that load this config from a file and your application can fetch the values as normal from the environment.&lt;/p&gt;
&lt;p&gt;But sometimes you might want to have this config loaded into your shell or some other interactive tool.
That&#39;s where you can use &lt;code&gt;dotenv-shell&lt;/code&gt;, a small tool, written in Rust.
It wraps around &lt;a href=&quot;https://github.com/slapresta/rust-dotenv&quot;&gt;rust-dotenv&lt;/a&gt; and allows to load the config and then execute a program (your shell by default).&lt;/p&gt;
&lt;p&gt;First install the tool:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo install dotenv-shell
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file with your config:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;echo &amp;quot;REDIS_URL=redis://localhost:6379&amp;quot; &amp;gt; .env
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then start a shell and you can access the configuration as environment variables:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ dotenv-shell
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ echo $REDIS_URL
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;redis://localhost:6379
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course you can launch whatever tool you want:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ dotenv-shell /usr/bin/irb
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;irb(main):001:0&amp;gt; ENV[&amp;#39;REDIS_URL&amp;#39;]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt; &amp;quot;redis://localhost:6379&amp;quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/badboy/dotenv-shell&quot;&gt;Available on GitHub&lt;/a&gt; and &lt;a href=&quot;https://crates.io/crates/dotenv-shell&quot;&gt;as a Crate&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Only now I learn about another application doing just the same: &lt;a href=&quot;https://github.com/timonv/benv&quot;&gt;benv&lt;/a&gt; by &lt;a href=&quot;https://twitter.com/timonvonk&quot;&gt;@timonvonk&lt;/a&gt;.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2016/03/04/load-your-config-into-your-environment</guid>
      <pubDate>Fri, 04 Mar 2016 12:30:00 +0100</pubDate>
    </item>
    <item>
      <title>Create GitHub releases with Rust using Hubcaps</title>
      <link>https://fnordig.de/2016/02/23/create-releases-using-hubcaps-a-rust-library</link>
      <description>&lt;p&gt;For one of my projects I need to access the GitHub API to create releases.
Luckily, through reading &lt;a href=&quot;https://this-week-in-rust.org/blog/2016/02/22/this-week-in-rust-119/&quot;&gt;This Week in Rust #119&lt;/a&gt;, I discovered &lt;a href=&quot;https://github.com/softprops/hubcaps&quot;&gt;Hubcaps&lt;/a&gt;, a library for interfacing with GitHub.&lt;/p&gt;
&lt;p&gt;Though it lacks some documentation and is not yet fully finished, it already provides APIs for the relevant parts regarding releases.&lt;/p&gt;
&lt;p&gt;On GitHub a release is always associated with a &lt;a href=&quot;https://git-scm.com/book/en/v2/Git-Basics-Tagging&quot;&gt;Git tag&lt;/a&gt;, but need to be specifially created to be shown on the site with the full description and optional assets attached to them.
It is also possible to mark releases as a draft (then it is only visible to repo contributors) or as a pre-release, useful for alpha releases of a library or application.&lt;/p&gt;
&lt;p&gt;Once you have a Git tag in your repository the API can be used to create an associated release using the following Rust code:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;extern crate&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; hyper;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;extern crate&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; hubcaps;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::{env, process};
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;hyper::Client;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;hubcaps::{Github, ReleaseOptions};
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; token &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= match &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;env::var(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;GITHUB_TOKEN&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;ok&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Some&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(token) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; token,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;_ =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            println!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;example missing GITHUB_TOKEN&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            process::exit(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    };
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; client &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Client::new();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; github &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Github::new(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;hubcaps/0.1.1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;client, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Some&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(token));
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; user &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;username&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; repo &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;my-library&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; name &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;ONE DOT OH&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; body &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;This is a long long body&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; tag &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;v1.0.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; opts &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;ReleaseOptions::builder(tag)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(name)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(body)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;commitish&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;master&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;draft&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;prerelease&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; repo &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; github.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;repo&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(user, repo);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; release &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; repo.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;releases&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; release.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;create&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;opts) {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Ok&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;println!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;Release created&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Err&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(e) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;println!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;Failed to create release: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;{:?}&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, e),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    };
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you clone &lt;a href=&quot;https://github.com/softprops/hubcaps&quot;&gt;Hubcaps&lt;/a&gt; and put the above code in a file named &lt;code&gt;releases.rs&lt;/code&gt; into the &lt;code&gt;examples/&lt;/code&gt; folder, you can run it with &lt;code&gt;cargo run --example releases&lt;/code&gt;.
You need to get a &lt;a href=&quot;https://github.com/settings/tokens&quot;&gt;personal access token&lt;/a&gt; first and set it in your environment (&lt;code&gt;export GITHUB_TOKEN=&amp;lt;your token here&amp;gt;&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;Of course it has the repository and tag hard-coded, but this is easy to adapt.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The code was tested with Rust 1.6 and hubcaps 0.1.1&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://gist.github.com/badboy/0cbc3411b6c23c1cb33c&quot;&gt;Updated version&lt;/a&gt; to work with hubcaps 0.2.0 online.&lt;/em&gt;&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2016/02/23/create-releases-using-hubcaps-a-rust-library</guid>
      <pubDate>Tue, 23 Feb 2016 20:32:00 +0100</pubDate>
    </item>
    <item>
      <title>omnomnom - Parsing ISO8601 dates using nom</title>
      <link>https://fnordig.de/2015/07/16/omnomnom-parsing-iso8601-dates-using-nom</link>
      <description>&lt;p&gt;&lt;strong&gt;Update 2018-07-01:&lt;/strong&gt; This article was updated in 2018 and is &lt;a href=&quot;https://github.com/badboy/iso8601/blob/338b3d1a9ca220372292f631a3bc2e5176cca331/docs/parsing-iso8601-dates-using-nom.md&quot;&gt;now available as documentation in the iso8601 repository&lt;/a&gt;.
Thanks to &lt;a href=&quot;https://github.com/ccouzens&quot;&gt;Chris Couzens&lt;/a&gt; for the updates.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;There are thousands of ways to note down a date and time.
The international date format is standardized as &lt;a href=&quot;https://en.wikipedia.org/wiki/ISO_8601&quot;&gt;ISO8601&lt;/a&gt;, though it still allows a widespread of different formats.&lt;/p&gt;
&lt;p&gt;The basic format looks like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;2015-07-02T19:45:00+0100&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And that&#39;s what we will parse today using &lt;a href=&quot;https://github.com/Geal/nom&quot;&gt;nom&lt;/a&gt;,
a parser combinator library created by &lt;a href=&quot;https://twitter.com/gcouprie&quot;&gt;Geoffroy Couprie&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The idea is that you write small self-contained parsers, which all do only one simple thing, like parsing the year in our string, and then combine these small parsers to a bigger one to parse the full format.
&lt;code&gt;nom&lt;/code&gt; comes with a wide variety of small parsers: handling different integers, reading simple byte arrays, optional fields, mapping parsed data over a function, ...
Most of them are provided as combinable macros.
It&#39;s very easy to implement your own small parsers, either by providing a method that handles a short byte buffer or by combining existing parsers.&lt;/p&gt;
&lt;p&gt;So let&#39;s dive right in and see how to use nom in real code.&lt;/p&gt;
&lt;h3&gt;Analysis&lt;/h3&gt;
&lt;p&gt;This is what we want to parse:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;2015-07-02T19:45:00+0100&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It has several parts we need to parse:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;YYYY-MM-DDTHH:MM:SS+OOOO&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;with the following meaning:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Characters&lt;/th&gt;&lt;th&gt;Meaning&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;YYYY&lt;/td&gt;&lt;td&gt;The year, can be negative or null and can be extended if necessary&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;MM&lt;/td&gt;&lt;td&gt;Month from 1 to 12 (0-prefixed)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;DD&lt;/td&gt;&lt;td&gt;Day from 1 to 31 (0-prefixed)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;Separator between date and time&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;HH&lt;/td&gt;&lt;td&gt;Hour, 0-23 (0-prefixed)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;MM&lt;/td&gt;&lt;td&gt;Minutes, 0-59 (0-prefixed)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;SS&lt;/td&gt;&lt;td&gt;Seconds, 0-59 (0-prefixed)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;OOOO&lt;/td&gt;&lt;td&gt;Timezone offset, separated by a &lt;code&gt;+&lt;/code&gt; or &lt;code&gt;-&lt;/code&gt; sign or &lt;code&gt;Z&lt;/code&gt; for UTC&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Parts like the seconds and the timezone offset are optional. Datetime strings without them will default to a zero value for that field.
The date parts are separated by a dash (&lt;code&gt;-&lt;/code&gt;) and the time parts by a colon (&lt;code&gt;:&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;We will built a small parser for each of these parts and at the end combine them to parse a full date time string.&lt;/p&gt;
&lt;h3&gt;Parsing the date: 2015-07-16&lt;/h3&gt;
&lt;p&gt;Let&#39;s start with the sign. As we need it several times, we create its own parser for that.
Parsers are created by giving them a name, stating the return value (or defaulting to a byte slice) and the parser combinators to handle the input.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(sign &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;i32&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, alt!(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        tag!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;-&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{ |_| &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1 &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;|
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        tag!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;+&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{ |_| &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1 &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        )
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    );
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First, we parse either a plus or a minus sign.
This combines two already existing parsers: &lt;code&gt;tag!&lt;/code&gt;, which will match the given byte array (in our case a single character) and &lt;code&gt;alt!&lt;/code&gt;, which will try a list of parsers, returning on the first successful one.
We can directly map the result of the sub-parsers to either &lt;code&gt;-1&lt;/code&gt; or &lt;code&gt;1&lt;/code&gt;, so we don&#39;t need to deal with the byte slice later.&lt;/p&gt;
&lt;p&gt;Next we parse the year, which consists of an optional sign and 4 digits (I know, I know, it is possible to extend this to more digits, but let&#39;s keep it simple for now).&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(positive_year  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;i32&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, map!(call!(take_4_digits), buf_to_i32));
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; year &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;i32&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, chain!(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        pref: opt!(sign) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        y:    positive_year
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        ,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        || {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            pref.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap_or&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; y
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        }));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A lot of additional stuff here. So let&#39;s separate it.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(positive_year  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;i32&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, map!(call!(take_4_digits), buf_to_i32));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This creates a new named parser, that again returns the remaining input and an 32-bit integer.
To work, it first calls &lt;code&gt;take_4_digits&lt;/code&gt; and then maps that result to the corresponding integer (using a &lt;a href=&quot;https://github.com/badboy/iso8601/blob/master/src/helper.rs#L8&quot;&gt;small helper function&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;take_4_digits&lt;/code&gt; is another small helper parser. We also got one for 2 digits:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; take_4_digits, flat_map!(take!(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;), check!(is_digit)));
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; take_2_digits, flat_map!(take!(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;), check!(is_digit)));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This takes 4 (or 2) characters from the input and checks that each character is a digit.
&lt;code&gt;flat_map!&lt;/code&gt; and &lt;code&gt;check!&lt;/code&gt; are quite generic, so they are useful for a lot of cases.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; year &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;i32&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, chain!(
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The year is also returned as a 32-bit integer (there&#39;s a pattern!).
Using the &lt;code&gt;chain!&lt;/code&gt; macro, we can chain together multiple parsers and work with the sub-results.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        pref: opt!(sign) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        y:    positive_year
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our sign is directly followed by 4 digits. It&#39;s optional though, that&#39;s why we use &lt;code&gt;opt!&lt;/code&gt;.
&lt;code&gt;~&lt;/code&gt; is the concatenation operator in the &lt;code&gt;chain!&lt;/code&gt; macro.
We save the sub-results to variables (&lt;code&gt;pref&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;).&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        ,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        || {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            pref.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap_or&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; y
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        }));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To get the final result, we multiply the prefix (which comes back as either &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;-1&lt;/code&gt;) with the year.
Don&#39;t forget the &lt;code&gt;,&lt;/code&gt; (comma) right before the closure.
This is a small syntactic hint for the &lt;code&gt;chain!&lt;/code&gt; macro that the mapping function will follow and no more parsers.&lt;/p&gt;
&lt;p&gt;We can now successfully parse a year:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;assert_eq!(Done(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[][&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;2015&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;year&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;2015&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;));
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;assert_eq!(Done(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[][&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0333&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;year&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;-0333&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our nom parser will return an &lt;code&gt;IResult&lt;/code&gt;. If all went well, we get &lt;code&gt;Done(I,O)&lt;/code&gt; with &lt;code&gt;I&lt;/code&gt; and &lt;code&gt;O&lt;/code&gt; being the appropriate types.
For our case &lt;code&gt;I&lt;/code&gt; is the same as the input, a buffer slice (&lt;code&gt;&amp;amp;[u8]&lt;/code&gt;), and &lt;code&gt;O&lt;/code&gt; is the output of the parser itself, an integer (&lt;code&gt;i32&lt;/code&gt;).
The return value could also be an &lt;code&gt;Error(Err)&lt;/code&gt;, if something went completely wrong, or &lt;code&gt;Incomplete(u32)&lt;/code&gt;, requesting more data to be able to satisfy the parser (you can&#39;t parse a 4-digit year with only 3 characters input).&lt;/p&gt;
&lt;p&gt;Parsing the month and day is a bit easier now: we simply take the digits and map them to an integer:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; month &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u32&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, map!(call!(take_2_digits), buf_to_u32));
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; day   &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u32&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, map!(call!(take_2_digits), buf_to_u32));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All that&#39;s left is combining these 3 parts to parse a full date.
Again we can chain the different parsers and map it to some useful value:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; date &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], Date&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, chain!(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        y: year      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;           tag!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;-&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        m: month     &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;           tag!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;-&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        d: day
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        ,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        || { Date{ year: y, month: m, day: d }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        ));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Date&lt;/code&gt; is a &lt;a href=&quot;https://github.com/badboy/iso8601/blob/master/src/lib.rs#L19-23&quot;&gt;small struct&lt;/a&gt;, that can hold the necessary information, just as you would expect.&lt;/p&gt;
&lt;p&gt;And it already works:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;assert_eq!(Done(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[][&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], Date{ year: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;2015&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, month: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, day: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;16  &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}), &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;date&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;2015-07-16&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;));
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;assert_eq!(Done(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[][&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], Date{ year: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;333&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, month: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, day: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;11  &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}), &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;date&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;-0333-06-11&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Parsing the time: 16:43:52&lt;/h3&gt;
&lt;p&gt;Next, we parse the time. The individual parts are really simple, just some digits:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; hour   &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u32&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, map!(call!(take_2_digits), buf_to_u32));
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; minute &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u32&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, map!(call!(take_2_digits), buf_to_u32));
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; second &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u32&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, map!(call!(take_2_digits), buf_to_u32));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Putting them together becomes a bit more complex, as the &lt;code&gt;second&lt;/code&gt; part is optional:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; time &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], Time&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, chain!(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        h: hour      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;           tag!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;:&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        m: minute    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        s: empty_or!(chain!(tag!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;:&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; s:second , || { s }))
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        ,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        || { Time{ hour: h,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                   minute: m,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                   second: s.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap_or&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                   tz_offset: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;           }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        ));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, even &lt;code&gt;chain!&lt;/code&gt; parsers can be nested.
The sub-parts then must be mapped once for the inner parser and once into the final value of the outer parser.
&lt;code&gt;empty_or!&lt;/code&gt; returns an &lt;code&gt;Option&lt;/code&gt;. Either &lt;code&gt;None&lt;/code&gt; if there is no input left or it applies the nested parser. If this parser doesn&#39;t fail, &lt;code&gt;Some(value)&lt;/code&gt; is returned.&lt;/p&gt;
&lt;p&gt;Our parser now works for simple time information:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;assert_eq!(Done(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[][&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], Time{ hour: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, minute: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;43&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, second: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;52&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, tz_offset: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}), &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;16:43:52&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;));
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;assert_eq!(Done(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[][&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], Time{ hour: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, minute: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;43&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, second:  &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, tz_offset: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}), &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;16:43&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But it leaves out one important bit: the timezone.&lt;/p&gt;
&lt;h3&gt;Parsing the timezone: +0100&lt;/h3&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;2015-07-02T19:45:00-0500
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;2015-07-02T19:45:00Z
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;2015-07-02T19:45:00+01
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Above are three variants of valid dates with timezones.
The timezone in an ISO8601 string is either an appended &lt;code&gt;Z&lt;/code&gt;, indicating UTC,
or it&#39;s separated using a sign (&lt;code&gt;+&lt;/code&gt; or &lt;code&gt;-&lt;/code&gt;) and appends the offset from UTC in hours and minutes (with the minutes being optional).&lt;/p&gt;
&lt;p&gt;Let&#39;s cover the UTC special case first:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(timezone_utc &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;i32&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, map!(tag!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;Z&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;), |_| &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This should look familiar by now.
It&#39;s a simple &lt;code&gt;Z&lt;/code&gt; character, which we map to &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The other case is the sign-separated hour and minute offset.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(timezone_hour &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;i32&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, chain!(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        s: sign &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        h: hour &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        m: empty_or!(chain!(tag!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;:&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;? ~&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; m: minute , || { m }))
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        ,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        || { (s &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;* &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(h &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;as i32&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;* &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3600&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+ &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(m.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap_or&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;* &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;60&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;as i32 &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        ));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can re-use our already existing parsers and once again chain them to get what we want.
The minutes are optional (and might be separated using a colon).&lt;/p&gt;
&lt;p&gt;Instead of keeping this as is, we&#39;re mapping it to the offset in seconds.
We will see why later.
We could also just map it to a tuple like &lt;br&gt;&lt;code&gt;(s, h, m.unwrap_or(0))&lt;/code&gt; and handle conversion at a later point.&lt;/p&gt;
&lt;p&gt;Combined we get&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(timezone &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;i32&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, alt!(timezone_utc &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; timezone_hour));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Putting it all together&lt;/h3&gt;
&lt;p&gt;We now got individual parsers for the date, the time and the timezone offset.&lt;/p&gt;
&lt;p&gt;Putting it all together, our final datetime parser looks quite small and easy to understand:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;named!(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; datetime &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;], DateTime&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, chain!(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        d:   date      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;             tag!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;T&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        t:   time      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;~
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        tzo: empty_or!(call!(timezone))
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        ,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        || {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            DateTime{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                date: d,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                time: t.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;set_tz&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(tzo.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap_or&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        ));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing special anymore. We can now parse all kinds of date strings:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;datetime&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;2007-08-31T16:47+00:00&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;datetime&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;2007-12-24T18:21Z&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;datetime&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;2008-02-01T09:00:22+05&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But it will also parse invalid dates and times:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;datetime&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;2234-13-42T25:70Z&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this is fine for now. We can handle the actual validation in a later step.
For example, we could use &lt;a href=&quot;https://crates.io/crates/chrono&quot;&gt;chrono&lt;/a&gt;, a time library, &lt;a href=&quot;https://github.com/badboy/iso8601/blob/master/src/lib.rs#L65-L71&quot;&gt;to handle this for us&lt;/a&gt;.
Using chrono it&#39;s obvious why we already multiplied our timezone offset to be in seconds: this time we can just hand it off to chrono as is.&lt;/p&gt;
&lt;p&gt;The full code for this ISO8601 parser is available in &lt;a href=&quot;https://github.com/badboy/iso8601/blob/master/src/easy.rs&quot;&gt;easy.rs&lt;/a&gt;. The repository also includes &lt;a href=&quot;https://github.com/badboy/iso8601/blob/master/src/lib.rs&quot;&gt;a more complex parser&lt;/a&gt;, that does some validation while parsing
(it checks that the time and date are reasonable values, but it does not check that it is a valid date for example)&lt;/p&gt;
&lt;h3&gt;What&#39;s left?&lt;/h3&gt;
&lt;p&gt;These simple parsers or even some more complex ones are already usable.
At least if you already got all the data at hand and if a simple return value satisfies your needs.
But especially for larger and more complex formats like media files reading everything into memory and spitting out a single large value isn&#39;t sufficient at all.&lt;/p&gt;
&lt;p&gt;nom is prepared for that.
Soon it will become as easy as using an object from which nom can &lt;a href=&quot;http://doc.rust-lang.org/nightly/std/io/trait.Read.html&quot;&gt;&lt;code&gt;Read&lt;/code&gt;&lt;/a&gt;.
For most things you shouldn&#39;t worry about that, as a simple &lt;code&gt;BufReader&lt;/code&gt; will work.&lt;/p&gt;
&lt;p&gt;For the other end of the chain, nom has &lt;a href=&quot;https://github.com/Geal/nom#consumers&quot;&gt;Consumers&lt;/a&gt;.
A Consumer handles the complex part of actually requesting data, calling the right sub-parsers and holding the necessary state.
This is what you need to build yourself.
Internally it&#39;s best abstracted using some kind of state machine, so you always know which part of the format to expect next, how to parse it, what to return to the user and so on.
Take a look at &lt;a href=&quot;https://github.com/Geal/nom/blob/master/tests/mp4.rs&quot;&gt;the MP4 parser&lt;/a&gt;, which has an &lt;code&gt;MP4Consumer&lt;/code&gt; handling the different parts of the format.
Soon my own library, &lt;a href=&quot;http://rdb.fnordig.de/&quot;&gt;rdb-rs&lt;/a&gt;, will have this as well.&lt;/p&gt;
&lt;p&gt;Small thing aside: Geoffroy created &lt;a href=&quot;https://github.com/Geal/machine&quot;&gt;machine&lt;/a&gt; to define a state machine and I got &lt;a href=&quot;https://github.com/badboy/microstate&quot;&gt;microstate&lt;/a&gt; for this.&lt;/p&gt;
&lt;h3&gt;Why am I doing this?&lt;/h3&gt;
&lt;p&gt;I&#39;m currently developing &lt;a href=&quot;http://rdb.fnordig.de/&quot;&gt;rdb-rs&lt;/a&gt;, a library to parse and analyze Redis dump files.
It&#39;s currently limited to parsing and reformatting into several formats and can be mainly used as a CLI utility.
But &lt;a href=&quot;https://github.com/seppo0010/rsedis&quot;&gt;there are projects&lt;/a&gt; that could benefit from a nicer API to integrate it into another tool.
The current parser is hand-made. It&#39;s fast, it&#39;s working, but it provides a limited, not very extensible API.
I hope to get a proper parser done with nom, that I can build on to provide all necessary methods, while still being super-fast and memory-safe.
Work &lt;a href=&quot;https://github.com/badboy/rdb-rs/tree/nom-parser&quot;&gt;already started&lt;/a&gt;, but I&#39;m far from done for now&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://twitter.com/gcouprie&quot;&gt;Geoffroy&lt;/a&gt; for the discussions, the help and for reading a draft of this post.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2015/07/16/omnomnom-parsing-iso8601-dates-using-nom</guid>
      <pubDate>Thu, 16 Jul 2015 11:00:00 +0200</pubDate>
    </item>
    <item>
      <title>The difference of Rust&#39;s thread::spawn and thread::scoped</title>
      <link>https://fnordig.de/2015/03/05/the-difference-of-rust-s-spawn-and-scoped</link>
      <description>&lt;p&gt;So yesterday I gave a Rust introduction talk at the local hackerspace, &lt;a href=&quot;http://ccc.ac&quot;&gt;CCCAC&lt;/a&gt;.
The slides are already &lt;a href=&quot;https://fnordig.de/talks/2015/cccac/rust-intro/&quot;&gt;online&lt;/a&gt;.
The talk went pretty well and I think I could convince a few people why the ideas in Rust are actually useful.
Though I made one mistake in explaining a concurrency feature (see &lt;a href=&quot;https://fnordig.de/talks/2015/cccac/rust-intro/#29&quot;&gt;slide 30&lt;/a&gt;).
As it turns out, the example as I explained it was different from the presented code and one of the attendees actually asked me about it.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;// Careful, this example is not quite right.
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::thread;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::sync::{Arc, Mutex};
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; numbers &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Arc::new(Mutex::new(vec![&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;]));
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;in &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3 &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; number &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; numbers.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;clone&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let _ = &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;thread::scoped(|| {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; array &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; number.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            array[i] &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            println!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;numbers[&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;] is &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, i, array[i]);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        });
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I used this example to explain why it is necessary to wrap the vector in a mutex and the mutex in an Arc to make it possible to write to it from several threads.
The problem lies within the used thread abstraction: &lt;a href=&quot;http://doc.rust-lang.org/nightly/std/thread/fn.scoped.html&quot;&gt;thread::scoped&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Spawn a new scoped thread, returning a JoinGuard for it.
The join guard can be used to explicitly join the child thread (via join), returning Result&lt;T&gt;, or it will implicitly join the child upon being dropped.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So in the case of the above code each thread is joined right after it was created and thus the threads don&#39;t even run concurrently, making the Arc and Mutex unnecessary. The following shortened example will still work, though not show casing what I intended to:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::thread;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; numbers &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;vec![&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;];
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;in &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3 &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; number &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &amp;amp;mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; numbers;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let _ = &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;thread::scoped(|| {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            number[i] &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            println!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;numbers[&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;] is &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, i, number[i]);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        });
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is another in-built threading method: &lt;a href=&quot;http://doc.rust-lang.org/nightly/std/thread/fn.spawn.html&quot;&gt;thread::spawn&lt;/a&gt;. Its documentation reads:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Spawn a new thread, returning a JoinHandle for it.
The join handle will implicitly detach the child thread upon being dropped.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And this is actually what I need to correctly demonstrate what I wanted to: the use of Arc and Mutex to safely share writable access to shared memory through mutual exclusion. The following example works and has all necessary parts:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::thread;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::sync::{Arc, Mutex};
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; numbers &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Arc::new(Mutex::new(vec![&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;]));
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; threads &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;vec![];
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;in &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3 &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; number &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; numbers.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;clone&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; cur &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;thread::spawn(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;move|| &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; array &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; number.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            array[i] &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            println!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;numbers[&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;] is &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, i, array[i]);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        });
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        threads.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(cur);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; threads {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let _ =&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; i.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running it gives the expected output (your output might differ, the order is non-deterministic):&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ rustc concurrency.rs
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ ./concurrency
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;numbers[1] is 3
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;numbers[2] is 4
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;numbers[0] is 2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Rust book contains a complete chapter on this topic: &lt;a href=&quot;http://doc.rust-lang.org/book/concurrency.html&quot;&gt;Concurrency&lt;/a&gt;, covering a bit more of the background and also the Channel concept.&lt;/p&gt;
&lt;p&gt;Again, thanks to the &lt;a href=&quot;http://ccc.ac&quot;&gt;CCCAC&lt;/a&gt; and for all people listening to me and quite some questions afterwards.
For all who could not attend: the video should be up soon.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2015/03/05/the-difference-of-rust-s-spawn-and-scoped</guid>
      <pubDate>Thu, 05 Mar 2015 14:41:00 +0100</pubDate>
    </item>
    <item>
      <title>rdb-rs - fast and efficient RDB parsing utility</title>
      <link>https://fnordig.de/2015/01/15/rdb-rs-fast-and-efficient-rdb-parsing-utility</link>
      <description>&lt;p&gt;Ever since I started looking into &lt;a href=&quot;http://rust-lang.org/&quot;&gt;Rust&lt;/a&gt; I knew I needed a bigger project for which I could use it.
I released a &lt;a href=&quot;https://github.com/badboy/lzf-rs&quot;&gt;few&lt;/a&gt; &lt;a href=&quot;https://github.com/badboy/crc64-rs&quot;&gt;small&lt;/a&gt; &lt;a href=&quot;https://github.com/badboy/redlock-rs&quot;&gt;libraries&lt;/a&gt;, all based on Redis code/tools, so I figured:
Why not a bigger project focused on Redis as well?
We already have a nice &lt;a href=&quot;https://github.com/mitsuhiko/redis-rs&quot;&gt;client library&lt;/a&gt;, so I did not need to write one myself.
I then thought about writing a Cluster-aware library on top of that, but before I got any real code written I faced some difficulties in how I want the API to look like, so I abandonded the idea for now as well.
The next idea was to have another implementation of the Cluster configuration utility &lt;code&gt;redis-trib&lt;/code&gt;. Problem though: I did not even finish my attempt &lt;a href=&quot;https://github.com/badboy/redis-trib.go&quot;&gt;in Go&lt;/a&gt;.
I looked around for more ideas and then I came across the &lt;a href=&quot;https://github.com/sripathikrishnan/redis-rdb-tools&quot;&gt;redis-rdb-tools&lt;/a&gt; again.
This small Python utility can parse, format and analyze Redis&#39; dump files.
Its author Sripathi Krishnan also documented the &lt;a href=&quot;https://github.com/sripathikrishnan/redis-rdb-tools/wiki/Redis-RDB-Dump-File-Format&quot;&gt;file format&lt;/a&gt; and version history of RDB.&lt;/p&gt;
&lt;p&gt;Sripathi didn&#39;t pay much attention to his project anymore, and so some bugs and feature requests remained unsolved.
With the current changes for Redis 3.0 like the Quicklist and a new RDB version, the redis-rdb-tools can&#39;t be used anymore for new dump files without patches.&lt;/p&gt;
&lt;p&gt;So on last year&#39;s 31c3 I took some time and started reading and implementing a RDB parser in Rust based on the documentation.
While reading the documentation, the Python code as well as Redis&#39; own &lt;a href=&quot;https://github.com/antirez/redis/blob/unstable/src/rdb.c&quot;&gt;rdb.c&lt;/a&gt; I took notes and later rewrote and reformatted Sripathi&#39;s documentation to be up to date and to also include the latest changes.&lt;/p&gt;
&lt;p&gt;Today I release this updated documentation. It&#39;s available online at &lt;a href=&quot;http://rdb.fnordig.de/&quot;&gt;rdb.fnordig.de&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://rdb.fnordig.de/file_format.html&quot;&gt;RDB File Format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://rdb.fnordig.de/version_history.html&quot;&gt;RDB Version History&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will keep it updated, should there be need and of course I will improve it if necessary.&lt;/p&gt;
&lt;p&gt;At the same time I also open source my port of the redis-rdb-tools to Rust:&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;https://github.com/badboy/rdb-rs&quot;&gt;rdb-rs&lt;/a&gt;&lt;/h2&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;code&gt;rdb-rs&lt;/code&gt; is a library and tool to parse RDB and dump it into another format like JSON or the &lt;a href=&quot;http://redis.io/topics/protocol&quot;&gt;Redis protocol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rdb-rs&lt;/code&gt; is offered both as a library and as a stand-alone command line tool.&lt;/p&gt;
&lt;p&gt;The command line tool can be used to dump an existing RDB file in one of the provided formats:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ rdb --format json dump.rdb
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[{&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;key&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;value&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ rdb --format protocol dump.rdb
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;*2
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$6
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;SELECT
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$1
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;*3
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$3
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;SET
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$3
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;key
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$5
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;value
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For now it is nothing too fancy, but it gets the job done.
Over the next days and weeks I will improve it, add missing features such as filter options and hopefully also a memory reporter.&lt;/p&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;Using the library is as easy as calling the &lt;code&gt;rdb::parse&lt;/code&gt; function and pass it a stream to read from and a formatter to use.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::io::{BufferedReader, File};
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; file &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;File::open(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Path::new(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;dump.rdb&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;));
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; reader &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;BufferedReader::new(file);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;rdb::parse(reader, rdb::JSONFormatter::new());
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;rdb-rs&lt;/code&gt; brings 4 pre-defined formatters, which can be used:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PlainFormatter&lt;/code&gt;: Just plain output for testing&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JSONFormatter&lt;/code&gt;: JSON-encoded output&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NilFormatter&lt;/code&gt;: Surpresses all output&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ProtocolFormatter&lt;/code&gt;: Formats the data in &lt;a href=&quot;http://redis.io/topics/protocol&quot;&gt;RESP&lt;/a&gt;, the Redis Serialization Protocol&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Adding your own formatter is as easy as implementing the &lt;a href=&quot;http://rdb.fnordig.de/doc/rdb/formatter/trait.RdbParseFormatter.html&quot;&gt;RdbParseFormatter&lt;/a&gt; trait.&lt;/p&gt;
&lt;p&gt;Over the next weeks I will rework parts of the library. Currently I&#39;m not too happy with the API offered, especially proper return values and error handling.
The code also needs to be refactored to allow for filtering and memory reporting.
For the &lt;code&gt;redis-rdb-tools&lt;/code&gt; Sripathi also reverse-engineered and documented the memory usage of key-value pairs, which needs updates as well.
This will take me some time to bring into the same format.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Finally, I want to say thanks to Sripathi Krishnan for building the rdb-tools and for the proper and very well written documentation. It helped a lot getting this done.&lt;/p&gt;
&lt;p&gt;Also thanks to &lt;a href=&quot;https://twitter.com/mattsta&quot;&gt;Matt&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/andygrunwald&quot;&gt;Andy&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/itamarhaber&quot;&gt;Itamar&lt;/a&gt; for some input and comments on the small parts of the project I showed them.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2015/01/15/rdb-rs-fast-and-efficient-rdb-parsing-utility</guid>
      <pubDate>Thu, 15 Jan 2015 23:50:00 +0100</pubDate>
    </item>
    <item>
      <title>The story of my childhood or: Rust on the PSP</title>
      <link>https://fnordig.de/2014/12/03/a-story-of-hacking-or-rust-on-the-psp</link>
      <description>&lt;hr /&gt;
&lt;p&gt;Don&#39;t care for all the stuff of my childhood? &lt;a href=&quot;#more-rust&quot;&gt;↓ Head down&lt;/a&gt; to see the Rust part&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Let&#39;s do a time travel.&lt;/p&gt;
&lt;p&gt;10 years back, it&#39;s 2004.
Sony releases the first version of the &lt;a href=&quot;http://en.wikipedia.org/wiki/PlayStation_Portable&quot;&gt;Playstation Portable&lt;/a&gt;.
First in Japan, 4 months later in the US and yet another half year later in the EU (including Germany).&lt;/p&gt;
&lt;p&gt;I read about this new little device in the autumn of 2004 and I knew immediately: I want this.
I also knew: I can&#39;t wait a whole year for it to get to the German market.
So 13-year old me sat down in front of his parent&#39;s PC and started searching through the depths of the internets.
Well, mostly Ebay, because that seemed to be the best place to get brand new hardware.&lt;/p&gt;
&lt;p&gt;It must have been around January or February that I finally found a more or less trustworthy looking offer that was not too expensive.
Just 4 days after clicking &lt;em&gt;Buy&lt;/em&gt; on Ebay my PSP finally arrived (yes, just 4 days shipping straight from Japan) and I could unpack it.&lt;/p&gt;
&lt;p&gt;But I couldn&#39;t do much more. D&#39;oh! The first firmware version on the PSP was quite limited.
It only supported WEP, luckily we still had WEP set up at home.
The next problem: it didn&#39;t even include a web browser yet, so even though I had a Wifi connection, I couldn&#39;t use it.
On to the next problem: Music and videos. Well, Music worked sort of (this was becoming my most expensive MP3 player at that time).
Videos were another story. It only supported MP4 in some weird encoding formats and the only way to get it on the PSP was by using a Memory Stick Pro, one of these tiny little memory cards that only Sony used. They were really expensive, the PSP came with a 32 MB card and I scraped together all my left pocket money to get a 128 MB card. Even back then that was quite limited space. So videos were off the hook as well.&lt;/p&gt;
&lt;p&gt;Afterall the PSP was a gaming device, so I should be able to play right?
Yeah, actually for me that was a small afterthought, I didn&#39;t buy a game together with the PSP.
Off to Ebay again, luckily I found the original &lt;a href=&quot;http://en.wikipedia.org/wiki/Ridge_Racer_(2004_video_game)&quot;&gt;Ridge Racer&lt;/a&gt;, of course the Japanese version. Even now I would say: This was the best game ever released for the PSP. The graphics were astonishing, the music, the gameplay was fantastic, the rising dificulty of tracks and opponents promised hours of fun (and frustration).&lt;/p&gt;
&lt;p&gt;While I played this game for hours, other people used their valuable time for far more important things: Hacking the PSP. Successfully.&lt;/p&gt;
&lt;p&gt;Firmware 1.0 and 1.5 were exploited just 6 months after the first release.
What followed was the big uprise of the Homebrew scene. And I was part of it.
Younger me already knew some HTML, some (frontend) Javascript and I just learned C and C++.
I wanted to use that knowledge for my first own and publicly released apps!
The first step was getting the development toolchain set up.
I had an old 600 MHz computer, running Windows XP (I guess, or was it still Windows 98?)
The toolchain was based on GCC and was optimized for POSIX environments, which Windows clearly isn&#39;t,
but someone invested enough time to get it working on &lt;a href=&quot;https://www.cygwin.com/&quot;&gt;cygwin&lt;/a&gt;, including a nice one-click installer that did most of the work.
This was the time before Google Code and long before GitHub, so you had to download pre-compiled EXE files from one-click hoster sites.
The links could be found in one of the dozen forums that existed back then.
The whole process to setup Cygwin and the PSP toolchain on my slow computer took nearly 24 hours, so I had to leave the computer on over night (a novelty back then for me). And it failed quite often. So repeat and repeat until it finishes without any failure once.&lt;/p&gt;
&lt;p&gt;In the end I got it working and went on developing for the PSP.
I learned C, I battled with C, I switched over to C++ and back to C, I threw in some Lua (Lua was one of the first bigger things fully ported to the PSP and thus the best option to quickly develop for the PSP).&lt;/p&gt;
&lt;p&gt;The PSP scene was also the first online community I was part of.
I became a moderator and blogger of one of the bigger German PSP news sites, portable-news.de.
I became friends with people that later offered me my first job as a developer (thanks &lt;a href=&quot;https://twitter.com/g33konaut&quot;&gt;@g33konaut&lt;/a&gt;),
that I still see once or twice a year (thanks &lt;a href=&quot;https://twitter.com/atsutane_&quot;&gt;@atsutane&lt;/a&gt;), and others that I never heard anything of again (I&#39;m bad with names, I can&#39;t even remember much more from back then).&lt;/p&gt;
&lt;p&gt;The biggest released application from my time as a PSP dev is probably the PSP Customizer.
A release post on &lt;a href=&quot;http://www.logic-sunrise.com/forums/files/file/728-271-se-a-customizer-v05b-psp/&quot;&gt;some french forum is still online&lt;/a&gt; and of course &lt;a href=&quot;http://dl.qj.net/psp/homebrew-applications/fw302-oe-customizer-v10.html&quot;&gt;v1.0 on the good old qj.net&lt;/a&gt;.
The PSP Customizer could be used to change the boot screen, the menu backgrounds, change menu texts or dump and restore your flash registry (this contained some internal config I guess).
Nothing fancy, it was not even originally written by me (though I ended up rewritting most of it).
As the text on QJ suggests it was quite known around the community and people actually used it.
Sadly I don&#39;t have any code of it anymore.
It wasn&#39;t open source (before GitHub publishing code was really a big hassle), it wasn&#39;t even version-controlled.
I remember a day where I deleted the &lt;em&gt;whole&lt;/em&gt; project by mistake.
It must have been just before another release. I spent the whole night trying to recover as much as possible.
In the end I had to rewrite large parts off my head (luckily it wasn&#39;t the most complicated code).&lt;/p&gt;
&lt;p&gt;I also wrote some other small applications, most of which I can&#39;t even remember.
What I can remember is a PoC of a round-based tactics game, written as a web app (HTML and some crude Javascript magic to work in the limited web browser on the PSP) and inspired by &lt;a href=&quot;http://en.wikipedia.org/wiki/Field_Commander&quot;&gt;Field Commander&lt;/a&gt;. I never finished it or showed it to anyone.&lt;/p&gt;
&lt;p&gt;The only application I still have the source code of is the first-ever Twitter client for the PSP: &lt;a href=&quot;https://github.com/badboy/p-twit&quot;&gt;p-twit!&lt;/a&gt;.
I published the code 5 years ago, probably one of the more horrible pieces of code I&#39;ve got online.
The original p-twit! announcement:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;@badboy_: tada! twitter via PSP! release soon
(&lt;a href=&quot;https://twitter.com/badboy_/status/826911057&quot;&gt;tweet&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That was also the last thing I wrote for the PSP.
I think 2008/2009 was also the time the homebrew scene slowed down.
My community place, portable-news.de, was dead, more and more devs lost interest, there was nothing entirely new to be done.
Smartphones became the new go-to hardware for small applications and fun games developed by people at home.&lt;/p&gt;
&lt;p&gt;(More about the &lt;a href=&quot;http://en.wikibooks.org/wiki/PSP/Homebrew_History&quot;&gt;homebrew history&lt;/a&gt;)&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Jumping back to 2014.
I learned quite a lot more since my PSP homebrew days. I&#39;m now studying computer science and working part-time as a developer. I write C, C++, Ruby, Javascript.
And most recently &lt;a href=&quot;http://fnordig.de/2014/08/12/first-experience-with-rust/&quot;&gt;I started learning Rust&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a id=&quot;more-rust&quot;&gt;&lt;/a&gt;
Then, on the 12th of November I was chilling on the balcony of the hotel on Hawaii, browsing the Internet, when I came across the following post on Reddit:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.reddit.com/r/rust/comments/2m10id/hello_world_on_a_psp_via_rust/&quot;&gt;&lt;strong&gt;&quot;Hello World&quot; on a PSP via Rust!&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Actually it was nothing more than a picture showing a PSP executing some &quot;Hello World&quot; app.
Then some comments came in, including a link to &lt;a href=&quot;https://gist.github.com/luqmana/ca2899134311f1bf919d&quot;&gt;the code and instructions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As soon as I was back home, I grabbed my PSP, booted up a new virtual machine and installed the &lt;a href=&quot;https://github.com/pspdev/psptoolchain&quot;&gt;psptoolchain&lt;/a&gt; (mostly the same hassle as in the old days, it just finishes a lot quicker).&lt;/p&gt;
&lt;p&gt;First step: Re-compile and run p-twit. Yip, it works (ok, it starts. Of course the Twitter API is so closed these days, it wouldn&#39;t be able to do anything).&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;a href=&quot;//tmp.fnordig.de/rust-on-psp/2014-11-24_11.54.27.jpg&quot;&gt;&lt;img src=&quot;//tmp.fnordig.de/rust-on-psp/th-2014-11-24_11.54.27.jpg&quot; alt=&quot;p-twit runs again&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;Second step: Follow the instructions from the &lt;a href=&quot;https://gist.github.com/luqmana/ca2899134311f1bf919d&quot;&gt;Gist&lt;/a&gt;.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;jer@psp-dev:~/rust-for-psp$ rustc hello.rs --target psp -lpspdebug -lpspdisplay -lpspge -lm -lc -lpspuser -lgcc
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;jer@psp-dev:~/rust-for-psp$ psp-fixup-imports hello
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Error, no sceModuleInfo section found
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;D&#39;oh! That didn&#39;t work.
I played around, tried all kinds of things, then gave up a little frustrated.&lt;/p&gt;
&lt;p&gt;A few days later I talked to &lt;a href=&quot;https://github.com/luqmana/&quot;&gt;luqmana&lt;/a&gt; in the Rust IRC channel.
He turned his Gist into a real repository, &lt;a href=&quot;https://github.com/luqmana/rust-psp-hello&quot;&gt;rust-psp-hello&lt;/a&gt;, including scripts and a Cargofile. Still, no luck for me.
Even after re-installing the toolchain several times on different machines I still faced the awful &lt;code&gt;Error, no sceModuleInfo section found&lt;/code&gt; after every compile.&lt;/p&gt;
&lt;p&gt;After some more tweaking, re-installing, compiling and chatting with luqmana it turns out: He&#39;s not using the same toolchain build as I do.
He simply used the pre-compiled &lt;a href=&quot;http://sourceforge.net/projects/minpspw/&quot;&gt;minpspw&lt;/a&gt; package
(&lt;em&gt;Update 04.12.2014&lt;/em&gt;: Luqman informed me he does in fact built it himself from the minpspw svn, which in turn uses the psptoolchain I tried with first, so absolutely no idea why directly using it failed).
Once I grabbed that, the &quot;Hello World&quot; application compiled and ran! Success!&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;a href=&quot;//tmp.fnordig.de/rust-on-psp/2014-11-27_01.13.59.jpg&quot;&gt;&lt;img src=&quot;//tmp.fnordig.de/rust-on-psp/th-2014-11-27_01.13.59.jpg&quot; alt=&quot;From Rust with love&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;The journey doesn&#39;t end here.
Only partly satisfied with what I had, I took some free time on a train ride to write a wrapper for the input handling.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;a href=&quot;//tmp.fnordig.de/rust-on-psp/2014-11-28_12.25.50.jpg&quot;&gt;&lt;img src=&quot;//tmp.fnordig.de/rust-on-psp/th-2014-11-28_12.25.50.jpg&quot; alt=&quot;Press X, press O&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;Now it&#39;s possible to react to user input with this simple piece of code:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; pad_data &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;ctrl::Input::new();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; pad_data.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;read_changed&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; pad_data.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;pressed_key&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      Button::Cross &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;utils::debug_print(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;X pressed&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      Button::Circle &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;utils::debug_print(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;O pressed&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      Button::Triangle &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;utils::debug_print(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;TRIANGLE pressed&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      Button::Square &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;utils::debug_print(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;SQUARE pressed&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      Button::None &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;_ =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;utils::debug_print(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;unhandled keypress&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The full implementation is up in &lt;a href=&quot;https://github.com/badboy/rust-psp-hello&quot;&gt;my fork of rust-psp-hello&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There&#39;s still a lot I want to do now that I&#39;m started:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Implement wrappers for the missing libraries (display, wifi)&lt;/li&gt;
&lt;li&gt;Figure out a good (&lt;em&gt;Rusty&lt;/em&gt;) API for these wrappers&lt;/li&gt;
&lt;li&gt;Get my own PSP to connect to a WiFi again (I&#39;m not sure why but it won&#39;t connect to my home network)&lt;/li&gt;
&lt;li&gt;Figure out why the freshly compiled psptoolchain fails to link in the &lt;code&gt;sceModuleInfo&lt;/code&gt; section&lt;/li&gt;
&lt;li&gt;Build something cool to present&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&#39;d be happy if anyone wants to help or wants to know more. Just work on the repo (Pull Requests welcome) or drop me a message on Twitter or via email.
I&#39;d also be happy to hear storys from others that developed for the PSP 5 or 7 or 9 years ago.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2014/12/03/a-story-of-hacking-or-rust-on-the-psp</guid>
      <pubDate>Wed, 03 Dec 2014 20:03:00 +0100</pubDate>
    </item>
    <item>
      <title>A Rust library for LibLZF</title>
      <link>https://fnordig.de/2014/10/15/a-rust-library-for-liblzf</link>
      <description>&lt;p&gt;In the last four months I did not produce much open-source code. I was busy writing my Bachelor Thesis.
But I was active in the community, I attended several conferences, I read a lot of stuff and I wrote down a lot more things to do.&lt;/p&gt;
&lt;p&gt;One of these things was &quot;learn Rust&quot;, as you might figure (and writing more).
Well, I submitted my thesis on Monday and went on to write some actual Rust code.&lt;/p&gt;
&lt;p&gt;So I created &lt;a href=&quot;https://github.com/badboy/lzf-rs&quot;&gt;lzf-rs&lt;/a&gt;, a wrapper around &lt;a href=&quot;http://software.schmorp.de/pkg/liblzf.html&quot;&gt;LibLZF&lt;/a&gt;, a super small and fast compression library, originally written by Marc Lehmann.
LibLZF consists of just 4 files and is super-easy to compile as a small library.
LibLZF itself is used by &lt;a href=&quot;https://github.com/antirez/redis/blob/3c6f9ac37c849c82aebf5b45e895faa6cc80e7be/src/rdb.c#L222&quot;&gt;Redis&lt;/a&gt; for compressing strings in the RDB,
that&#39;s how I got to know it. I still don&#39;t know how it works, but I want to learn it now (and maybe port the whole code to Rust instead of using a wrapper around the C library?)&lt;/p&gt;
&lt;p&gt;I used Rust&#39;s &lt;a href=&quot;http://doc.rust-lang.org/guide-ffi.html&quot;&gt;Foreign Function Interface&lt;/a&gt; to write the wrapper. Accessing C code from within Rust is quite simple.
The hard part is choosing the right data types and writing the API in a safe and usable way.
I&#39;m not 100% happy with the current API of lzf-rs, so expect it to change.
I&#39;m still in the process of figuring out what to expose and what not.&lt;/p&gt;
&lt;p&gt;And now, enough of the talking. This is how to use the library:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; lzf;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; data &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;foobar&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; compressed &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;lzf::compress(data.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;as_bytes&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;()).&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; decompressed &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;lzf::decompress(compressed.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;as_slice&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(), data.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;()).&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;m happy to get some feedback. It&#39;s my first serious Rust code, so prone to bugs and maybe not to Rusty afterall.
Ping me on &lt;a href=&quot;https://twitter.com/badboy_&quot;&gt;Twitter&lt;/a&gt;, drop me an &lt;a href=&quot;mailto:janerik@fnordig.de&quot;&gt;email&lt;/a&gt; or &lt;a href=&quot;https://github.com/badboy/lzf-rs/issues&quot;&gt;open an issue&lt;/a&gt;.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2014/10/15/a-rust-library-for-liblzf</guid>
      <pubDate>Wed, 15 Oct 2014 11:10:00 +0200</pubDate>
    </item>
    <item>
      <title>first experience with Rust</title>
      <link>https://fnordig.de/2014/08/12/first-experience-with-rust</link>
      <description>&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;tl;dr:&lt;/strong&gt; Rust code for the SIMPLE language available &lt;a href=&quot;https://github.com/badboy/small-step-simple-rust&quot;&gt;in a git-repo&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I had some spare time yesterday after I finished my last-ever bachelor exam (yey!) so I took my chances and started to write some &lt;a href=&quot;http://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt;.
Just two days ago I also started to read &lt;a href=&quot;https://twitter.com/tomstuart&quot;&gt;Tom Stuart&lt;/a&gt;&#39;s book &lt;a href=&quot;http://computationbook.com/&quot;&gt;&quot;Understanding Computation&quot;&lt;/a&gt;.
In Chapter 1, &quot;The Meaning of Programs&quot;, he introduces a small and simple programming language called SIMPLE. By using a small-step approach and Ruby as the language of implementation he builds up the virtual machine to execute an already built AST. Go read the first chapter, it&#39;s in the sample (and thus free) to get a better idea.
The &lt;a href=&quot;https://github.com/tomstuart/computationbook/tree/master/the_meaning_of_programs&quot;&gt;original code&lt;/a&gt; is some simple to understand Ruby, just under 200 lines.&lt;/p&gt;
&lt;p&gt;It has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Numbers&lt;/li&gt;
&lt;li&gt;Booleans&lt;/li&gt;
&lt;li&gt;Variables&lt;/li&gt;
&lt;li&gt;Assignments&lt;/li&gt;
&lt;li&gt;Addition and Multiplication&lt;/li&gt;
&lt;li&gt;less-than comparison&lt;/li&gt;
&lt;li&gt;if-else clause&lt;/li&gt;
&lt;li&gt;while loop&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&#39;s nearly all it takes for a programming language.
Usage of the Ruby code looks like this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Machine&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Sequence&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Assign&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:x&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Number&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Assign&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:res&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Add&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Add&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Number&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;38&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Variable&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:x&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)), &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Variable&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:y&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)))
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    )
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    { &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:y &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Number&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  ).run
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;; res &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;38 &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; y, {&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:y&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;»}
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;do-&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;nothing; res &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;38 &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; y, {&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:y&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;», &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:x&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;»}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;38 &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; y, {&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:y&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;», &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:x&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;»}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;38 &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+ &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3 &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; y, {&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:y&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;», &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:x&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;»}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;41 &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; y, {&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:y&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;», &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:x&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;»}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;41 &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+ &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, {&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:y&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;», &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:x&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;»}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;42&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, {&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:y&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;», &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:x&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;»}
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;do-&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;nothing, {&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:y&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;», &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:x&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;», &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;:res&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt;«&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;42&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;»}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;nil
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because we build the AST by ourself instead of taking a lexer/parser to do the job, the example takes a bit more code than you would think.
But it still is simple enough to grasp.&lt;/p&gt;
&lt;p&gt;Now the same small sample &quot;programm&quot; in Rust:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; env &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;HashMap::new();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;env.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;insert&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;y&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;to_string&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(), number!(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;));
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let mut&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; m &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Machine::new(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    sequence!(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        assign!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, number!(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        assign!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;res&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, add!(add!(number!(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;38&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;), variable!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)), variable!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;y&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)))
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      ),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    env);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;m.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;// Add this point `res` in the HashMap will be `Number(42)`
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yep, not much of a difference. It will even output the same steps as above (but without the environment hash).
The full code is available in &lt;a href=&quot;https://github.com/badboy/small-step-simple-rust&quot;&gt;a git repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I don&#39;t want to explain each and every peace of that code, but instead focus on what I learned about Rust.&lt;/p&gt;
&lt;h2&gt;Use the docs&lt;/h2&gt;
&lt;p&gt;There are &lt;a href=&quot;http://doc.rust-lang.org/std/index.html&quot;&gt;API docs&lt;/a&gt; as well as a &lt;a href=&quot;http://doc.rust-lang.org/reference.html&quot;&gt;Reference Manual&lt;/a&gt; and even more &lt;a href=&quot;http://doc.rust-lang.org/index.html&quot;&gt;general documentation&lt;/a&gt;
(all links are the nightly versions as I use that).
But Rust is in active development. Things are changing fast. Documentation on features might be outdated (especially older blog posts or StackOverflow answers) or even missing (but it gets better with &lt;a href=&quot;https://twitter.com/steveklabnik&quot;&gt;Steven Klabnik&lt;/a&gt; working full-time at it).
Get familiar with the Standard Library and its docs. Often you need to read that to fully understand how to use a certain data structure or how to implement a specific trait for your code.&lt;/p&gt;
&lt;p&gt;Document your code. Rust makes that real easy. Comments are parsed as markdown (you know that already, don&#39;t you?) and &lt;code&gt;rustdoc&lt;/code&gt; generates a static HTML site from your code (all the API docs are generated this way).&lt;/p&gt;
&lt;h2&gt;Don&#39;t fear the errors&lt;/h2&gt;
&lt;p&gt;The error and warning messages of the Rust compiler are great. Most often they actually find simple mistakes (wrong variable name, missing self) and actually tell you how to fix it.
Other times, even though the message is quite clear, it&#39;s not clear how to properly fix your code to compile.
But &lt;em&gt;when&lt;/em&gt; it compiles, it actually did what I wanted it to do.
Most of my errors or &quot;design mistakes&quot; were caught by the explicit type system and safeness checks.
Everytime I googled an error message I ended up in the GitHub issue tracker of Rust. Sometimes this helped as it clearly discussed the problem and gave useful answers.&lt;/p&gt;
&lt;h2&gt;Test your stuff&lt;/h2&gt;
&lt;p&gt;Rust comes with in-built test support. Simply tag code with &lt;code&gt;#[test]&lt;/code&gt; and it will only be compiled and run if you pass the &lt;code&gt;--test&lt;/code&gt; flag to the compiler (or use &lt;code&gt;cargo test&lt;/code&gt;).
It was the first time that I actually ended up doing TDD: First a small test, see it fail, fix the code, see the test pass, refactor if needed. Extend tests.
Just super convenient, but make sure to extract your tests in larger code bases (huge files won&#39;t help anyone).&lt;/p&gt;
&lt;h2&gt;Use language features&lt;/h2&gt;
&lt;p&gt;Pattern matching is nice. It often saves you one or two more if statements. Just deconstruct your object right in the pattern match.
Macros are a nice addition, too. The pure Rust syntax might be a little bit verbose sometimes, so just save some keystrokes for your convenience and use a short macro (please, don&#39;t over-do it, the docs explicitely say that macros are harder to debug than pure Rust code).
Make sure you&#39;re editor has proper language support, &lt;a href=&quot;https://github.com/wting/rust.vim&quot;&gt;rust.vim&lt;/a&gt; worked quite good for me and did everything right from the start.&lt;/p&gt;
&lt;p&gt;I still need to learn about a few Rust features.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I still don&#39;t know how to properly seperate your stuff in modules and seperate source files&lt;/li&gt;
&lt;li&gt;I have no idea about proper pointer borrowing and other safety features&lt;/li&gt;
&lt;li&gt;I&#39;ve got no idea how lifetimes work and the syntax is not the best in my opinion (&lt;code&gt;&#39;&lt;/code&gt; as the marker to indicate a lifetime name).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Summing it all up&lt;/h2&gt;
&lt;p&gt;Yes, Rust is more verbose than Ruby. Yes, it&#39;s much more strict than C or Ruby. Yes, it&#39;s not yet ready and changing fast.&lt;/p&gt;
&lt;p&gt;But its concepts are nice. More safe and robust code just by more explicit type checks and immutable by default make you think more about the actual application design. They catch errors before you even run the code and make it easy to explicitely state the intent of your code (&quot;code should be self-documenting&quot; ;)).&lt;/p&gt;
&lt;p&gt;I don&#39;t see me writing lots of Rust code in the near future, but it certainly helps to once in a while have a look at different systems to learn.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2014/08/12/first-experience-with-rust</guid>
      <pubDate>Tue, 12 Aug 2014 13:25:00 +0200</pubDate>
    </item>
    
  </channel>
</rss>
