aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorRobert <rw@users.noreply.github.com>2018-09-02 17:05:50 -0700
committerrw <me@rwinslow.com>2018-09-02 18:26:55 -0700
commit3c54fd964b6beae9a92955415568a001c9cea23d (patch)
tree08f625977a0de84337044abe4ca7beadb4d9ac22 /docs
parente7578548a5714dd278d798344d6619d8cbbfb4d9 (diff)
downloadflatbuffers-3c54fd964b6beae9a92955415568a001c9cea23d.tar.gz
Port FlatBuffers to Rust (#4898)
This is a port of FlatBuffers to Rust. It provides code generation and a runtime library derived from the C++ implementation. It utilizes the Rust type system to provide safe and fast traversal of FlatBuffers data. There are 188 tests, including many fuzz tests of roundtrips for various serialization scenarios. Initial benchmarks indicate that the canonical example payload can be written in ~700ns, and traversed in ~100ns. Rustaceans may be interested in the Follow, Push, and SafeSliceAccess traits. These traits lift traversals, reads, writes, and slice accesses into the type system, providing abstraction with no runtime penalty.
Diffstat (limited to 'docs')
-rw-r--r--docs/source/Compiler.md2
-rw-r--r--docs/source/FlatBuffers.md4
-rw-r--r--docs/source/RustUsage.md166
-rw-r--r--docs/source/Support.md34
-rw-r--r--docs/source/Tutorial.md201
-rw-r--r--docs/source/doxyfile2
6 files changed, 390 insertions, 19 deletions
diff --git a/docs/source/Compiler.md b/docs/source/Compiler.md
index 60494049..586087ad 100644
--- a/docs/source/Compiler.md
+++ b/docs/source/Compiler.md
@@ -43,6 +43,8 @@ For any schema input files, one or more generators can be specified:
- `--lobster`: Generate Lobster code.
+- `--rust`, `-r` : Generate Rust code.
+
For any data input files:
- `--binary`, `-b` : If data is contained in this file, generate a
diff --git a/docs/source/FlatBuffers.md b/docs/source/FlatBuffers.md
index 98042214..7cc93b92 100644
--- a/docs/source/FlatBuffers.md
+++ b/docs/source/FlatBuffers.md
@@ -4,7 +4,7 @@ FlatBuffers {#flatbuffers_index}
# Overview {#flatbuffers_overview}
[FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
-serialization library for C++, C#, C, Go, Java, JavaScript, Lobster, Lua, TypeScript, PHP, and Python.
+serialization library for C++, C#, C, Go, Java, JavaScript, Lobster, Lua, TypeScript, PHP, Python, and Rust.
It was originally created at Google for game development and other
performance-critical applications.
@@ -144,6 +144,8 @@ sections provide a more in-depth usage guide.
own programs.
- How to [use the generated Lobster code](@ref flatbuffers_guide_use_lobster) in your
own programs.
+- How to [use the generated Rust code](@ref flatbuffers_guide_use_rust) in your
+ own programs.
- [Support matrix](@ref flatbuffers_support) for platforms/languages/features.
- Some [benchmarks](@ref flatbuffers_benchmarks) showing the advantage of
using FlatBuffers.
diff --git a/docs/source/RustUsage.md b/docs/source/RustUsage.md
new file mode 100644
index 00000000..f4201086
--- /dev/null
+++ b/docs/source/RustUsage.md
@@ -0,0 +1,166 @@
+Use in Rust {#flatbuffers_guide_use_rust}
+==========
+
+## Before you get started
+
+Before diving into the FlatBuffers usage in Rust, it should be noted that
+the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
+to general FlatBuffers usage in all of the supported languages (including Rust).
+This page is designed to cover the nuances of FlatBuffers usage, specific to
+Rust.
+
+#### Prerequisites
+
+This page assumes you have written a FlatBuffers schema and compiled it
+with the Schema Compiler. If you have not, please see
+[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
+and [Writing a schema](@ref flatbuffers_guide_writing_schema).
+
+Assuming you wrote a schema, say `mygame.fbs` (though the extension doesn't
+matter), you've generated a Rust file called `mygame_generated.rs` using the
+compiler (e.g. `flatc --rust mygame.fbs`), you can now start using this in
+your program by including the file. As noted, this header relies on the crate
+`flatbuffers`, which should be in your include `Cargo.toml`.
+
+## FlatBuffers Rust library code location
+
+The code for the FlatBuffers Rust library can be found at
+`flatbuffers/rust`. You can browse the library code on the
+[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/rust).
+
+## Testing the FlatBuffers Rust library
+
+The code to test the Rust library can be found at `flatbuffers/tests/rust_usage_test`.
+The test code itself is located in
+[integration_test.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/tests/integration_test.rs)
+
+This test file requires `flatc` to be present. To review how to build the project,
+please read the [Building](@ref flatbuffers_guide_building) documenation.
+
+To run the tests, execute `RustTest.sh` from the `flatbuffers/tests` directory.
+For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply
+run: `cd tests && ./RustTest.sh`.
+
+*Note: The shell script requires [Rust](https://www.rust-lang.org) to
+be installed.*
+
+## Using the FlatBuffers Rust library
+
+*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
+example of how to use FlatBuffers in Rust.*
+
+FlatBuffers supports both reading and writing FlatBuffers in Rust.
+
+To use FlatBuffers in your code, first generate the Rust modules from your
+schema with the `--rust` option to `flatc`. Then you can import both FlatBuffers
+and the generated code to read or write FlatBuffers.
+
+For example, here is how you would read a FlatBuffer binary file in Rust:
+First, include the library and generated code. Then read the file into
+a `u8` vector, which you pass, as a byte slice, to `get_root_as_monster()`.
+
+This full example program is available in the Rust test suite:
+[monster_example.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/bin/monster_example.rs)
+
+It can be run by `cd`ing to the `rust_usage_test` directory and executing: `cargo run monster_example`.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
+ extern crate flatbuffers;
+
+ #[path = "../../monster_test_generated.rs"]
+ mod monster_test_generated;
+ pub use monster_test_generated::my_game;
+
+ use std::io::Read;
+
+ fn main() {
+ let mut f = std::fs::File::open("../monsterdata_test.mon").unwrap();
+ let mut buf = Vec::new();
+ f.read_to_end(&mut buf).expect("file reading failed");
+
+ let monster = my_game::example::get_root_as_monster(&buf[..]);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`monster` is of type `Monster`, and points to somewhere *inside* your
+buffer (root object pointers are not the same as `buffer_pointer` !).
+If you look in your generated header, you'll see it has
+convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
+ println!("{}", monster.hp()); // `80`
+ println!("{}", monster.mana()); // default value of `150`
+ println!("{:?}", monster.name()); // Some("MyMonster")
+ }
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+*Note: That we never stored a `mana` value, so it will return the default.*
+
+## Direct memory access
+
+As you can see from the above examples, all elements in a buffer are
+accessed through generated accessors. This is because everything is
+stored in little endian format on all platforms (the accessor
+performs a swap operation on big endian machines), and also because
+the layout of things is generally not known to the user.
+
+For structs, layout is deterministic and guaranteed to be the same
+across platforms (scalars are aligned to their
+own size, and structs themselves to their largest member), and you
+are allowed to access this memory directly by using `safe_slice` and
+on the reference to a struct, or even an array of structs.
+
+To compute offsets to sub-elements of a struct, make sure they
+are structs themselves, as then you can use the pointers to
+figure out the offset without having to hardcode it. This is
+handy for use of arrays of structs with calls like `glVertexAttribPointer`
+in OpenGL or similar APIs.
+
+It is important to note is that structs are still little endian on all
+machines, so only use tricks like this if you can guarantee you're not
+shipping on a big endian machine (using an `#[cfg(target_endian = "little")]`
+attribute would be wise).
+
+The special function `safe_slice` is implemented on Vector objects that are
+represented in memory the same way as they are represented on the wire. This
+function is always available on vectors of struct, bool, u8, and i8. It is
+conditionally-compiled on little-endian systems for all the remaining scalar
+types.
+
+The FlatBufferBuilder function `create_vector_direct` is implemented for all
+types that are endian-safe to write with a `memcpy`. It is the write-equivalent
+of `safe_slice`.
+
+## Access of untrusted buffers
+
+The generated accessor functions access fields over offsets, which is
+very quick. These offsets are used to index into Rust slices, so they are
+bounds-checked by the Rust runtime. However, our Rust implementation may
+change: we may convert access functions to use direct pointer dereferencing, to
+improve lookup speed. As a result, users should not rely on the aforementioned
+bounds-checking behavior.
+
+When you're processing large amounts of data from a source you know (e.g.
+your own generated data on disk), this is acceptable, but when reading
+data from the network that can potentially have been modified by an
+attacker, this is undesirable.
+
+The C++ port provides a buffer verifier. At this time, Rust does not. Rust may
+provide a verifier in a future version. In the meantime, Rust users can access
+the buffer verifier generated by the C++ port through a foreign function
+interface (FFI).
+
+## Threading
+
+Reading a FlatBuffer does not touch any memory outside the original buffer,
+and is entirely read-only (all immutable), so is safe to access from multiple
+threads even without synchronisation primitives.
+
+Creating a FlatBuffer is not thread safe. All state related to building
+a FlatBuffer is contained in a FlatBufferBuilder instance, and no memory
+outside of it is touched. To make this thread safe, either do not
+share instances of FlatBufferBuilder between threads (recommended), or
+manually wrap it in synchronisation primitives. There's no automatic way to
+accomplish this, by design, as we feel multithreaded construction
+of a single buffer will be rare, and synchronisation overhead would be costly.
+
+<br>
diff --git a/docs/source/Support.md b/docs/source/Support.md
index e4c66cd6..c8ac7f7e 100644
--- a/docs/source/Support.md
+++ b/docs/source/Support.md
@@ -18,23 +18,23 @@ In general:
NOTE: this table is a start, it needs to be extended.
-Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Dart | Lobster
------------------------------- | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ------- | -------
-Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes
-JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes
-Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No
-Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No
-Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No
-Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes
-Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No
-Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great
-Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes
-Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes
-Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes
-Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes
-Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes
-Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No
-Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | evanw/ev* | kr* | mik* | ch* | dnfield | aard*
+Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Dart | Lobster | Rust
+------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ------- | ------- | ----
+Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes | Yes
+JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes | No
+Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No
+Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No
+Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No
+Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes
+Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No | Yes
+Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great | Superb
+Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes | Yes
+Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes
+Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes
+Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ?
+Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ?
+Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No | ?
+Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | evanw/ev* | kr* | mik* | ch* | dnfield | aard* | rw
* aard = aardappel (previously: gwvo)
* ev = evolutional
diff --git a/docs/source/Tutorial.md b/docs/source/Tutorial.md
index 8cb1ab17..f2eaa2ea 100644
--- a/docs/source/Tutorial.md
+++ b/docs/source/Tutorial.md
@@ -33,6 +33,7 @@ Please select your desired language for our quest:
<input type="radio" name="language" value="dart">Dart</input>
<input type="radio" name="language" value="lua">Lua</input>
<input type="radio" name="language" value="lobster">Lobster</input>
+ <input type="radio" name="language" value="rust">Rust</input>
</form>
\endhtmlonly
@@ -144,6 +145,9 @@ For your chosen language, please cross-reference with:
<div class="language-lobster">
[sample_binary.lobster](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.lobster)
</div>
+<div class="language-rust">
+[sample_binary.rs](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.rs)
+</div>
## Writing the Monsters' FlatBuffer Schema
@@ -343,6 +347,12 @@ Please be aware of the difference between `flatc` and `flatcc` tools.
./../flatc --lobster monster.fbs
~~~
</div>
+<div class="language-rust">
+~~~{.sh}
+ cd flatbuffers/sample
+ ./../flatc --rust monster.fbs
+~~~
+</div>
For a more complete guide to using the `flatc` compiler, please read the
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
@@ -479,6 +489,21 @@ The first step is to import/include the library, generated files, etc.
include "monster_generated.lobster"
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // import the flatbuffers runtime library
+ extern crate flatbuffers;
+
+ // import the generated code
+ #[path = "./monster_generated.rs"]
+ mod monster_generated;
+ pub use monster_generated::my_game::sample::{get_root_as_monster,
+ Color, Equipment,
+ Monster, MonsterArgs,
+ Vec3,
+ Weapon, WeaponArgs};
+~~~
+</div>
Now we are ready to start building some buffers. In order to start, we need
to create an instance of the `FlatBufferBuilder`, which will contain the buffer
@@ -570,6 +595,13 @@ which will grow automatically if needed:
let builder = flatbuffers_builder {}
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // Build up a serialized buffer algorithmically.
+ // Initialize it with a capacity of 1024 bytes.
+ let mut builder = flatbuffers::FlatBufferBuilder::new_with_capacity(1024);
+~~~
+</div>
After creating the `builder`, we can start serializing our data. Before we make
our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
@@ -788,6 +820,24 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
builder.MyGame_Sample_WeaponEnd()
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // Serialize some weapons for the Monster: A 'sword' and an 'axe'.
+ let weapon_one_name = builder.create_string("Sword");
+ let weapon_two_name = builder.create_string("Axe");
+
+ // Use the `Weapon::create` shortcut to create Weapons with named field
+ // arguments.
+ let sword = Weapon::create(&mut builder, &WeaponArgs{
+ name: Some(weapon_one_name),
+ damage: 3,
+ });
+ let axe = Weapon::create(&mut builder, &WeaponArgs{
+ name: Some(weapon_two_name),
+ damage: 5,
+ });
+~~~
+</div>
Now let's create our monster, the `orc`. For this `orc`, lets make him
`red` with rage, positioned at `(1.0, 2.0, 3.0)`, and give him
@@ -959,6 +1009,15 @@ traversal. This is generally easy to do on any tree structures.
let inv = builder.MyGame_Sample_MonsterCreateInventoryVector(map(10): _)
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // Name of the Monster.
+ let name = builder.create_string("Orc");
+
+ // Inventory.
+ let inventory = builder.create_vector(&[0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+~~~
+</div>
We serialized two built-in data types (`string` and `vector`) and captured
their return values. These values are offsets into the serialized data,
@@ -1086,8 +1145,14 @@ offsets.
let weapons = builder.MyGame_Sample_MonsterCreateWeaponsVector(weapon_offsets)
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // Create a FlatBuffer `vector` that contains offsets to the sword and axe
+ // we created above.
+ let weapons = builder.create_vector(&[sword, axe]);
+~~~
+</div>
-<div class="language-cpp">
<br>
Note there's additional convenience overloads of `CreateVector`, allowing you
to work with data that's not in a `std::vector`, or allowing you to generate
@@ -1203,6 +1268,18 @@ for the `path` field above:
let path = builder.EndVector(2)
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // Create the path vector of Vec3 objects.
+ let x = Vec3::new(1.0, 2.0, 3.0);
+ let y = Vec3::new(4.0, 5.0, 6.0);
+ let path = builder.create_vector(&[x, y]);
+
+ // Note that, for convenience, it is also valid to create a vector of
+ // references to structs, like this:
+ // let path = builder.create_vector(&[&x, &y]);
+~~~
+</div>
We have now serialized the non-scalar components of the orc, so we
can serialize the monster itself:
@@ -1438,6 +1515,27 @@ can serialize the monster itself:
let orc = builder.MyGame_Sample_MonsterEnd()
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // Create the monster using the `Monster::create` helper function. This
+ // function accepts a `MonsterArgs` struct, which supplies all of the data
+ // needed to build a `Monster`. To supply empty/default fields, just use the
+ // Rust built-in `Default::default()` function, as demononstrated below.
+ let orc = Monster::create(&mut builder, &MonsterArgs{
+ pos: Some(&Vec3::new(1.0f32, 2.0f32, 3.0f32)),
+ mana: 150,
+ hp: 80,
+ name: Some(name),
+ inventory: Some(inventory),
+ color: Color::Red,
+ weapons: Some(weapons),
+ equipped_type: Equipment::Weapon,
+ equipped: Some(axe.as_union_value()),
+ path: Some(path),
+ ..Default::default()
+ });
+~~~
+</div>
Note how we create `Vec3` struct in-line in the table. Unlike tables, structs
are simple combinations of scalars that are always stored inline, just like
@@ -1592,6 +1690,14 @@ Here is a repetition these lines, to help highlight them more clearly:
builder.MyGame_Sample_MonsterAddEquipped(axe)
~~~
</div>
+<div class="language-rust">
+ ~~~{.rs}
+ // You need to call `as_union_value` to turn an object into a type that
+ // can be used as a union value.
+ monster_builder.add_equipped_type(Equipment::Weapon); // Union type
+ monster_builder.add_equipped(axe.as_union_value()); // Union data
+ ~~~
+</div>
After you have created your buffer, you will have the offset to the root of the
data in the `orc` variable, so you can finish the buffer by calling the
@@ -1675,6 +1781,12 @@ appropriate `finish` method.
builder.Finish(orc)
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // Call `finish()` to instruct the builder that this monster is complete.
+ builder.finish(orc, None);
+~~~
+</div>
The buffer is now ready to be stored somewhere, sent over the network, be
compressed, or whatever you'd like to do with it. You can access the buffer
@@ -1784,6 +1896,13 @@ like so:
let buf = builder.SizedCopy() // Of type `string`.
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // This must be called after `finish()`.
+ // `finished_data` returns a byte slice.
+ let buf = builder.finished_data(); // Of type `&[u8]`
+~~~
+</div>
Now you can write the bytes to a file, send them over the network..
@@ -1917,6 +2036,21 @@ import './monster_my_game.sample_generated.dart' as myGame;
include "monster_generated.lobster"
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // import the flatbuffers runtime library
+ extern crate flatbuffers;
+
+ // import the generated code
+ #[path = "./monster_generated.rs"]
+ mod monster_generated;
+ pub use monster_generated::my_game::sample::{get_root_as_monster,
+ Color, Equipment,
+ Monster, MonsterArgs,
+ Vec3,
+ Weapon, WeaponArgs};
+~~~
+</div>
Then, assuming you have a buffer of bytes received from disk,
network, etc., you can create start accessing the buffer like so:
@@ -2044,6 +2178,14 @@ myGame.Monster monster = new myGame.Monster(data);
let monster = MyGame_Sample_GetRootAsMonster(buf)
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ let buf = /* the data you just read, in a &[u8] */
+
+ // Get an accessor to the root object inside the buffer.
+ let monster = get_root_as_monster(buf);
+~~~
+</div>
If you look in the generated files from the schema compiler, you will see it generated
accessors for all non-`deprecated` fields. For example:
@@ -2136,6 +2278,14 @@ accessors for all non-`deprecated` fields. For example:
let name = monster.name
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // Get and test some scalar types from the FlatBuffer.
+ let hp = monster.hp();
+ let mana = monster.mana();
+ let name = monster.name();
+~~~
+</div>
These should hold `300`, `150`, and `"Orc"` respectively.
@@ -2245,6 +2395,14 @@ To access sub-objects, in the case of our `pos`, which is a `Vec3`:
let z = pos.z
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ let pos = monster.pos().unwrap();
+ let x = pos.x();
+ let y = pos.y();
+ let z = pos.z();
+~~~
+</div>
`x`, `y`, and `z` will contain `1.0`, `2.0`, and `3.0`, respectively.
@@ -2329,6 +2487,16 @@ FlatBuffers `vector`.
let third_item = monster.inventory(2)
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // Get a test an element from the `inventory` FlatBuffer's `vector`.
+ let inv = monster.inventory().unwrap();
+
+ // Note that this vector is returned as a slice, because direct access for
+ // this type, a `u8` vector, is safe on all platforms:
+ let third_item = inv[2];
+~~~
+</div>
For `vector`s of `table`s, you can access the elements like any other vector,
except your need to handle the result as a FlatBuffer `table`:
@@ -2424,6 +2592,17 @@ except your need to handle the result as a FlatBuffer `table`:
let second_weapon_damage = monster.weapons(1).damage
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // Get and test the `weapons` FlatBuffers's `vector`.
+ let weps = monster.weapons().unwrap();
+ let weps_len = weps.len();
+
+ let wep2 = weps.get(1);
+ let second_weapon_name = wep2.name();
+ let second_weapon_damage = wep2.damage();
+~~~
+</div>
Last, we can access our `Equipped` FlatBuffer `union`. Just like when we created
the `union`, we need to get both parts of the `union`: the type and the data.
@@ -2585,6 +2764,18 @@ We can access the type to dynamically cast the data as needed (since the
let weapon_damage = union_weapon.damage // 5
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ // Get and test the `Equipment` union (`equipped` field).
+ // `equipped_as_weapon` returns a FlatBuffer handle much like normal table
+ // fields, but this will return `None` is the union is not actually of that
+ // type.
+ if monster.equipped_type() == Equipment::Weapon {
+ let equipped = monster.equipped_as_weapon().unwrap();
+ let weapon_name = equipped.name();
+ let weapon_damage = equipped.damage();
+~~~
+</div>
## Mutating FlatBuffers
@@ -2675,6 +2866,11 @@ mutators like so:
<API for mutating FlatBuffers is not yet available in Lobster.>
~~~
</div>
+<div class="language-rust">
+~~~{.rs}
+ <API for mutating FlatBuffers is not yet available in Rust.>
+~~~
+</div>
We use the somewhat verbose term `mutate` instead of `set` to indicate that this
is a special use case, not to be confused with the default way of constructing
@@ -2798,5 +2994,8 @@ For your chosen language, see:
<div class="language-lobster">
[Use in Lobster](@ref flatbuffers_guide_use_lobster)
</div>
+<div class="language-rust">
+[Use in Rust](@ref flatbuffers_guide_use_rust)
+</div>
<br>
diff --git a/docs/source/doxyfile b/docs/source/doxyfile
index 19a2ec94..6ba3c108 100644
--- a/docs/source/doxyfile
+++ b/docs/source/doxyfile
@@ -760,6 +760,7 @@ INPUT = "FlatBuffers.md" \
"PythonUsage.md" \
"LuaUsage.md" \
"LobsterUsage.md" \
+ "RustUsage.md" \
"Support.md" \
"Benchmarks.md" \
"WhitePaper.md" \
@@ -778,6 +779,7 @@ INPUT = "FlatBuffers.md" \
"../../net/FlatBuffers/FlatBufferBuilder.cs" \
"../../include/flatbuffers/flatbuffers.h" \
"../../go/builder.go"
+ "../../rust/flatbuffers/src/builder.rs"
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses