<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Rajeev Edmonds — Blog</title>
  <subtitle>Short, practical notes on Rust and command-line tools by Rajeev Edmonds.</subtitle>
  <link href="https://www.rajeevedmonds.com/blog/feed.xml" rel="self" type="application/atom+xml"/>
  <link href="https://www.rajeevedmonds.com/blog/" rel="alternate" type="text/html"/>
  <id>https://www.rajeevedmonds.com/blog/</id>
  <updated>2026-10-06T00:00:00.000Z</updated>
  <author>
    <name>Rajeev Edmonds</name>
    <uri>https://www.rajeevedmonds.com/</uri>
  </author>
  <entry>
    <title>How Async Rust Works Under the Hood: Futures, Executors, and Pinning Explained</title>
    <link href="https://www.rajeevedmonds.com/blog/how-async-rust-works-futures-executors-pinning/" rel="alternate" type="text/html"/>
    <id>https://www.rajeevedmonds.com/blog/how-async-rust-works-futures-executors-pinning/</id>
    <published>2026-10-06T00:00:00.000Z</published>
    <updated>2026-10-06T00:00:00.000Z</updated>
    <summary>Learn how async Rust really works: Futures, poll, Wakers, executors, and Pin explained in plain English with code you can run.</summary>
    <content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;You write &lt;code&gt;async fn&lt;/code&gt;, sprinkle in a few &lt;code&gt;.await&lt;/code&gt; calls, and everything just works. Until it doesn&#39;t.&lt;/p&gt;
&lt;p&gt;Then one day you hit an error like &lt;code&gt;future cannot be sent between threads safely&lt;/code&gt;. Or you see &lt;code&gt;Pin&amp;lt;Box&amp;lt;dyn Future&amp;lt;Output = ()&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; in a function signature and feel your confidence drain away. Or your whole server freezes because of one innocent-looking function call.&lt;/p&gt;
&lt;p&gt;Most of the confusion around async Rust comes from one thing: &lt;strong&gt;it works very differently from async in languages like JavaScript, Go, or C#.&lt;/strong&gt; There is no built-in runtime and no hidden scheduler. The language gives you a small set of building blocks, and the ecosystem builds everything else on top.&lt;/p&gt;
&lt;p&gt;In this guide, we&#39;ll open the hood and look at those building blocks one by one: the &lt;code&gt;Future&lt;/code&gt; trait, &lt;code&gt;poll&lt;/code&gt;, wakers, executors, and the famously confusing &lt;code&gt;Pin&lt;/code&gt;. We&#39;ll also write a tiny working executor from scratch. You can follow along with a plain &lt;code&gt;cargo new&lt;/code&gt; project and no external crates.&lt;/p&gt;
&lt;p&gt;By the end, you&#39;ll know what the compiler does with your &lt;code&gt;async fn&lt;/code&gt;, why &lt;code&gt;Pin&lt;/code&gt; exists, and how to avoid the most common production mistakes.&lt;/p&gt;
&lt;h2&gt;The Big Idea: Async Rust Is Lazy and Cooperative&lt;/h2&gt;
&lt;p&gt;Before the details, two ideas explain almost everything else.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Futures are lazy.&lt;/strong&gt; Calling an &lt;code&gt;async fn&lt;/code&gt; does not run any of its body. It returns a value (a future) that describes the work. Nothing happens until something polls that value.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scheduling is cooperative.&lt;/strong&gt; A task runs until it hits an &lt;code&gt;.await&lt;/code&gt; that can&#39;t make progress, and only then does it give control back. Nobody forcibly interrupts it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Compare this with OS threads, where the kernel can pause your code at any instruction. In async Rust, &lt;em&gt;you&lt;/em&gt; decide where the pause points are, and they are your &lt;code&gt;.await&lt;/code&gt;s.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If a task never reaches an &lt;code&gt;.await&lt;/code&gt;, it never gives the thread back. That&#39;s the root cause of most &amp;quot;my async server froze&amp;quot; bugs. We&#39;ll come back to this.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;What Is a Future, Really?&lt;/h2&gt;
&lt;p&gt;A future is any type that implements this trait from the standard library:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;token type-definition class-name&quot;&gt;Future&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token type-definition class-name&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;poll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Pin&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cx&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token lifetime-annotation symbol&quot;&gt;&#39;_&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Poll&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token type-definition class-name&quot;&gt;Poll&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Ready&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Pending&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s the whole thing. A future is something you can ask, &amp;quot;Are you done yet?&amp;quot; by calling &lt;code&gt;poll&lt;/code&gt;. It answers in one of two ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Poll::Ready(value)&lt;/code&gt;: finished, here&#39;s the result.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Poll::Pending&lt;/code&gt;: not done yet, ask me again later.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notice that &lt;code&gt;poll&lt;/code&gt; takes a &lt;code&gt;Context&lt;/code&gt;. That&#39;s how a future says, &amp;quot;Don&#39;t keep asking me in a loop. I&#39;ll tell you when I&#39;m ready.&amp;quot; We&#39;ll get to that in the waker section.&lt;/p&gt;
&lt;h3&gt;Polling vs. Callbacks&lt;/h3&gt;
&lt;p&gt;Many languages use callbacks or promises that &lt;em&gt;push&lt;/em&gt; results to you. Rust uses a &lt;strong&gt;poll-based&lt;/strong&gt; model, where the executor &lt;em&gt;pulls&lt;/em&gt; progress out of futures.&lt;/p&gt;
&lt;p&gt;This has real benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Zero-cost abstractions.&lt;/strong&gt; Futures are plain structs. No heap allocation is required just to have a future.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No hidden runtime.&lt;/strong&gt; You choose your executor, or write your own.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy cancellation.&lt;/strong&gt; Dropping a future cancels it. There is no separate cancel token to wire up.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backpressure.&lt;/strong&gt; The consumer controls when work progresses.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What the Compiler Does With &lt;code&gt;async fn&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Here is a simple async function:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;greet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch_name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;format!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello, {name}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The compiler turns this into an anonymous type that implements &lt;code&gt;Future&amp;lt;Output = String&amp;gt;&lt;/code&gt;. Conceptually, it is a &lt;strong&gt;state machine&lt;/strong&gt;, an enum with one variant per suspension point:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Simplified. The real generated code is more involved.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token type-definition class-name&quot;&gt;GreetFuture&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;WaitingForName&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; fetch&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FetchNameFuture&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Done&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each time the executor calls &lt;code&gt;poll&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The future resumes from its current state.&lt;/li&gt;
&lt;li&gt;It runs until the next &lt;code&gt;.await&lt;/code&gt; that returns &lt;code&gt;Pending&lt;/code&gt;, or until it finishes.&lt;/li&gt;
&lt;li&gt;It saves any local variables it still needs inside the state, then returns.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is why async Rust is so efficient. All the locals that live across an &lt;code&gt;.await&lt;/code&gt; are stored &lt;em&gt;inside the future itself&lt;/em&gt;, in one struct. No separate stack is needed per task, as with threads or green threads.&lt;/p&gt;
&lt;h3&gt;A Practical Consequence: Future Size&lt;/h3&gt;
&lt;p&gt;Because the future stores everything that lives across an &lt;code&gt;.await&lt;/code&gt;, large local values make large futures:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;heavy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; buffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0u8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;64&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 64 KB lives inside the future&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;do_something&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you spawn thousands of tasks like this, memory adds up. Large buffers are better placed on the heap with &lt;code&gt;Vec&lt;/code&gt; or &lt;code&gt;Box&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Wakers: How a Future Says &amp;quot;Try Me Again&amp;quot;&lt;/h2&gt;
&lt;p&gt;If the executor just polled every future in a tight loop, you&#39;d burn 100% CPU doing nothing. Wakers solve this.&lt;/p&gt;
&lt;p&gt;When a future returns &lt;code&gt;Pending&lt;/code&gt;, it must first arrange for &lt;strong&gt;someone to call &lt;code&gt;wake()&lt;/code&gt;&lt;/strong&gt; when progress becomes possible. The &lt;code&gt;Waker&lt;/code&gt; lives inside the &lt;code&gt;Context&lt;/code&gt; passed to &lt;code&gt;poll&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The flow looks like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The executor polls your future with a &lt;code&gt;Context&lt;/code&gt; containing a &lt;code&gt;Waker&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The future tries to do work (say, read from a socket) and finds no data yet.&lt;/li&gt;
&lt;li&gt;The future &lt;strong&gt;clones and stores the waker&lt;/strong&gt;, then returns &lt;code&gt;Pending&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Later, something external happens, such as the OS reporting that the socket is readable.&lt;/li&gt;
&lt;li&gt;That event source calls &lt;code&gt;waker.wake()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The executor puts the task back in its queue and polls it again.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The golden rule:&lt;/strong&gt; Returning &lt;code&gt;Pending&lt;/code&gt; without arranging a wake-up means your task may sleep forever. The compiler can&#39;t catch this, so it&#39;s one of the easiest bugs to write when implementing futures by hand.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Executors and Reactors: Who Actually Drives Everything?&lt;/h2&gt;
&lt;p&gt;People often use &amp;quot;runtime&amp;quot; loosely, but separate jobs are being done:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;th&gt;Real-world example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Executor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Holds tasks, polls them when woken, runs them on threads&lt;/td&gt;
&lt;td&gt;Tokio&#39;s scheduler, smol&#39;s executor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reactor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Watches for I/O and timer events, calls &lt;code&gt;wake()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tokio&#39;s I/O driver built on &lt;code&gt;mio&lt;/code&gt; (epoll, kqueue, IOCP)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Futures&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Describe the work and register wakers&lt;/td&gt;
&lt;td&gt;Your &lt;code&gt;async fn&lt;/code&gt;s, &lt;code&gt;TcpStream::read&lt;/code&gt;, &lt;code&gt;sleep&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;An executor is surprisingly simple at its core: a queue of tasks plus a loop. A reactor is the part that talks to the operating system.&lt;/p&gt;
&lt;h2&gt;Build a Tiny Executor From Scratch&lt;/h2&gt;
&lt;p&gt;Let&#39;s make this concrete. We&#39;ll build two things using only the standard library:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A future that completes after a delay.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;block_on&lt;/code&gt; function that runs a future to completion.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 1: A Hand-Written Future&lt;/h3&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;future&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;pin&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;sync&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Mutex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Poll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Waker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token type-definition class-name&quot;&gt;Shared&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    done&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    waker&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Waker&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token type-definition class-name&quot;&gt;Delay&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    shared&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Mutex&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Delay&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dur&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;Self&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; shared &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Mutex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Shared&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; done&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; waker&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; thread_shared &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; shared&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Stand-in for a reactor: a helper thread that &quot;fires an event&quot;.&lt;/span&gt;
        &lt;span class=&quot;token namespace&quot;&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;move&lt;/span&gt; &lt;span class=&quot;token closure-params&quot;&gt;&lt;span class=&quot;token closure-punctuation punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token closure-punctuation punctuation&quot;&gt;|&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token namespace&quot;&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dur&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;mut&lt;/span&gt; s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; thread_shared&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unwrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;done &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;w&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;waker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;take&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                w&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wake&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token class-name&quot;&gt;Delay&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; shared &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Future&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Delay&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token type-definition class-name&quot;&gt;Output&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;poll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Pin&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cx&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token lifetime-annotation symbol&quot;&gt;&#39;_&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Poll&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;mut&lt;/span&gt; s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shared&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unwrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;done &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;Poll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Ready&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// Store the latest waker so the helper thread can wake us.&lt;/span&gt;
            s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;waker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cx&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;waker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;Poll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Pending&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Two details are worth noticing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We &lt;strong&gt;overwrite the stored waker on every poll&lt;/strong&gt;. The executor may hand us a different waker each time, and the most recent one is the one that counts.&lt;/li&gt;
