<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Robert Winslow</title>
    <description>The latest articles on DEV Community by Robert Winslow (@robert_winslow).</description>
    <link>https://dev.to/robert_winslow</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F175991%2F3d49c8d1-8265-4dcb-ad79-569024c15180.jpg</url>
      <title>DEV Community: Robert Winslow</title>
      <link>https://dev.to/robert_winslow</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/robert_winslow"/>
    <language>en</language>
    <item>
      <title>Tutorial: Use FlatBuffers in Rust</title>
      <dc:creator>Robert Winslow</dc:creator>
      <pubDate>Tue, 04 Jun 2019 20:31:00 +0000</pubDate>
      <link>https://dev.to/robert_winslow/tutorial-use-flatbuffers-in-rust-262k</link>
      <guid>https://dev.to/robert_winslow/tutorial-use-flatbuffers-in-rust-262k</guid>
      <description>&lt;p&gt;(This article is &lt;a href="https://rwinslow.com/posts/use-flatbuffers-in-rust/"&gt;cross-posted&lt;/a&gt; from &lt;a href="https://rwinslow.com"&gt;my blog&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/google/flatbuffers"&gt;FlatBuffers project&lt;/a&gt; is an extremely efficient schema-versioned serialization library. In this tutorial, you'll learn how to use it in Rust.&lt;/p&gt;

&lt;p&gt;To learn more about why we need yet another way to encode data, go read my post &lt;a href="https://rwinslow.com/posts/why-flatbuffers/"&gt;Why FlatBuffers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;FlatBuffers is a serialization format from Google. It's really fast at reading and writing your data: much quicker than JSON or XML, and often faster than Google's other format, Protocol Buffers. It's schema-versioned, which means your data has integrity (like in a relational database). FlatBuffers supports thirteen programming languages: C++, C#, C, Dart, Go, Java, JavaScript, Lobster, Lua, PHP, Python, Rust, and TypeScript.&lt;/p&gt;

&lt;p&gt;This post will show you how to set up FlatBuffers and then use it in a demo Rust program.&lt;/p&gt;

&lt;p&gt;(Full disclosure: I maintain the Golang, Python, and Rust FlatBuffers codebases.)&lt;/p&gt;

&lt;p&gt;This tutorial has seven short parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the FlatBuffers compiler&lt;/li&gt;
&lt;li&gt;Create a new Cargo project (if needed)&lt;/li&gt;
&lt;li&gt;Write a FlatBuffers schema definition&lt;/li&gt;
&lt;li&gt;Generate Rust accessor code from the schema&lt;/li&gt;
&lt;li&gt;Install the FlatBuffers Rust runtime library&lt;/li&gt;
&lt;li&gt;Write a demo Rust program to encode and decode example data&lt;/li&gt;
&lt;li&gt;Learn more and get involved&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you'd like to see all of the code in one place, I've put the project up at &lt;a href="https://github.com/rw/rust_flatbuffers_example"&gt;a GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a id="section-installation"&gt;&lt;/a&gt;1. Install the FlatBuffers compiler
&lt;/h2&gt;

&lt;p&gt;First things first: let's install the compiler.&lt;/p&gt;

&lt;p&gt;The compiler is used only in development. That means you have no new system dependencies to worry about in production environments!&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation with Homebrew on OSX
&lt;/h3&gt;

&lt;p&gt;On my OSX system, I use &lt;a href="https://github.com/Homebrew/homebrew"&gt;Homebrew&lt;/a&gt; to manage packages. To update the Homebrew library and install FlatBuffers, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew update
&lt;span class="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;flatbuffers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;(As is usual on my blog, I indicate CLI input with the prefix &lt;code&gt;$&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;Personally, I like to install the latest development version from the official Git repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew update
&lt;span class="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;flatbuffers &lt;span class="nt"&gt;--HEAD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If successful, you will have the &lt;code&gt;flatc&lt;/code&gt; program accessible from your shell. To verify it's installed, execute &lt;code&gt;flatc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;flatc
flatc: missing input files
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Other installation methods
&lt;/h3&gt;

&lt;p&gt;If you'd like to install from source, install a Windows executable, or build for Visual Studio, head over to my post &lt;a href="https://rwinslow.com/posts/how-to-install-flatbuffers/"&gt;Installing FlatBuffers&lt;/a&gt; for more.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a id="section-cargo-setup"&gt;&lt;/a&gt;2. Create a new Cargo project (if needed)
&lt;/h2&gt;

&lt;p&gt;(If you're adding FlatBuffers to an existing Rust project, you can skip this step.)&lt;/p&gt;

&lt;p&gt;Create a basic Cargo configuration with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cargo new rust_flatbuffers_example
     Created binary &lt;span class="o"&gt;(&lt;/span&gt;application&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;rust_flatbuffers_example&lt;span class="sb"&gt;`&lt;/span&gt; package
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There will now be a directory called &lt;code&gt;rust_flatbuffers_example&lt;/code&gt;. Change the current working directory to that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;rust_flatbuffers_example
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, note that the directory contains the following files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree
&lt;span class="nb"&gt;.&lt;/span&gt;
|-- Cargo.toml
&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nt"&gt;--&lt;/span&gt; src
    &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nt"&gt;--&lt;/span&gt; main.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, check that the Cargo package is properly configured. Do this by running the example program that Cargo automatically generated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cargo run --quiet
Hello, world!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you do not see this output, then please have a look at the &lt;a href="https://doc.rust-lang.org/cargo/"&gt;official documentation on setting up Rust and Cargo&lt;/a&gt; to troubleshoot your configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a id="section-schema"&gt;&lt;/a&gt;3. Write a FlatBuffers schema definition
&lt;/h2&gt;

&lt;p&gt;All data in FlatBuffers are defined by schemas. Schemas in FlatBuffers are plain text files, and they are similar in purpose to schemas in databases like Postgres.&lt;/p&gt;

&lt;p&gt;We'll work with data that make up user details for a website. It's a trivial example, but good for an introduction. Here's the schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// myschema.fbs
namespace users;

table User {
  name:string;
  id:ulong;
}

root_type User;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Place the above code in a file called &lt;code&gt;myschema.fbs&lt;/code&gt;, in the root of your Cargo project.&lt;/p&gt;

&lt;p&gt;This schema defines &lt;code&gt;User&lt;/code&gt;, which holds one user's &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;id&lt;/code&gt;. The namespace for these types is &lt;code&gt;users&lt;/code&gt; (which will be the generated Rust package name). The topmost type in our object hierarchy is the root type &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Schemas are a core part of FlatBuffers, and we're barely scratching the surface with this one. It's possible to have default values, vectors, objects-within-objects, enums, and more. If you're curious, go read the &lt;a href="https://google.github.io/flatbuffers/md__schemas.html"&gt;documentation on the schema format&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a id="section-generate"&gt;&lt;/a&gt;4. Generate Rust accessor code from the schema
&lt;/h2&gt;

&lt;p&gt;The next step is to use the &lt;code&gt;flatc&lt;/code&gt; compiler to generate Rust code for us. It takes a schema file as input, and outputs ready-to-use Rust code.&lt;/p&gt;

&lt;p&gt;In the directory with the &lt;code&gt;myschema.fbs&lt;/code&gt; file, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;flatc &lt;span class="nt"&gt;--rust&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; src myschema.fbs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will generate Rust code in a new file called &lt;code&gt;myschema_generated.rs&lt;/code&gt; in the pre-existing &lt;code&gt;src&lt;/code&gt; directory. Here's what our project looks like afterwards:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree
&lt;span class="nb"&gt;.&lt;/span&gt;
|-- Cargo.lock
|-- Cargo.toml
|-- myschema.fbs
&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nt"&gt;--&lt;/span&gt; src
    |-- main.rs
    &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nt"&gt;--&lt;/span&gt; myschema_generated.rs

1 directory, 6 files
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that one file is generated for each schema file.&lt;/p&gt;

&lt;p&gt;A quick browse of &lt;code&gt;src/myschema_generated.rs&lt;/code&gt; shows that there are three sections to the generated file. Here's how to think about the different function groups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type definition and initializer for reading &lt;code&gt;User&lt;/code&gt; data
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_root_as_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_size_prefixed_root_as_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;init_from_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;flatbuffers&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Instance methods providing read access to &lt;code&gt;User&lt;/code&gt; data
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Functions used to create new &lt;code&gt;User&lt;/code&gt; objects
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="n"&gt;fbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nn"&gt;flatbuffers&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FlatBufferBuilder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;UserArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;flatbuffers&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;WIPOffset&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;(Note that I've elided some of the lifetime annotations in the above code.)&lt;/p&gt;

&lt;p&gt;We'll use these functions when we write the demo program.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a id="section-install-runtime"&gt;&lt;/a&gt;5. Install the FlatBuffers Rust runtime library
&lt;/h2&gt;

&lt;p&gt;The official FlatBuffers Rust runtime package is hosted on crates.io: &lt;a href="https://crates.io/crates/flatbuffers"&gt;Official FlatBuffers Runtime Rust Library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To use this in your project, add &lt;code&gt;flatbuffers&lt;/code&gt; to your dependencies manifest in &lt;code&gt;Cargo.toml&lt;/code&gt;. The file should now look similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[package]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"rust_flatbuffers_example"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;
&lt;span class="py"&gt;authors&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"rw &amp;lt;me@rwinslow.com&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;edition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2018"&lt;/span&gt;

&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;flatbuffers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I use &lt;code&gt;*&lt;/code&gt; to fetch the latest package version. In general, you'll want to pick a specific version. You can learn more about this in the documentation for the &lt;a href="https://doc.rust-lang.org/cargo/guide/dependencies.html"&gt;Cargo dependencies format&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a id="section-demo"&gt;&lt;/a&gt;6. Write a demo Rust program to encode and decode example data
&lt;/h2&gt;

&lt;p&gt;Now, we'll overwrite the default Cargo "Hello World" program with code to write and read our FlatBuffers data.&lt;/p&gt;

&lt;p&gt;(We do this for the sake of simplicity, so that I can avoid explaining the Cargo build system here. To learn more about Cargo projects, head over to the &lt;a href="https://doc.rust-lang.org/cargo/guide/project-layout.html"&gt;official documentation on Cargo project file layouts&lt;/a&gt;.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Imports
&lt;/h3&gt;

&lt;p&gt;To begin, we will import the generated module using the &lt;code&gt;mod&lt;/code&gt; statement. Place the following code in &lt;code&gt;src/main.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;// src/main.rs part 1 of 4: imports&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;flatbuffers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;myschema_generated&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;flatbuffers&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FlatBufferBuilder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;myschema_generated&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;users&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UserArgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;finish_user_buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_root_as_user&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This usage of the &lt;code&gt;mod&lt;/code&gt; keyword instructs the Rust build system to make the items in the file called &lt;code&gt;myschema_generated.rs&lt;/code&gt; accessible to our program. The &lt;code&gt;use&lt;/code&gt; statement makes two generated types, &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;UserArgs&lt;/code&gt;, accessible to our code with convenient names.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing
&lt;/h3&gt;

&lt;p&gt;FlatBuffer objects are stored directly in byte slices. Each Flatbuffers object is constructed using the generated functions we made with the &lt;code&gt;flatc&lt;/code&gt; compiler.&lt;/p&gt;

&lt;p&gt;Append the following snippet to your &lt;code&gt;src/main.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;// src/main.rs part 2 of 4: make_user function&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;make_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bldr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;FlatBufferBuilder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Reset the `bytes` Vec to a clean state.&lt;/span&gt;
    &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="nf"&gt;.clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c"&gt;// Reset the `FlatBufferBuilder` to a clean state.&lt;/span&gt;
    &lt;span class="n"&gt;bldr&lt;/span&gt;&lt;span class="nf"&gt;.reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c"&gt;// Create a temporary `UserArgs` object to build a `User` object.&lt;/span&gt;
    &lt;span class="c"&gt;// (Note how we call `bldr.create_string` to create the UTF-8 string&lt;/span&gt;
    &lt;span class="c"&gt;// ergonomically.)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bldr&lt;/span&gt;&lt;span class="nf"&gt;.create_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c"&gt;// Call the `User::create` function with the `FlatBufferBuilder` and our&lt;/span&gt;
    &lt;span class="c"&gt;// UserArgs object, to serialize the data to the FlatBuffer. The returned&lt;/span&gt;
    &lt;span class="c"&gt;// value is an offset used to track the location of this serializaed data.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;user_offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;User&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bldr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c"&gt;// Finish the write operation by calling the generated function&lt;/span&gt;
    &lt;span class="c"&gt;// `finish_user_buffer` with the `user_offset` created by `User::create`.&lt;/span&gt;
    &lt;span class="nf"&gt;finish_user_buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bldr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_offset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c"&gt;// Copy the serialized FlatBuffers data to our own byte buffer.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;finished_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bldr&lt;/span&gt;&lt;span class="nf"&gt;.finished_data&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="nf"&gt;.extend_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;finished_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This function takes a FlatBuffers &lt;code&gt;Builder&lt;/code&gt; object and uses generated methods to write the user's name and ID.&lt;/p&gt;

&lt;p&gt;Note that the &lt;code&gt;name&lt;/code&gt; string is created with the &lt;code&gt;bldr.create_string&lt;/code&gt; function. We do this because, in FlatBuffers, variable-length data like strings need to be created &lt;em&gt;outside&lt;/em&gt; the object that references them. In the code above, this is still ergonomic because we can call &lt;code&gt;bldr.create_string&lt;/code&gt; inline from the &lt;code&gt;UserArgs&lt;/code&gt; object.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading
&lt;/h3&gt;

&lt;p&gt;FlatBuffer objects are stored as byte slices, and we access the data inside using the generated functions (that the &lt;code&gt;flatc&lt;/code&gt; compiler made for us in &lt;code&gt;myschema_generated.rs&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Append the following code to your &lt;code&gt;src/main.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;// src/main.rs part 3 of 4: read_user function&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;read_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_root_as_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="nf"&gt;.name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="nf"&gt;.id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This function takes a byte slice as input, and initializes a FlatBuffer reader for the &lt;code&gt;User&lt;/code&gt; type. It then gives us access to the name and ID values in the byte slice.&lt;/p&gt;

&lt;h3&gt;
  
  
  The main function
&lt;/h3&gt;

&lt;p&gt;Now we tie it all together. This is the &lt;code&gt;main&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;// src/main.rs part 4 of 4: main function&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;bldr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;FlatBufferBuilder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c"&gt;// Write the provided `name` and `id` into the `bytes` Vec using the&lt;/span&gt;
    &lt;span class="c"&gt;// FlatBufferBuilder `bldr`:&lt;/span&gt;
    &lt;span class="nf"&gt;make_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;bldr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Arthur Dent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c"&gt;// Now, `bytes` contains the serialized representation of our User object.&lt;/span&gt;

    &lt;span class="c"&gt;// To read the serialized data, call our `read_user` function to decode&lt;/span&gt;
    &lt;span class="c"&gt;// the `user` and `id`:&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;read_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="c"&gt;// Show the decoded information:&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{} has id {}. The encoded data is {} bytes long."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This function writes, reads, then prints our data. Note that &lt;code&gt;bytes&lt;/code&gt; is the byte vector with encoded data. This is the serialized data you could send over the network, or save to a file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running it
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cargo run
Arthur Dent has &lt;span class="nb"&gt;id &lt;/span&gt;42. The buffer is 48 bytes long.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To recap, what we've done here is write a short program that uses generated code to write, then read, a byte slice in which we encoded data for an example User. This User has name "Arthur Dent" and ID 42.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a id="section-involved"&gt;&lt;/a&gt;7. Learn more and get involved
&lt;/h2&gt;

&lt;p&gt;FlatBuffers is an active open-source project, with backing from Google. It's Apache-licensed, and available for C++, C#, C, Dart, Go, Java, JavaScript, Lobster, Lua, PHP, Python, Rust, and TypeScript (with more languages on the way!).&lt;/p&gt;

&lt;p&gt;Here are some resources to get you started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/google/flatbuffers"&gt;GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google/flatbuffers/issues"&gt;Issue tracker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://google.github.io/flatbuffers/"&gt;Official documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And my &lt;a href="https://rwinslow.com/tags/flatbuffers/"&gt;additional blog posts on FlatBuffers&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>flatbuffers</category>
      <category>serialization</category>
      <category>filestorage</category>
    </item>
  </channel>
</rss>
