TRust-DNS: implementing futures-rs and tokio-rs support
So! To recap the bits, and where this all stands now:<p>The end goal is to implement &quot;Your Server is a Function&quot;  <a href="https:&#x2F;&#x2F;monkey.org&#x2F;~marius&#x2F;funsrv.pdf" rel="nofollow">https:&#x2F;&#x2F;monkey.org&#x2F;~marius&#x2F;funsrv.pdf</a> , that is, built on top of three primitives:<p>1. Futures<p>2. Services, which are functions of Request -&gt; Future&lt;Response&gt;<p>3. Filters, which takes a Request and a Service, and returns a Future&lt;Response&gt;<p>To do this, Tokio is built up of multiple packages that each have a focus.<p>At the lowest layer, you have two primitive libraries: futures and mio. Futures are a generic, no-allocation abstraction that looks something like this: <a href="https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.1.6&#x2F;futures&#x2F;future&#x2F;trait.Future.html" rel="nofollow">https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.1.6&#x2F;futures&#x2F;future&#x2F;trait.Future.ht...</a><p><pre><code>  pub trait Future {
      type Item;
      type Error;
      fn poll(&amp;mut self) -&gt; Poll&lt;Self::Item, Self::Error&gt;;
  }
</code></pre>
... and a bunch of more interesting methods built on top of poll. Futures, as you can see, can be generic over the kind of value they produce, as well as possible errors while producing said value. poll drives the future forward, and should never block. Usually, you don&#x27;t call poll directly, you create a Task, which represents a chain of futures, and tell it to run. It will then handle doing the right thing, calling the right methods in the right ways.<p>The second component is mio. Mio is a low-level, asynchronous I&#x2F;O library, that gives you the standard event loop stuff. In other words, it&#x27;s a very thin wrapper around epoll&#x2F;kqueue, and has an adapter to make iocp fit. There are deeper reasons that readiness was chosen over completion as a model, but I won&#x27;t get into that right now.<p>So, the lowest layer of tokio proper is tokio-core, which combines futures and mio to give you the ability to say &quot;give me an event loop. Chain some futures together. Run this chain on the event loop.&quot; But that&#x27;s still a fairly low-level interface. And it&#x27;s what&#x27;s being shown off here.<p>At the same level, tokio-service is what gives you the Service abstraction.<p>At the sort of middle layer, there&#x27;s a bunch of libraries that you can use, like tokio-proto, which gives a slightly higher-level interface for implementing network protocols.<p>Finally, the unreleased tokio package combines this ecosystem into an easy to use way to build servers, it&#x27;s the whole package. This &quot;tons of tiny packages&quot; approach means that if you want to extend tokio in some way, you pick the appropriate level of the stack for your task, and plug it in, and everything up the chain can benefit. It&#x27;s very modular and extensible.<p>In graphical form, check out this image: <a href="https:&#x2F;&#x2F;twitter.com&#x2F;rustconf&#x2F;status&#x2F;774734062636249089" rel="nofollow">https:&#x2F;&#x2F;twitter.com&#x2F;rustconf&#x2F;status&#x2F;774734062636249089</a> which comes from this talk: <a href="https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=bcrzfivXpc4" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=bcrzfivXpc4</a><p>The key enabler here is Rust&#x27;s zero-cost abstractions: last time we measured, tokio-core had a very small (less than half a percent, IIRC) overhead compared to writing a mio event loop by hand. And that&#x27;s before significant profiling effort has been done. So while in many languages, all of these layers would add up to significantly reduced speed, the idea here is that in Rust, they won&#x27;t. A significant portion of this is zero-allocation or single-allocation, for example.