&lt;li&gt;The waker is called &lt;em&gt;after&lt;/em&gt; we set &lt;code&gt;done = true&lt;/code&gt;. Setting the flag first avoids a race where the future is polled and sees stale state.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Step 2: A Minimal &lt;code&gt;block_on&lt;/code&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;pin&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;pin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;sync&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Wake&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token type-definition class-name&quot;&gt;ThreadWaker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Wake&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ThreadWaker&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;wake&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unpark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;block_on&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fut&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Output&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;mut&lt;/span&gt; fut &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token macro property&quot;&gt;pin!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fut&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; waker&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Waker&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ThreadWaker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;into&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;mut&lt;/span&gt; cx &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from_waker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;waker&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt; fut&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;as_mut&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;poll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;mut&lt;/span&gt; cx&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;Poll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Ready&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;Poll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Pending&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;park&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// sleep until woken&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 3: Run It&lt;/h3&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;block_on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;Delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from_secs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;one second later&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run &lt;code&gt;cargo run&lt;/code&gt; and you&#39;ll see the two messages one second apart. The main thread sleeps in &lt;code&gt;park()&lt;/code&gt; during the wait and uses almost no CPU.&lt;/p&gt;
&lt;p&gt;This is the same pattern real runtimes follow. They just add task queues, many threads, and a proper reactor. A runtime like Tokio is this idea, scaled up and polished.&lt;/p&gt;
&lt;h2&gt;Why Does Pin Exist?&lt;/h2&gt;
&lt;p&gt;Now the part everyone dreads. Let&#39;s make it simple.&lt;/p&gt;
&lt;h3&gt;The Problem: Self-Referential Futures&lt;/h3&gt;
&lt;p&gt;Look at this function:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;example&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; r &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;// a reference to a local&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;something&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// suspension point&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{:?}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The reference &lt;code&gt;r&lt;/code&gt; points to &lt;code&gt;data&lt;/code&gt;. Both live inside the generated future, across the &lt;code&gt;.await&lt;/code&gt;. So the future contains a pointer &lt;strong&gt;to itself&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Now imagine the future is moved to a different memory address, perhaps by passing it into a function or pushing it into a &lt;code&gt;Vec&lt;/code&gt;. The bytes get copied, but &lt;code&gt;r&lt;/code&gt; still holds the &lt;em&gt;old&lt;/em&gt; address. That is a dangling pointer, which means undefined behavior.&lt;/p&gt;
&lt;p&gt;Normally Rust&#39;s borrow checker prevents this kind of thing. But for compiler-generated state machines, it can&#39;t express &amp;quot;this struct borrows from itself.&amp;quot; The solution is to make sure the future &lt;strong&gt;never moves once it has started being polled.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;The Solution: &lt;code&gt;Pin&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Pin&amp;lt;P&amp;gt;&lt;/code&gt; wraps a pointer type like &lt;code&gt;&amp;amp;mut T&lt;/code&gt; or &lt;code&gt;Box&amp;lt;T&amp;gt;&lt;/code&gt;. It promises that the value pointed to &lt;strong&gt;will not be moved&lt;/strong&gt; until it&#39;s dropped, unless the type opts out.&lt;/p&gt;
&lt;p&gt;That&#39;s why &lt;code&gt;poll&lt;/code&gt; takes &lt;code&gt;self: Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;/code&gt; and not &lt;code&gt;&amp;amp;mut self&lt;/code&gt;. A plain &lt;code&gt;&amp;amp;mut&lt;/code&gt; would let you do &lt;code&gt;std::mem::swap&lt;/code&gt; and move the future. A pinned reference won&#39;t.&lt;/p&gt;
&lt;h3&gt;Unpin: The Escape Hatch&lt;/h3&gt;
&lt;p&gt;Most types don&#39;t care about being moved. &lt;code&gt;u32&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt;, and &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt; are all fine. These types automatically implement the marker trait &lt;code&gt;Unpin&lt;/code&gt;, and for them pinning is a no-op.&lt;/p&gt;
&lt;p&gt;Futures generated by &lt;code&gt;async&lt;/code&gt; blocks are typically &lt;code&gt;!Unpin&lt;/code&gt;. That is what makes pinning matter for them.&lt;/p&gt;
&lt;p&gt;Here is a summary of the common ways to pin something:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Where it lives&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Box::pin(fut)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Heap&lt;/td&gt;
&lt;td&gt;Safest and simplest. Costs one allocation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;std::pin::pin!(fut)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stack (current scope)&lt;/td&gt;
&lt;td&gt;No allocation. Stable since Rust 1.68.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Pin::new(&amp;amp;mut fut)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Wherever it is&lt;/td&gt;
&lt;td&gt;Only works if &lt;code&gt;fut: Unpin&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Pin::new_unchecked&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Wherever it is&lt;/td&gt;
&lt;td&gt;&lt;code&gt;unsafe&lt;/code&gt;. You take responsibility for never moving it.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;When You&#39;ll Actually Meet Pin in Daily Code&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Storing futures in collections.&lt;/strong&gt; You can&#39;t put different async blocks in a &lt;code&gt;Vec&lt;/code&gt; directly, since each has a unique type. Use &lt;code&gt;Vec&amp;lt;Pin&amp;lt;Box&amp;lt;dyn Future&amp;lt;Output = T&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Using &lt;code&gt;select!&lt;/code&gt;.&lt;/strong&gt; Futures reused across loop iterations often need &lt;code&gt;pin!&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Recursion.&lt;/strong&gt; An async function that calls itself needs boxing, because the future would otherwise have infinite size:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;future&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;pin&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;countdown&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Pin&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;dyn&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Output&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;move&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{n}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;countdown&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If &lt;code&gt;Pin&lt;/code&gt; errors confuse you, the fix is usually &lt;code&gt;Box::pin(...)&lt;/code&gt; or &lt;code&gt;pin!(...)&lt;/code&gt;. Reach for those first. You rarely need &lt;code&gt;unsafe&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;How Tokio Schedules Your Tasks&lt;/h2&gt;
&lt;p&gt;Let&#39;s connect all of this to the runtime most people use. When you write:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token attribute attr-name&quot;&gt;#[tokio::main]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; handle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;tokio&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// some work&lt;/span&gt;
        &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; handle&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unwrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{result}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;tokio::spawn&lt;/code&gt; wraps your future in a task and hands it to the scheduler. By default, Tokio uses a &lt;strong&gt;multi-threaded work-stealing scheduler&lt;/strong&gt;: one worker thread per CPU core, each with its own queue. If a worker runs out of tasks, it steals from another.&lt;/p&gt;
