1Use in Rust {#flatbuffers_guide_use_rust} 2========== 3 4## Before you get started 5 6Before diving into the FlatBuffers usage in Rust, it should be noted that 7the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide 8to general FlatBuffers usage in all of the supported languages (including Rust). 9This page is designed to cover the nuances of FlatBuffers usage, specific to 10Rust. 11 12#### Prerequisites 13 14This page assumes you have written a FlatBuffers schema and compiled it 15with the Schema Compiler. If you have not, please see 16[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) 17and [Writing a schema](@ref flatbuffers_guide_writing_schema). 18 19Assuming you wrote a schema, say `mygame.fbs` (though the extension doesn't 20matter), you've generated a Rust file called `mygame_generated.rs` using the 21compiler (e.g. `flatc --rust mygame.fbs` or via helpers listed in "Useful 22tools created by others" section bellow), you can now start using this in 23your program by including the file. As noted, this header relies on the crate 24`flatbuffers`, which should be in your include `Cargo.toml`. 25 26## FlatBuffers Rust library code location 27 28The code for the FlatBuffers Rust library can be found at 29`flatbuffers/rust`. You can browse the library code on the 30[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/rust). 31 32## Testing the FlatBuffers Rust library 33 34The code to test the Rust library can be found at `flatbuffers/tests/rust_usage_test`. 35The test code itself is located in 36[integration_test.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/tests/integration_test.rs) 37 38This test file requires `flatc` to be present. To review how to build the project, 39please read the [Building](@ref flatbuffers_guide_building) documenation. 40 41To run the tests, execute `RustTest.sh` from the `flatbuffers/tests` directory. 42For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply 43run: `cd tests && ./RustTest.sh`. 44 45*Note: The shell script requires [Rust](https://www.rust-lang.org) to 46be installed.* 47 48## Using the FlatBuffers Rust library 49 50*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth 51example of how to use FlatBuffers in Rust.* 52 53FlatBuffers supports both reading and writing FlatBuffers in Rust. 54 55To use FlatBuffers in your code, first generate the Rust modules from your 56schema with the `--rust` option to `flatc`. Then you can import both FlatBuffers 57and the generated code to read or write FlatBuffers. 58 59For example, here is how you would read a FlatBuffer binary file in Rust: 60First, include the library and generated code. Then read the file into 61a `u8` vector, which you pass, as a byte slice, to `get_root_as_monster()`. 62 63This full example program is available in the Rust test suite: 64[monster_example.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/bin/monster_example.rs) 65 66It can be run by `cd`ing to the `rust_usage_test` directory and executing: `cargo run monster_example`. 67 68~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs} 69 extern crate flatbuffers; 70 71 #[allow(dead_code, unused_imports)] 72 #[path = "../../monster_test_generated.rs"] 73 mod monster_test_generated; 74 pub use monster_test_generated::my_game; 75 76 use std::io::Read; 77 78 fn main() { 79 let mut f = std::fs::File::open("../monsterdata_test.mon").unwrap(); 80 let mut buf = Vec::new(); 81 f.read_to_end(&mut buf).expect("file reading failed"); 82 83 let monster = my_game::example::get_root_as_monster(&buf[..]); 84~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 85 86`monster` is of type `Monster`, and points to somewhere *inside* your 87buffer (root object pointers are not the same as `buffer_pointer` !). 88If you look in your generated header, you'll see it has 89convenient accessors for all fields, e.g. `hp()`, `mana()`, etc: 90 91~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs} 92 println!("{}", monster.hp()); // `80` 93 println!("{}", monster.mana()); // default value of `150` 94 println!("{:?}", monster.name()); // Some("MyMonster") 95 } 96~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 97 98*Note: That we never stored a `mana` value, so it will return the default.* 99 100## Direct memory access 101 102As you can see from the above examples, all elements in a buffer are 103accessed through generated accessors. This is because everything is 104stored in little endian format on all platforms (the accessor 105performs a swap operation on big endian machines), and also because 106the layout of things is generally not known to the user. 107 108For structs, layout is deterministic and guaranteed to be the same 109across platforms (scalars are aligned to their 110own size, and structs themselves to their largest member), and you 111are allowed to access this memory directly by using `safe_slice` and 112on the reference to a struct, or even an array of structs. 113 114To compute offsets to sub-elements of a struct, make sure they 115are structs themselves, as then you can use the pointers to 116figure out the offset without having to hardcode it. This is 117handy for use of arrays of structs with calls like `glVertexAttribPointer` 118in OpenGL or similar APIs. 119 120It is important to note is that structs are still little endian on all 121machines, so only use tricks like this if you can guarantee you're not 122shipping on a big endian machine (using an `#[cfg(target_endian = "little")]` 123attribute would be wise). 124 125The special function `safe_slice` is implemented on Vector objects that are 126represented in memory the same way as they are represented on the wire. This 127function is always available on vectors of struct, bool, u8, and i8. It is 128conditionally-compiled on little-endian systems for all the remaining scalar 129types. 130 131The FlatBufferBuilder function `create_vector_direct` is implemented for all 132types that are endian-safe to write with a `memcpy`. It is the write-equivalent 133of `safe_slice`. 134 135## Access of untrusted buffers 136 137The generated accessor functions access fields over offsets, which is 138very quick. These offsets are used to index into Rust slices, so they are 139bounds-checked by the Rust runtime. However, our Rust implementation may 140change: we may convert access functions to use direct pointer dereferencing, to 141improve lookup speed. As a result, users should not rely on the aforementioned 142bounds-checking behavior. 143 144When you're processing large amounts of data from a source you know (e.g. 145your own generated data on disk), this is acceptable, but when reading 146data from the network that can potentially have been modified by an 147attacker, this is undesirable. 148 149The C++ port provides a buffer verifier. At this time, Rust does not. Rust may 150provide a verifier in a future version. In the meantime, Rust users can access 151the buffer verifier generated by the C++ port through a foreign function 152interface (FFI). 153 154## Threading 155 156Reading a FlatBuffer does not touch any memory outside the original buffer, 157and is entirely read-only (all immutable), so is safe to access from multiple 158threads even without synchronisation primitives. 159 160Creating a FlatBuffer is not thread safe. All state related to building 161a FlatBuffer is contained in a FlatBufferBuilder instance, and no memory 162outside of it is touched. To make this thread safe, either do not 163share instances of FlatBufferBuilder between threads (recommended), or 164manually wrap it in synchronisation primitives. There's no automatic way to 165accomplish this, by design, as we feel multithreaded construction 166of a single buffer will be rare, and synchronisation overhead would be costly. 167 168## Useful tools created by others 169 170* [flatc-rust](https://github.com/frol/flatc-rust) - FlatBuffers compiler 171(flatc) as API for transparent `.fbs` to `.rs` code-generation via Cargo 172build scripts integration. 173 174<br> 175