&lt;p&gt;Because your task might be resumed on a &lt;em&gt;different&lt;/em&gt; thread after an &lt;code&gt;.await&lt;/code&gt;, the future must be &lt;code&gt;Send&lt;/code&gt;. That&#39;s the origin of the dreaded error:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;error: future cannot be sent between threads safely&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It usually means something non-&lt;code&gt;Send&lt;/code&gt; (like an &lt;code&gt;Rc&lt;/code&gt;, or a &lt;code&gt;std::sync::MutexGuard&lt;/code&gt;) is held across an &lt;code&gt;.await&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you don&#39;t need multiple threads, Tokio also offers a single-threaded flavor:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token attribute attr-name&quot;&gt;#[tokio::main(flavor = &lt;span class=&quot;token string&quot;&gt;&quot;current_thread&quot;&lt;/span&gt;)]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Choosing a Runtime&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Runtime&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;th&gt;Character&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tokio&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Servers, networking, most production apps&lt;/td&gt;
&lt;td&gt;Largest ecosystem, work-stealing, feature-rich&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;smol&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Smaller apps and libraries&lt;/td&gt;
&lt;td&gt;Lightweight and minimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Embassy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Embedded, &lt;code&gt;no_std&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Async on microcontrollers, no heap needed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Common Async Rust Pitfalls (and How to Fix Them)&lt;/h2&gt;
&lt;h3&gt;1. Blocking the Executor&lt;/h3&gt;
&lt;p&gt;This is the number one mistake.&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;bad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;thread&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from_secs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// blocks the worker thread!&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While that thread sleeps, every task scheduled on it is stuck. Use the async version:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;good&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token namespace&quot;&gt;tokio&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from_secs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For CPU-heavy or genuinely blocking work (file parsing, hashing, a sync library), move it off the async workers:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;tokio&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;spawn_blocking&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token closure-params&quot;&gt;&lt;span class=&quot;token closure-punctuation punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token closure-punctuation punctuation&quot;&gt;|&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;expensive_computation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. Holding a Lock Across &lt;code&gt;.await&lt;/code&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Risky: std::sync::MutexGuard held over an await point&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; guard &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unwrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;do_io&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;guard&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can cause deadlocks and &lt;code&gt;Send&lt;/code&gt; errors. Prefer to drop the guard before awaiting:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; guard &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unwrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// guard dropped here&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;do_io&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you truly need to hold a lock across an await, use &lt;code&gt;tokio::sync::Mutex&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;3. Forgetting to &lt;code&gt;.await&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Because futures are lazy, this does nothing:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;save_to_db&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// never runs; just creates a future&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The compiler warns with &lt;code&gt;unused_must_use&lt;/code&gt;. Treat that warning as an error.&lt;/p&gt;
&lt;h3&gt;4. Cancellation Surprises&lt;/h3&gt;
&lt;p&gt;Dropping a future cancels it at its last &lt;code&gt;.await&lt;/code&gt;. That&#39;s powerful, but with &lt;code&gt;tokio::select!&lt;/code&gt; a losing branch is simply dropped, and any partial work in it is lost. If an operation isn&#39;t &lt;strong&gt;cancel-safe&lt;/strong&gt;, such as a read that has consumed some bytes into a temporary buffer, you can lose data. Always check the docs for cancel-safety notes on the functions you use inside &lt;code&gt;select!&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;5. Accidentally Sequential Code&lt;/h3&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch_a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch_b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// starts only after a finishes&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the two are independent, run them concurrently:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;tokio&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token macro property&quot;&gt;join!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fetch_a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch_b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Best Practices Checklist&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Keep the time between &lt;code&gt;.await&lt;/code&gt;s short. Long synchronous stretches starve other tasks.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;spawn_blocking&lt;/code&gt; for blocking or CPU-heavy work.&lt;/li&gt;
&lt;li&gt;Don&#39;t hold &lt;code&gt;std&lt;/code&gt; mutex guards across &lt;code&gt;.await&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Prefer &lt;code&gt;join!&lt;/code&gt; for independent operations.&lt;/li&gt;
&lt;li&gt;Use bounded channels so slow consumers apply backpressure.&lt;/li&gt;
&lt;li&gt;Avoid large stack arrays in async functions. Box them.&lt;/li&gt;
&lt;li&gt;Check cancel-safety before using futures inside &lt;code&gt;select!&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If you&#39;re writing a library, avoid tying users to one runtime when you can.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Async Rust looks mysterious mainly because the machinery is exposed rather than hidden. Once you see the pieces, they fit together neatly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;code&gt;async fn&lt;/code&gt; becomes a &lt;strong&gt;state machine&lt;/strong&gt; that implements &lt;code&gt;Future&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Executors &lt;strong&gt;poll&lt;/strong&gt; futures, and futures return &lt;code&gt;Ready&lt;/code&gt; or &lt;code&gt;Pending&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;Pending&lt;/code&gt; future stores a &lt;strong&gt;waker&lt;/strong&gt;, and the reactor calls it when progress is possible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pin&lt;/strong&gt; exists so self-referential state machines never move in memory.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cooperative scheduling&lt;/strong&gt; means you must never block a worker thread.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A good next step is to take the &lt;code&gt;Delay&lt;/code&gt; and &lt;code&gt;block_on&lt;/code&gt; code above and extend it. Add a task queue so &lt;code&gt;block_on&lt;/code&gt; can run several futures, then compare your version with Tokio&#39;s source. Building even a toy executor will teach you more than reading a dozen articles.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Make Your Rust CLI Pipe-Friendly: stdin, stdout and Broken Pipes</title>
    <link href="https://www.rajeevedmonds.com/blog/pipe-friendly-cli-in-rust/" rel="alternate" type="text/html"/>
    <id>https://www.rajeevedmonds.com/blog/pipe-friendly-cli-in-rust/</id>
    <published>2026-09-28T00:00:00.000Z</published>
    <updated>2026-09-28T00:00:00.000Z</updated>
    <summary>Read from a file or from stdin, write efficiently, and exit quietly when someone runs your tool through head.</summary>
    <content type="html">&lt;p&gt;The best command-line tools compose. They read from a file &lt;em&gt;or&lt;/em&gt; from a pipe, and they behave when their output is piped into something else. Getting that right in Rust takes only a few lines, but there&#39;s one classic trap: the broken pipe.&lt;/p&gt;
&lt;h2&gt;Read from a file or stdin&lt;/h2&gt;
&lt;p&gt;Here&#39;s a small tool, &lt;code&gt;shout&lt;/code&gt;, that uppercases its input. With a path argument it reads that file; without one it reads stdin.&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;fs&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;io&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BufRead&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BufReader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BufWriter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IsTerminal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;io&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;nth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; reader&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;dyn&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BufRead&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt; path &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;BufReader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;io&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stdin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;is_terminal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token macro property&quot;&gt;eprintln!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;usage: shout &amp;lt;file&gt;  (or pipe text into stdin)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;io&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stdin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;mut&lt;/span&gt; out &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BufWriter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;io&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; line &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; reader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token macro property&quot;&gt;writeln!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;to_uppercase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A few details are worth knowing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Box&amp;lt;dyn BufRead&amp;gt;&lt;/code&gt; lets both branches share one loop, whether the source is a file or stdin.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IsTerminal&lt;/code&gt; (stable since Rust 1.70) tells you whether stdin is an interactive terminal. Without that check, running &lt;code&gt;shout&lt;/code&gt; with no arguments would sit there silently waiting for input, which looks like a hang.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stdout&lt;/code&gt; is line-buffered, so wrapping it in a &lt;code&gt;BufWriter&lt;/code&gt; cuts down on system calls when you print many lines.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The broken pipe trap&lt;/h2&gt;
&lt;p&gt;Now try &lt;code&gt;shout big.log | head -n 3&lt;/code&gt;. &lt;code&gt;head&lt;/code&gt; prints three lines and exits, closing the pipe, and your next write fails. Rust&#39;s runtime ignores &lt;code&gt;SIGPIPE&lt;/code&gt;, so instead of being killed silently like a typical Unix tool, your program gets a &lt;code&gt;BrokenPipe&lt;/code&gt; error. With &lt;code&gt;println!&lt;/code&gt;, that error becomes a panic. With &lt;code&gt;writeln!&lt;/code&gt; and &lt;code&gt;?&lt;/code&gt;, it bubbles up as an &lt;code&gt;Err&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That &lt;code&gt;Err&lt;/code&gt; isn&#39;t a real failure. The reader simply got what it needed. So treat it as a normal exit in &lt;code&gt;main&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;io&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ErrorKind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;BrokenPipe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// downstream (e.g. `head`) closed the pipe, which is fine&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token macro property&quot;&gt;eprintln!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;shout: {e}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now the tool works in all three modes:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;shout notes.txt
&lt;span class=&quot;token builtin class-name&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;hello&#92;nworld&#92;n&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; shout
shout big.log &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reading from stdin, writing through a buffer, and treating &lt;code&gt;BrokenPipe&lt;/code&gt; as a clean exit are three small habits that make a tool feel native on the command line.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>How to Integrate Assembly and C Code in Your Rust Projects (The Practical Guide)</title>
    <link href="https://www.rajeevedmonds.com/blog/integrate-assembly-and-c-code-in-rust-projects/" rel="alternate" type="text/html"/>
    <id>https://www.rajeevedmonds.com/blog/integrate-assembly-and-c-code-in-rust-projects/</id>
    <published>2026-09-28T00:00:00.000Z</published>
    <updated>2026-09-28T00:00:00.000Z</updated>
    <summary>Learn how to call C and assembly from Rust using build.rs, the cc crate, bindgen, and inline asm. Practical examples, safe wrappers, and fixes.</summary>
    <content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Rust is great, but it doesn&#39;t live in a vacuum. Sooner or later, you&#39;ll hit a moment where you need to talk to code that isn&#39;t Rust.&lt;/p&gt;
&lt;p&gt;Maybe your company has a battle-tested C library that nobody wants to rewrite. Maybe you&#39;re working with a hardware SDK that ships only a C header. Or maybe you&#39;ve found a hot loop where a few hand-written instructions beat what the compiler generates.&lt;/p&gt;
&lt;p&gt;So how do you bring C and assembly into a Rust project without turning your build into a mess? And how do you keep Rust&#39;s safety guarantees from falling apart at the boundary?&lt;/p&gt;
&lt;p&gt;This guide answers both questions. We&#39;ll cover the main ways to mix these languages, build a working example step by step, and go through the mistakes that cause most FFI crashes. I&#39;ll assume you know basic Rust, but I&#39;ll explain the low-level parts as we go.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; All examples target x86_64 Linux, since that&#39;s where most people start. I&#39;ll flag where macOS, Windows, or ARM need changes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Why Mix Rust With C and Assembly?&lt;/h2&gt;
&lt;p&gt;Before writing any code, it helps to know when this is actually worth doing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Good reasons:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reusing existing C libraries.&lt;/strong&gt; OpenSSL, SQLite, zlib, and libcurl represent decades of work. Wrapping them is often smarter than rewriting them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Talking to operating systems and hardware.&lt;/strong&gt; Many drivers, SDKs, and system APIs expose C interfaces.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gradual migration.&lt;/strong&gt; You can move a C codebase to Rust one module at a time instead of in a risky big-bang rewrite.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Squeezing out performance.&lt;/strong&gt; Some CPU instructions have no clean Rust equivalent, such as special vector instructions, cycle counters, or system-specific tricks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learning.&lt;/strong&gt; Writing assembly for a Rust function teaches you a lot about how calling conventions really work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Bad reasons:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;quot;C is always faster.&amp;quot; It isn&#39;t. Rust and C compile down to similar machine code, and LLVM optimizes both well.&lt;/li&gt;
&lt;li&gt;&amp;quot;Hand-written assembly beats the compiler.&amp;quot; It rarely does for general code. Always benchmark first.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The Big Picture: Ways to Integrate&lt;/h2&gt;
&lt;p&gt;Here are the main approaches you&#39;ll use:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Where the Code Lives&lt;/th&gt;
&lt;th&gt;Difficulty&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;FFI with &lt;code&gt;extern &amp;quot;C&amp;quot;&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Calling C functions from Rust&lt;/td&gt;
&lt;td&gt;Separate &lt;code&gt;.c&lt;/code&gt; files or a system library&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;build.rs&lt;/code&gt; + &lt;code&gt;cc&lt;/code&gt; crate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Compiling C or &lt;code&gt;.S&lt;/code&gt; files as part of &lt;code&gt;cargo build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Inside your project&lt;/td&gt;
&lt;td&gt;Easy to medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Inline &lt;code&gt;asm!&lt;/code&gt; / &lt;code&gt;global_asm!&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Small snippets of assembly&lt;/td&gt;
&lt;td&gt;Inside your Rust source&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;bindgen&lt;/code&gt; / &lt;code&gt;cbindgen&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Auto-generating bindings in either direction&lt;/td&gt;
&lt;td&gt;Generated at build time&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Standalone &lt;code&gt;.s&lt;/code&gt;/&lt;code&gt;.S&lt;/code&gt; files&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Larger assembly routines&lt;/td&gt;
&lt;td&gt;Separate assembly files&lt;/td&gt;
&lt;td&gt;Advanced&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;All of these rely on one idea: the &lt;strong&gt;C ABI&lt;/strong&gt;. It&#39;s the agreed-upon convention for how functions receive arguments and return values. Rust, C, and assembly can all speak it, and that shared language is what makes mixing them possible.&lt;/p&gt;
&lt;h2&gt;Understanding FFI in Rust&lt;/h2&gt;
&lt;p&gt;FFI stands for Foreign Function Interface. In Rust, it comes down to two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Declaring&lt;/strong&gt; foreign functions inside an &lt;code&gt;extern &amp;quot;C&amp;quot;&lt;/code&gt; block.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Calling&lt;/strong&gt; them inside &lt;code&gt;unsafe&lt;/code&gt;, because Rust can&#39;t verify what happens on the other side.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{x}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That works because the C standard library is already linked into every Rust program on most platforms.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A quick syntax note:&lt;/strong&gt; Since Rust 1.82, you can write &lt;code&gt;unsafe extern &amp;quot;C&amp;quot; { ... }&lt;/code&gt;, and it&#39;s required in the 2024 edition. Older code uses plain &lt;code&gt;extern &amp;quot;C&amp;quot; { ... }&lt;/code&gt;. Both mean the same thing. The newer form lets you mark individual items as &lt;code&gt;safe&lt;/code&gt; or &lt;code&gt;unsafe&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Why &lt;code&gt;unsafe&lt;/code&gt;?&lt;/h3&gt;
&lt;p&gt;The Rust compiler has no idea what a C function does. It can&#39;t check that pointers are valid, that lengths are correct, or that the function won&#39;t write past the end of a buffer. So you&#39;re making a promise: &amp;quot;I&#39;ve checked this, and it&#39;s fine.&amp;quot;&lt;/p&gt;
&lt;p&gt;The best practice is to keep that promise in &lt;strong&gt;one place&lt;/strong&gt;. Wrap each unsafe call in a small safe function, and let the rest of your program use the safe version. We&#39;ll do exactly that below.&lt;/p&gt;
&lt;h2&gt;Mapping Types Between Rust and C&lt;/h2&gt;
&lt;p&gt;Getting types wrong is the number one source of subtle FFI bugs. Here are the common mappings:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;C Type&lt;/th&gt;
&lt;th&gt;Rust Type&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::ffi::c_int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Don&#39;t assume it&#39;s &lt;code&gt;i32&lt;/code&gt; on every platform&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;unsigned int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;c_uint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;long&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;c_long&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;32-bit on Windows, 64-bit on 64-bit Linux&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;size_t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;usize&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;uint8_t&lt;/code&gt;, &lt;code&gt;uint32_t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;u8&lt;/code&gt;, &lt;code&gt;u32&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fixed-width types map cleanly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;char *&lt;/code&gt; (string)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*const c_char&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;CStr&lt;/code&gt;/&lt;code&gt;CString&lt;/code&gt; to convert&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;void *&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*mut c_void&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;const T *&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*const T&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;T *&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*mut T&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;struct&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#[repr(C)] struct&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Without &lt;code&gt;repr(C)&lt;/code&gt;, layout is not guaranteed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;function pointer&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Option&amp;lt;extern &amp;quot;C&amp;quot; fn(...)&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Option&lt;/code&gt; allows null&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Two rules to remember:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Always use &lt;code&gt;#[repr(C)]&lt;/code&gt; on structs you share with C.&lt;/strong&gt; Rust is free to reorder fields in normal structs, and C won&#39;t expect that.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prefer fixed-width types&lt;/strong&gt; (&lt;code&gt;u32&lt;/code&gt;, &lt;code&gt;i64&lt;/code&gt;) in your own C code when you control both sides. It removes a whole class of &amp;quot;works on my machine&amp;quot; problems.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Step-by-Step: Adding C and Assembly to a Rust Project&lt;/h2&gt;
&lt;p&gt;Let&#39;s build something real. Our small project will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Call a &lt;strong&gt;C function&lt;/strong&gt; that computes a checksum.&lt;/li&gt;
&lt;li&gt;Call an &lt;strong&gt;assembly function&lt;/strong&gt; that adds two numbers.&lt;/li&gt;
&lt;li&gt;Compile both automatically with &lt;code&gt;cargo build&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Step 1: Create the Project&lt;/h3&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;cargo&lt;/span&gt; new rust-ffi-demo
&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; rust-ffi-demo
&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; csrc asm&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your layout will end up like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rust-ffi-demo/
├── Cargo.toml
├── build.rs
├── csrc/
│   ├── checksum.c
│   └── checksum.h
├── asm/
│   └── add.S
└── src/
    └── main.rs
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 2: Write the C Code&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;csrc/checksum.h&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;ifndef&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;CHECKSUM_H&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;CHECKSUM_H&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stddef.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdint.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;simple_checksum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;size_t&lt;/span&gt; len&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;csrc/checksum.c&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;checksum.h&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;simple_checksum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;size_t&lt;/span&gt; len&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;uint32_t&lt;/span&gt; sum &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;size_t&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; len&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// rotate left by 1, then XOR in the next byte&lt;/span&gt;
        sum &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sum &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sum &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;31&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        sum &lt;span class=&quot;token operator&quot;&gt;^=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; sum&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing fancy. It&#39;s a small function that&#39;s easy to verify by hand.&lt;/p&gt;
&lt;h3&gt;Step 3: Write the Assembly Code&lt;/h3&gt;
&lt;p&gt;We&#39;ll use a &lt;code&gt;.S&lt;/code&gt; file (capital S). That capital matters: it tells the compiler to run the C preprocessor first, and it&#39;s the file type the &lt;code&gt;cc&lt;/code&gt; crate handles well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;asm/add.S&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-asm&quot;&gt;&lt;code class=&quot;language-asm&quot;&gt;    .intel_syntax noprefix
    .text
    .globl add_asm
    .type add_asm, @function

add_asm:
    lea rax, [rdi + rsi]
    ret

    .size add_asm, .-add_asm
    .section .note.GNU-stack,&quot;&quot;,@progbits&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What&#39;s happening here?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On x86_64 Linux (the System V ABI), the first two integer arguments arrive in &lt;code&gt;rdi&lt;/code&gt; and &lt;code&gt;rsi&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The return value goes in &lt;code&gt;rax&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lea rax, [rdi + rsi]&lt;/code&gt; computes the sum without touching the flags register. It&#39;s a common trick.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;.note.GNU-stack&lt;/code&gt; line tells the linker your code doesn&#39;t need an executable stack. Without it, newer linkers may warn.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Heads up for other platforms:&lt;/strong&gt; On macOS, C symbols get a leading underscore (&lt;code&gt;_add_asm&lt;/code&gt;), and Windows uses a different calling convention entirely. ARM64 uses different registers (&lt;code&gt;x0&lt;/code&gt;, &lt;code&gt;x1&lt;/code&gt;) and different syntax. Assembly is not portable, and that&#39;s normal.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Step 4: Compile Everything With &lt;code&gt;build.rs&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Add the &lt;code&gt;cc&lt;/code&gt; crate as a &lt;strong&gt;build dependency&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Cargo.toml&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-toml&quot;&gt;&lt;code class=&quot;language-toml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token table class-name&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rust-ffi-demo&quot;&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0.1.0&quot;&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;edition&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2024&quot;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token table class-name&quot;&gt;build-dependencies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;cc&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now create &lt;code&gt;build.rs&lt;/code&gt; in the project root. Cargo runs this before compiling your main crate.&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Compile the C library&lt;/span&gt;
    &lt;span class=&quot;token namespace&quot;&gt;cc&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;csrc/checksum.c&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;csrc&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;opt_level&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;warnings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;checksum&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Compile assembly only where it makes sense&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; arch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;CARGO_CFG_TARGET_ARCH&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unwrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; os &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;CARGO_CFG_TARGET_OS&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unwrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; arch &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;x86_64&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; os &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;linux&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token namespace&quot;&gt;cc&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;asm/add.S&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;addasm&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Only re-run this script when these files change&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;cargo:rerun-if-changed=csrc/checksum.c&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;cargo:rerun-if-changed=csrc/checksum.h&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;cargo:rerun-if-changed=asm/add.S&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice we check the &lt;strong&gt;target&lt;/strong&gt; architecture using &lt;code&gt;CARGO_CFG_TARGET_ARCH&lt;/code&gt;, not &lt;code&gt;cfg!(target_arch)&lt;/code&gt;. Inside &lt;code&gt;build.rs&lt;/code&gt;, &lt;code&gt;cfg!&lt;/code&gt; describes the machine running the build script, not the machine you&#39;re compiling &lt;em&gt;for&lt;/em&gt;. It makes no difference in a normal build, but it breaks silently when you cross-compile.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;cc&lt;/code&gt; crate finds a C compiler (&lt;code&gt;gcc&lt;/code&gt;, &lt;code&gt;clang&lt;/code&gt;, or MSVC), compiles your files into a static library, and tells Cargo to link it. You don&#39;t need to write any linker flags yourself.&lt;/p&gt;
&lt;h3&gt;Step 5: Call Everything From Rust&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/main.rs&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;simple_checksum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; len&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token attribute attr-name&quot;&gt;#[cfg(all(target_arch = &lt;span class=&quot;token string&quot;&gt;&quot;x86_64&quot;&lt;/span&gt;, target_os = &lt;span class=&quot;token string&quot;&gt;&quot;linux&quot;&lt;/span&gt;))]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;add_asm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/// Safe wrapper around the C checksum function.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;checksum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// SAFETY: the pointer and length come from a valid slice,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// and the C function only reads `len` bytes.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;simple_checksum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;as_ptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token attribute attr-name&quot;&gt;#[cfg(all(target_arch = &lt;span class=&quot;token string&quot;&gt;&quot;x86_64&quot;&lt;/span&gt;, target_os = &lt;span class=&quot;token string&quot;&gt;&quot;linux&quot;&lt;/span&gt;))]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i64&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// SAFETY: add_asm is a pure function with no memory access.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add_asm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; msg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;b&quot;hello from Rust&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;checksum = {:#010x}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;checksum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token attribute attr-name&quot;&gt;#[cfg(all(target_arch = &lt;span class=&quot;token string&quot;&gt;&quot;x86_64&quot;&lt;/span&gt;, target_os = &lt;span class=&quot;token string&quot;&gt;&quot;linux&quot;&lt;/span&gt;))]&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;2 + 40 = {}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run it:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;cargo&lt;/span&gt; run&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should see the checksum printed, followed by &lt;code&gt;2 + 40 = 42&lt;/code&gt;. That&#39;s the whole loop: write C or assembly, describe it in an &lt;code&gt;extern&lt;/code&gt; block, wrap it safely, and let Cargo build it all.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Put the &lt;code&gt;extern&lt;/code&gt; block and the safe wrappers in their own module, such as &lt;code&gt;ffi.rs&lt;/code&gt;. The rest of your codebase should never see the word &lt;code&gt;unsafe&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Using Inline Assembly Directly in Rust&lt;/h2&gt;
&lt;p&gt;You don&#39;t always need a separate file. For short snippets, Rust has built-in support through the &lt;code&gt;asm!&lt;/code&gt; macro, which has been stable since Rust 1.59.&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;arch&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;asm&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token attribute attr-name&quot;&gt;#[cfg(target_arch = &lt;span class=&quot;token string&quot;&gt;&quot;x86_64&quot;&lt;/span&gt;)]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;add_inline&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;u64&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;mut&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token macro property&quot;&gt;asm!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;add {0}, {1}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;inout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pure&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nomem&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nostack&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    result
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s break that down:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;{0}&lt;/code&gt; and &lt;code&gt;{1}&lt;/code&gt; are placeholders. Rust picks the actual registers for you, which is much safer than hard-coding them.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inout(reg) result&lt;/code&gt; means &amp;quot;this value goes in and comes back out.&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;in(reg) b&lt;/code&gt; means &amp;quot;read-only input.&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;options(pure, nomem, nostack)&lt;/code&gt; are promises to the compiler: no side effects, no memory access, no stack use. These let it optimize aggressively, so &lt;strong&gt;only add them if they&#39;re true.&lt;/strong&gt; If you lie, you get bugs that are very hard to trace.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Inline &lt;code&gt;asm!&lt;/code&gt; vs. Separate &lt;code&gt;.S&lt;/code&gt; Files&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Inline &lt;code&gt;asm!&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Separate &lt;code&gt;.S&lt;/code&gt; file&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Register allocation&lt;/td&gt;
&lt;td&gt;Compiler handles it&lt;/td&gt;
&lt;td&gt;You handle it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inlining&lt;/td&gt;
&lt;td&gt;Can be inlined into callers&lt;/td&gt;
&lt;td&gt;Always a real function call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setup&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Needs &lt;code&gt;build.rs&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;A few instructions&lt;/td&gt;
&lt;td&gt;Whole functions or routines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Syntax&lt;/td&gt;
&lt;td&gt;Intel by default on x86&lt;/td&gt;
&lt;td&gt;Whatever your assembler accepts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Two More Tools Worth Knowing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;global_asm!&lt;/code&gt;&lt;/strong&gt; lets you emit a whole block of assembly at module level, which is handy for defining entire functions without a build script.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Naked functions&lt;/strong&gt; give you full control over a function&#39;s prologue and epilogue. They were stabilized in Rust 1.88 using &lt;code&gt;#[unsafe(naked)]&lt;/code&gt; and &lt;code&gt;naked_asm!&lt;/code&gt;. Check your compiler version before relying on them.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Generating Bindings Automatically With bindgen&lt;/h2&gt;
&lt;p&gt;Hand-writing &lt;code&gt;extern&lt;/code&gt; blocks is fine for three functions. For a library with three hundred, it&#39;s a recipe for typos.&lt;/p&gt;
&lt;p&gt;That&#39;s where &lt;code&gt;bindgen&lt;/code&gt; comes in. It reads your C header and generates the Rust declarations for you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Cargo.toml&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-toml&quot;&gt;&lt;code class=&quot;language-toml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token table class-name&quot;&gt;build-dependencies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;cc&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;bindgen&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0.71&quot;&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;# check crates.io for the latest version&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;csrc/wrapper.h&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;checksum.h&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;build.rs&lt;/code&gt; (bindgen part)&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;path&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;PathBuf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// ... cc::Build code from before ...&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; bindings &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;bindgen&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;csrc/wrapper.h&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse_callbacks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;bindgen&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;CargoCallbacks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;generate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;failed to generate bindings&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; out &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PathBuf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;env&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;OUT_DIR&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unwrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    bindings
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write_to_file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;bindings.rs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;failed to write bindings&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/ffi.rs&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token attribute attr-name&quot;&gt;#![allow(non_upper_case_globals)]&lt;/span&gt;
&lt;span class=&quot;token attribute attr-name&quot;&gt;#![allow(non_camel_case_types)]&lt;/span&gt;
&lt;span class=&quot;token attribute attr-name&quot;&gt;#![allow(non_snake_case)]&lt;/span&gt;
&lt;span class=&quot;token attribute attr-name&quot;&gt;#![allow(dead_code)]&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;include!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token macro property&quot;&gt;concat!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token macro property&quot;&gt;env!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;OUT_DIR&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/bindings.rs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A few things to know about &lt;code&gt;bindgen&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It needs &lt;strong&gt;libclang&lt;/strong&gt; installed on your machine. On Ubuntu or Debian, that&#39;s &lt;code&gt;sudo apt install libclang-dev&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The generated code is raw and unsafe. You still need to write safe wrappers on top.&lt;/li&gt;
&lt;li&gt;For very large libraries, commit the generated file to your repo so contributors don&#39;t all need libclang.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Going the Other Way: Calling Rust From C&lt;/h2&gt;
&lt;p&gt;Integration works in both directions. If you&#39;re migrating a C project to Rust, you&#39;ll want C code to call your new Rust functions.&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token attribute attr-name&quot;&gt;#[unsafe(no_mangle)]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;rust_multiply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    a &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; b
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;extern &amp;quot;C&amp;quot;&lt;/code&gt; gives the function the C calling convention.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#[unsafe(no_mangle)]&lt;/code&gt; stops Rust from renaming the symbol, so C can find it. On editions before 2024, write it as plain &lt;code&gt;#[no_mangle]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To make C happy, you also need a header. Instead of writing it by hand, use &lt;strong&gt;&lt;code&gt;cbindgen&lt;/code&gt;&lt;/strong&gt;, which reads your Rust code and generates a &lt;code&gt;.h&lt;/code&gt; file.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;cargo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; cbindgen
cbindgen &lt;span class=&quot;token parameter variable&quot;&gt;--lang&lt;/span&gt; c &lt;span class=&quot;token parameter variable&quot;&gt;--output&lt;/span&gt; rust_api.h&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To build a library that C can link against, set the crate type in &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-toml&quot;&gt;&lt;code class=&quot;language-toml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token table class-name&quot;&gt;lib&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;crate-type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;staticlib&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;# or &quot;cdylib&quot; for a shared library&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;The Panic Problem&lt;/h3&gt;
&lt;p&gt;What happens if Rust code panics while being called from C? Historically, unwinding across an &lt;code&gt;extern &amp;quot;C&amp;quot;&lt;/code&gt; boundary was undefined behavior. Modern Rust makes &lt;code&gt;extern &amp;quot;C&amp;quot;&lt;/code&gt; functions abort the process if a panic tries to escape. That&#39;s safer than undefined behavior, but it still kills your program.&lt;/p&gt;
&lt;p&gt;The fix is to catch panics at the boundary:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;panic&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;catch_unwind&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token attribute attr-name&quot;&gt;#[unsafe(no_mangle)]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;rust_safe_divide&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;catch_unwind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token closure-params&quot;&gt;&lt;span class=&quot;token closure-punctuation punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token closure-punctuation punctuation&quot;&gt;|&lt;/span&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unwrap_or&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Return an error code instead of letting a panic escape. C programmers already expect that style.&lt;/p&gt;
&lt;h2&gt;Handling Strings, Memory, and Ownership&lt;/h2&gt;
&lt;p&gt;This is where most real-world FFI bugs live. The rule of thumb is simple: &lt;strong&gt;whoever allocates the memory must free it.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Passing Strings to C&lt;/h3&gt;
&lt;p&gt;Rust strings aren&#39;t null-terminated. C strings are. Use &lt;code&gt;CString&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;ffi&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;CString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c_char&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; c_char&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; s &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello from Rust&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;no interior null bytes&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;as_ptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Keep &lt;code&gt;s&lt;/code&gt; alive for as long as C uses the pointer. A classic mistake is writing &lt;code&gt;CString::new(&amp;quot;hi&amp;quot;).unwrap().as_ptr()&lt;/code&gt;, which drops the &lt;code&gt;CString&lt;/code&gt; immediately and hands C a dangling pointer.&lt;/p&gt;
&lt;h3&gt;Reading Strings From C&lt;/h3&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;ffi&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;CStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c_char&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;read_c_string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ptr&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; c_char&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CStr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from_ptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ptr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;to_string_lossy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;into_owned&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Memory Ownership Rules&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Memory allocated by C&lt;/strong&gt; (with &lt;code&gt;malloc&lt;/code&gt;) must be freed by C (&lt;code&gt;free&lt;/code&gt;). Never pass it to Rust&#39;s allocator.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory allocated by Rust&lt;/strong&gt; (like a &lt;code&gt;Box&lt;/code&gt; or &lt;code&gt;Vec&lt;/code&gt;) must be freed by Rust. If you hand it to C, give C a matching &lt;code&gt;free_thing()&lt;/code&gt; function to call back.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Borrowed pointers&lt;/strong&gt; should never be stored by C beyond the call unless you&#39;ve guaranteed the data lives long enough.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Real-World Use Cases&lt;/h2&gt;
&lt;p&gt;Here&#39;s where this kind of integration shows up in practice:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Wrapping system libraries&lt;/strong&gt; such as libc, libpcap, or libusb, which is how many &lt;code&gt;*-sys&lt;/code&gt; crates work.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Embedded and OS development&lt;/strong&gt;, where startup code and interrupt handlers are often small assembly routines.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cryptography&lt;/strong&gt;, where libraries pair a Rust API with hand-tuned assembly for hot loops.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CLI and developer tools&lt;/strong&gt;, where you might reuse an existing C parser or compression library instead of reimplementing it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance experiments&lt;/strong&gt;, where you replace one function with an assembly version and benchmark the difference.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Best Practices&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Isolate &lt;code&gt;unsafe&lt;/code&gt;.&lt;/strong&gt; Keep FFI declarations in one module and expose only safe functions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Document every &lt;code&gt;unsafe&lt;/code&gt; block&lt;/strong&gt; with a &lt;code&gt;// SAFETY:&lt;/code&gt; comment explaining why it&#39;s sound.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use &lt;code&gt;#[repr(C)]&lt;/code&gt;&lt;/strong&gt; on every shared struct.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Never let panics cross the boundary.&lt;/strong&gt; Catch them and return error codes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check for null pointers&lt;/strong&gt; before dereferencing anything that came from C.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Benchmark before writing assembly.&lt;/strong&gt; Use &lt;code&gt;cargo bench&lt;/code&gt; or Criterion, and compare against plain Rust first.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gate platform-specific code&lt;/strong&gt; with &lt;code&gt;cfg&lt;/code&gt; attributes and always provide a portable fallback.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test under sanitizers.&lt;/strong&gt; Tools like Valgrind and AddressSanitizer catch memory errors that Rust can&#39;t see across FFI.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add &lt;code&gt;rerun-if-changed&lt;/code&gt;&lt;/strong&gt; lines so &lt;code&gt;build.rs&lt;/code&gt; doesn&#39;t recompile everything on every build.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consider a &lt;code&gt;-sys&lt;/code&gt; crate&lt;/strong&gt; if you&#39;re wrapping a library others might use. Keep raw bindings in &lt;code&gt;foo-sys&lt;/code&gt; and the safe API in &lt;code&gt;foo&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Mixing Rust with C and assembly sounds intimidating, but the workflow is quite consistent once you&#39;ve seen it. Declare the foreign functions, compile the foreign code through &lt;code&gt;build.rs&lt;/code&gt; and the &lt;code&gt;cc&lt;/code&gt; crate, wrap the unsafe parts in safe functions, and test carefully.&lt;/p&gt;
&lt;p&gt;Here are the takeaways worth remembering:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;cc&lt;/code&gt; to compile C and &lt;code&gt;.S&lt;/code&gt; files during &lt;code&gt;cargo build&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;bindgen&lt;/code&gt; for big headers and &lt;code&gt;cbindgen&lt;/code&gt; when C needs to call Rust.&lt;/li&gt;
&lt;li&gt;Match types carefully and add &lt;code&gt;#[repr(C)]&lt;/code&gt; to shared structs.&lt;/li&gt;
&lt;li&gt;Keep &lt;code&gt;unsafe&lt;/code&gt; in one small module and document why it&#39;s sound.&lt;/li&gt;
&lt;li&gt;Never let panics cross the boundary, and always follow the &amp;quot;whoever allocates, frees&amp;quot; rule.&lt;/li&gt;
&lt;li&gt;Reach for assembly only after a benchmark tells you to.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Start small. Wrap one C function, get it running, then grow from there. Once that first &lt;code&gt;cargo run&lt;/code&gt; prints the right answer, the rest is repetition.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Friendly Errors in a Rust CLI with anyhow</title>
    <link href="https://www.rajeevedmonds.com/blog/friendly-errors-with-anyhow/" rel="alternate" type="text/html"/>
    <id>https://www.rajeevedmonds.com/blog/friendly-errors-with-anyhow/</id>
    <published>2026-09-22T00:00:00.000Z</published>
    <updated>2026-09-22T00:00:00.000Z</updated>
    <summary>Use anyhow&#39;s Context to turn cryptic failures like &#39;No such file or directory&#39; into messages your users can actually act on.</summary>
    <content type="html">&lt;p&gt;The default failure message from a lot of Rust code is technically correct and completely unhelpful: &lt;code&gt;No such file or directory (os error 2)&lt;/code&gt;. Which file? Doing what? In a command-line tool, the error message &lt;em&gt;is&lt;/em&gt; the user interface, so it&#39;s worth a few extra lines.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://docs.rs/anyhow&quot;&gt;anyhow&lt;/a&gt; crate is built for exactly this in application code. It gives you one catch-all &lt;code&gt;Result&lt;/code&gt; type, and a way to attach context as an error travels up the call stack.&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;cargo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; anyhow&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Add context at each step&lt;/h2&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;fs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;anyhow&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;bail&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;read_port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;fs&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read_to_string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;with_context&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token closure-params&quot;&gt;&lt;span class=&quot;token closure-punctuation punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token closure-punctuation punctuation&quot;&gt;|&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token macro property&quot;&gt;format!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;could not read config file `{path}`&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; port&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;u16&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; text
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;with_context&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token closure-params&quot;&gt;&lt;span class=&quot;token closure-punctuation punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token closure-punctuation punctuation&quot;&gt;|&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token macro property&quot;&gt;format!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;`{path}` does not contain a valid port number&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; port &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token macro property&quot;&gt;bail!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;port {port} is reserved; choose 1024 or higher&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; port &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;read_port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;port.txt&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;listening on port {port}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Three pieces do the work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;anyhow::Result&amp;lt;T&amp;gt;&lt;/code&gt; is shorthand for &lt;code&gt;Result&amp;lt;T, anyhow::Error&amp;gt;&lt;/code&gt;. Any error type that implements &lt;code&gt;std::error::Error&lt;/code&gt; converts into it automatically, so the &lt;code&gt;?&lt;/code&gt; operator just works.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.with_context(|| ...)&lt;/code&gt; wraps the original error with your message. The closure form only builds the string if there actually was an error.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bail!&lt;/code&gt; returns early with a brand-new error, for problems that aren&#39;t wrapping anything, like the range check above.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What the user sees&lt;/h2&gt;
&lt;p&gt;Returning &lt;code&gt;Result&lt;/code&gt; from &lt;code&gt;main&lt;/code&gt; means Rust prints the error and exits with status 1. If &lt;code&gt;port.txt&lt;/code&gt; is missing:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Error: could not read config file `port.txt`

Caused by:
    No such file or directory (os error 2)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And if the file contains &lt;code&gt;abc&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Error: `port.txt` does not contain a valid port number

Caused by:
    invalid digit found in string&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your message comes first and the underlying cause follows. Nothing was lost, and the user now knows what to fix.&lt;/p&gt;
&lt;h2&gt;A note on where to use it&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;anyhow&lt;/code&gt; is a great fit for binaries, where you mostly want to report an error and exit. If you&#39;re writing a library, callers often need to match on specific failures. That&#39;s where a typed error, usually derived with the &lt;a href=&quot;https://docs.rs/thiserror&quot;&gt;thiserror&lt;/a&gt; crate, is the better tool. Many projects use both: &lt;code&gt;thiserror&lt;/code&gt; inside the library, &lt;code&gt;anyhow&lt;/code&gt; in the &lt;code&gt;main.rs&lt;/code&gt; that calls it.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Parsing CLI Arguments in Rust with clap&#39;s Derive API</title>
    <link href="https://www.rajeevedmonds.com/blog/parse-cli-arguments-with-clap/" rel="alternate" type="text/html"/>
    <id>https://www.rajeevedmonds.com/blog/parse-cli-arguments-with-clap/</id>
    <published>2026-09-15T00:00:00.000Z</published>
    <updated>2026-09-15T00:00:00.000Z</updated>
    <summary>Turn a plain struct into a full argument parser, complete with flags, options, help text and --version, in about a dozen lines.</summary>
    <content type="html">&lt;p&gt;Every command-line tool starts the same way: it needs to read some arguments. You can loop over &lt;code&gt;std::env::args()&lt;/code&gt; by hand, but you&#39;ll be rewriting help text, validation and error messages within the hour. The &lt;a href=&quot;https://docs.rs/clap&quot;&gt;clap&lt;/a&gt; crate handles all of that, and its derive API lets you describe your whole CLI as a plain struct.&lt;/p&gt;
&lt;h2&gt;Set it up&lt;/h2&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;cargo&lt;/span&gt; new linecount
&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; linecount
&lt;span class=&quot;token function&quot;&gt;cargo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; clap &lt;span class=&quot;token parameter variable&quot;&gt;--features&lt;/span&gt; derive&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Describe the arguments as a struct&lt;/h2&gt;
&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;std&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;PathBuf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;clap&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Parser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/// A tiny example CLI&lt;/span&gt;
&lt;span class=&quot;token attribute attr-name&quot;&gt;#[derive(Parser, Debug)]&lt;/span&gt;
&lt;span class=&quot;token attribute attr-name&quot;&gt;#[command(version)]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token type-definition class-name&quot;&gt;Cli&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;/// File to read&lt;/span&gt;
    path&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PathBuf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/// Print extra detail&lt;/span&gt;
    &lt;span class=&quot;token attribute attr-name&quot;&gt;#[arg(short, long)]&lt;/span&gt;
    verbose&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/// Stop after this many lines&lt;/span&gt;
    &lt;span class=&quot;token attribute attr-name&quot;&gt;#[arg(short = &#39;n&#39;, long, default_value_t = 1000)]&lt;/span&gt;
    limit&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; cli &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Cli&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; cli&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;verbose &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token macro property&quot;&gt;eprintln!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;verbose mode on&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token macro property&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;would read up to {} lines from {}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cli&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;limit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cli&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s the whole parser. A few things are happening here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A field with no attribute (&lt;code&gt;path&lt;/code&gt;) becomes a required positional argument.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;bool&lt;/code&gt; field becomes a flag. &lt;code&gt;short&lt;/code&gt; and &lt;code&gt;long&lt;/code&gt; give you &lt;code&gt;-v&lt;/code&gt; and &lt;code&gt;--verbose&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The field&#39;s type is the validation. Pass &lt;code&gt;--limit abc&lt;/code&gt; and clap rejects it with a clear error, because &lt;code&gt;abc&lt;/code&gt; isn&#39;t a &lt;code&gt;usize&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Doc comments (&lt;code&gt;///&lt;/code&gt;) become the help text, so your documentation and your &lt;code&gt;--help&lt;/code&gt; never drift apart.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Try it&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;cargo run -- --help&lt;/code&gt; now prints something like this, with no extra code:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;A tiny example CLI

Usage: linecount [OPTIONS] &lt;PATH&gt;

Arguments:
  &lt;PATH&gt;  File to read

Options:
  -v, --verbose        Print extra detail
  -n, --limit &lt;LIMIT&gt;  Stop after this many lines [default: 1000]
  -h, --help           Print help
  -V, --version        Print version&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Cli::parse()&lt;/code&gt; also handles the failure path for you: on bad input it prints the error and exits with status 2, the conventional code for a usage error. If you&#39;d rather handle that yourself, &lt;code&gt;Cli::try_parse()&lt;/code&gt; returns a &lt;code&gt;Result&lt;/code&gt; instead.&lt;/p&gt;
&lt;p&gt;From here, the natural next steps are subcommands (put &lt;code&gt;#[derive(Subcommand)]&lt;/code&gt; on an enum) and value validation with &lt;code&gt;value_parser&lt;/code&gt;. Both are just more attributes on the same struct.&lt;/p&gt;
</content>
  </entry>
</feed>
