xref: /aosp_15_r20/external/flatbuffers/docs/source/RustUsage.md (revision 890232f25432b36107d06881e0a25aaa6b473652)
1*890232f2SAndroid Build Coastguard WorkerUse in Rust    {#flatbuffers_guide_use_rust}
2*890232f2SAndroid Build Coastguard Worker==========
3*890232f2SAndroid Build Coastguard Worker
4*890232f2SAndroid Build Coastguard Worker## Before you get started
5*890232f2SAndroid Build Coastguard Worker
6*890232f2SAndroid Build Coastguard WorkerBefore diving into the FlatBuffers usage in Rust, it should be noted that
7*890232f2SAndroid Build Coastguard Workerthe [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
8*890232f2SAndroid Build Coastguard Workerto general FlatBuffers usage in all of the supported languages (including Rust).
9*890232f2SAndroid Build Coastguard WorkerThis page is designed to cover the nuances of FlatBuffers usage, specific to
10*890232f2SAndroid Build Coastguard WorkerRust.
11*890232f2SAndroid Build Coastguard Worker
12*890232f2SAndroid Build Coastguard Worker#### Prerequisites
13*890232f2SAndroid Build Coastguard Worker
14*890232f2SAndroid Build Coastguard WorkerThis page assumes you have written a FlatBuffers schema and compiled it
15*890232f2SAndroid Build Coastguard Workerwith the Schema Compiler. If you have not, please see
16*890232f2SAndroid Build Coastguard Worker[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
17*890232f2SAndroid Build Coastguard Workerand [Writing a schema](@ref flatbuffers_guide_writing_schema).
18*890232f2SAndroid Build Coastguard Worker
19*890232f2SAndroid Build Coastguard WorkerAssuming you wrote a schema, say `mygame.fbs` (though the extension doesn't
20*890232f2SAndroid Build Coastguard Workermatter), you've generated a Rust file called `mygame_generated.rs` using the
21*890232f2SAndroid Build Coastguard Workercompiler (e.g. `flatc --rust mygame.fbs` or via helpers listed in "Useful
22*890232f2SAndroid Build Coastguard Workertools created by others" section bellow), you can now start using this in
23*890232f2SAndroid Build Coastguard Workeryour program by including the file. As noted, this header relies on the crate
24*890232f2SAndroid Build Coastguard Worker`flatbuffers`, which should be in your include `Cargo.toml`.
25*890232f2SAndroid Build Coastguard Worker
26*890232f2SAndroid Build Coastguard Worker## FlatBuffers Rust library code location
27*890232f2SAndroid Build Coastguard Worker
28*890232f2SAndroid Build Coastguard WorkerThe code for the FlatBuffers Rust library can be found at
29*890232f2SAndroid Build Coastguard Worker`flatbuffers/rust`. You can browse the library code on the
30*890232f2SAndroid Build Coastguard Worker[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/rust).
31*890232f2SAndroid Build Coastguard Worker
32*890232f2SAndroid Build Coastguard Worker## Testing the FlatBuffers Rust library
33*890232f2SAndroid Build Coastguard Worker
34*890232f2SAndroid Build Coastguard WorkerThe code to test the Rust library can be found at `flatbuffers/tests/rust_usage_test`.
35*890232f2SAndroid Build Coastguard WorkerThe test code itself is located in
36*890232f2SAndroid Build Coastguard Worker[integration_test.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/tests/integration_test.rs)
37*890232f2SAndroid Build Coastguard Worker
38*890232f2SAndroid Build Coastguard WorkerThis test file requires `flatc` to be present. To review how to build the project,
39*890232f2SAndroid Build Coastguard Workerplease read the [Building](@ref flatbuffers_guide_building) documentation.
40*890232f2SAndroid Build Coastguard Worker
41*890232f2SAndroid Build Coastguard WorkerTo run the tests, execute `RustTest.sh` from the `flatbuffers/tests` directory.
42*890232f2SAndroid Build Coastguard WorkerFor example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply
43*890232f2SAndroid Build Coastguard Workerrun: `cd tests && ./RustTest.sh`.
44*890232f2SAndroid Build Coastguard Worker
45*890232f2SAndroid Build Coastguard Worker*Note: The shell script requires [Rust](https://www.rust-lang.org) to
46*890232f2SAndroid Build Coastguard Workerbe installed.*
47*890232f2SAndroid Build Coastguard Worker
48*890232f2SAndroid Build Coastguard Worker## Using the FlatBuffers Rust library
49*890232f2SAndroid Build Coastguard Worker
50*890232f2SAndroid Build Coastguard Worker*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
51*890232f2SAndroid Build Coastguard Workerexample of how to use FlatBuffers in Rust.*
52*890232f2SAndroid Build Coastguard Worker
53*890232f2SAndroid Build Coastguard WorkerFlatBuffers supports both reading and writing FlatBuffers in Rust.
54*890232f2SAndroid Build Coastguard Worker
55*890232f2SAndroid Build Coastguard WorkerTo use FlatBuffers in your code, first generate the Rust modules from your
56*890232f2SAndroid Build Coastguard Workerschema with the `--rust` option to `flatc`. Then you can import both FlatBuffers
57*890232f2SAndroid Build Coastguard Workerand the generated code to read or write FlatBuffers.
58*890232f2SAndroid Build Coastguard Worker
59*890232f2SAndroid Build Coastguard WorkerFor example, here is how you would read a FlatBuffer binary file in Rust:
60*890232f2SAndroid Build Coastguard WorkerFirst, include the library and generated code. Then read the file into
61*890232f2SAndroid Build Coastguard Workera `u8` vector, which you pass, as a byte slice, to `root_as_monster()`.
62*890232f2SAndroid Build Coastguard Worker
63*890232f2SAndroid Build Coastguard WorkerThis full example program is available in the Rust test suite:
64*890232f2SAndroid Build Coastguard Worker[monster_example.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/bin/monster_example.rs)
65*890232f2SAndroid Build Coastguard Worker
66*890232f2SAndroid Build Coastguard WorkerIt can be run by `cd`ing to the `rust_usage_test` directory and executing: `cargo run monster_example`.
67*890232f2SAndroid Build Coastguard Worker
68*890232f2SAndroid Build Coastguard Worker~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
69*890232f2SAndroid Build Coastguard Worker    extern crate flatbuffers;
70*890232f2SAndroid Build Coastguard Worker
71*890232f2SAndroid Build Coastguard Worker    #[allow(dead_code, unused_imports)]
72*890232f2SAndroid Build Coastguard Worker    #[path = "../../monster_test_generated.rs"]
73*890232f2SAndroid Build Coastguard Worker    mod monster_test_generated;
74*890232f2SAndroid Build Coastguard Worker    pub use monster_test_generated::my_game;
75*890232f2SAndroid Build Coastguard Worker
76*890232f2SAndroid Build Coastguard Worker    use std::io::Read;
77*890232f2SAndroid Build Coastguard Worker
78*890232f2SAndroid Build Coastguard Worker    fn main() {
79*890232f2SAndroid Build Coastguard Worker        let mut f = std::fs::File::open("../monsterdata_test.mon").unwrap();
80*890232f2SAndroid Build Coastguard Worker        let mut buf = Vec::new();
81*890232f2SAndroid Build Coastguard Worker        f.read_to_end(&mut buf).expect("file reading failed");
82*890232f2SAndroid Build Coastguard Worker
83*890232f2SAndroid Build Coastguard Worker        let monster = my_game::example::root_as_monster(&buf[..]);
84*890232f2SAndroid Build Coastguard Worker~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
85*890232f2SAndroid Build Coastguard Worker
86*890232f2SAndroid Build Coastguard Worker`monster` is of type `Monster`, and points to somewhere *inside* your
87*890232f2SAndroid Build Coastguard Workerbuffer (root object pointers are not the same as `buffer_pointer` !).
88*890232f2SAndroid Build Coastguard WorkerIf you look in your generated header, you'll see it has
89*890232f2SAndroid Build Coastguard Workerconvenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
90*890232f2SAndroid Build Coastguard Worker
91*890232f2SAndroid Build Coastguard Worker~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
92*890232f2SAndroid Build Coastguard Worker        println!("{}", monster.hp());     // `80`
93*890232f2SAndroid Build Coastguard Worker        println!("{}", monster.mana());   // default value of `150`
94*890232f2SAndroid Build Coastguard Worker        println!("{:?}", monster.name()); // Some("MyMonster")
95*890232f2SAndroid Build Coastguard Worker    }
96*890232f2SAndroid Build Coastguard Worker~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
97*890232f2SAndroid Build Coastguard Worker
98*890232f2SAndroid Build Coastguard Worker*Note: That we never stored a `mana` value, so it will return the default.*
99*890232f2SAndroid Build Coastguard Worker
100*890232f2SAndroid Build Coastguard Worker## Direct memory access
101*890232f2SAndroid Build Coastguard Worker
102*890232f2SAndroid Build Coastguard WorkerAs you can see from the above examples, all elements in a buffer are
103*890232f2SAndroid Build Coastguard Workeraccessed through generated accessors. This is because everything is
104*890232f2SAndroid Build Coastguard Workerstored in little endian format on all platforms (the accessor
105*890232f2SAndroid Build Coastguard Workerperforms a swap operation on big endian machines), and also because
106*890232f2SAndroid Build Coastguard Workerthe layout of things is generally not known to the user.
107*890232f2SAndroid Build Coastguard Worker
108*890232f2SAndroid Build Coastguard WorkerFor structs, layout is deterministic and guaranteed to be the same
109*890232f2SAndroid Build Coastguard Workeracross platforms (scalars are aligned to their
110*890232f2SAndroid Build Coastguard Workerown size, and structs themselves to their largest member), and you
111*890232f2SAndroid Build Coastguard Workerare allowed to access this memory directly by using `safe_slice`
112*890232f2SAndroid Build Coastguard Workeron the reference to a struct, or even an array of structs.
113*890232f2SAndroid Build Coastguard Worker
114*890232f2SAndroid Build Coastguard WorkerTo compute offsets to sub-elements of a struct, make sure they
115*890232f2SAndroid Build Coastguard Workerare structs themselves, as then you can use the pointers to
116*890232f2SAndroid Build Coastguard Workerfigure out the offset without having to hardcode it. This is
117*890232f2SAndroid Build Coastguard Workerhandy for use of arrays of structs with calls like `glVertexAttribPointer`
118*890232f2SAndroid Build Coastguard Workerin OpenGL or similar APIs.
119*890232f2SAndroid Build Coastguard Worker
120*890232f2SAndroid Build Coastguard WorkerIt is important to note is that structs are still little endian on all
121*890232f2SAndroid Build Coastguard Workermachines, so the functions to enable tricks like this are only exposed on little
122*890232f2SAndroid Build Coastguard Workerendian machines. If you also ship on big endian machines, using an
123*890232f2SAndroid Build Coastguard Worker`#[cfg(target_endian = "little")]` attribute would be wise or your code will not
124*890232f2SAndroid Build Coastguard Workercompile.
125*890232f2SAndroid Build Coastguard Worker
126*890232f2SAndroid Build Coastguard WorkerThe special function `safe_slice` is implemented on Vector objects that are
127*890232f2SAndroid Build Coastguard Workerrepresented in memory the same way as they are represented on the wire. This
128*890232f2SAndroid Build Coastguard Workerfunction is always available on vectors of struct, bool, u8, and i8. It is
129*890232f2SAndroid Build Coastguard Workerconditionally-compiled on little-endian systems for all the remaining scalar
130*890232f2SAndroid Build Coastguard Workertypes.
131*890232f2SAndroid Build Coastguard Worker
132*890232f2SAndroid Build Coastguard WorkerThe FlatBufferBuilder function `create_vector_direct` is implemented for all
133*890232f2SAndroid Build Coastguard Workertypes that are endian-safe to write with a `memcpy`. It is the write-equivalent
134*890232f2SAndroid Build Coastguard Workerof `safe_slice`.
135*890232f2SAndroid Build Coastguard Worker
136*890232f2SAndroid Build Coastguard Worker## Access of untrusted buffers
137*890232f2SAndroid Build Coastguard Worker
138*890232f2SAndroid Build Coastguard WorkerThe safe Rust functions to interpret a slice as a table (`root`,
139*890232f2SAndroid Build Coastguard Worker`size_prefixed_root`, `root_with_opts`, and `size_prefixed_root_with_opts`)
140*890232f2SAndroid Build Coastguard Workerverify the data first. This has some performance cost, but is intended to be
141*890232f2SAndroid Build Coastguard Workersafe for use on flatbuffers from untrusted sources. There are corresponding
142*890232f2SAndroid Build Coastguard Worker`unsafe` versions with names ending in `_unchecked` which skip this
143*890232f2SAndroid Build Coastguard Workerverification, and may access arbitrary memory.
144*890232f2SAndroid Build Coastguard Worker
145*890232f2SAndroid Build Coastguard WorkerThe generated accessor functions access fields over offsets, which is
146*890232f2SAndroid Build Coastguard Workervery quick. The current implementation uses these to access memory without any
147*890232f2SAndroid Build Coastguard Workerfurther bounds checking. All of the safe Rust APIs ensure the verifier is run
148*890232f2SAndroid Build Coastguard Workerover these flatbuffers before accessing them.
149*890232f2SAndroid Build Coastguard Worker
150*890232f2SAndroid Build Coastguard WorkerWhen you're processing large amounts of data from a source you know (e.g.
151*890232f2SAndroid Build Coastguard Workeryour own generated data on disk), the `_unchecked` versions are acceptable, but
152*890232f2SAndroid Build Coastguard Workerwhen reading data from the network that can potentially have been modified by an
153*890232f2SAndroid Build Coastguard Workerattacker, it is desirable to use the safe versions which use the verifier.
154*890232f2SAndroid Build Coastguard Worker
155*890232f2SAndroid Build Coastguard Worker## Threading
156*890232f2SAndroid Build Coastguard Worker
157*890232f2SAndroid Build Coastguard WorkerReading a FlatBuffer does not touch any memory outside the original buffer,
158*890232f2SAndroid Build Coastguard Workerand is entirely read-only (all immutable), so is safe to access from multiple
159*890232f2SAndroid Build Coastguard Workerthreads even without synchronisation primitives.
160*890232f2SAndroid Build Coastguard Worker
161*890232f2SAndroid Build Coastguard WorkerCreating a FlatBuffer is not thread safe. All state related to building
162*890232f2SAndroid Build Coastguard Workera FlatBuffer is contained in a FlatBufferBuilder instance, and no memory
163*890232f2SAndroid Build Coastguard Workeroutside of it is touched. To make this thread safe, either do not
164*890232f2SAndroid Build Coastguard Workershare instances of FlatBufferBuilder between threads (recommended), or
165*890232f2SAndroid Build Coastguard Workermanually wrap it in synchronisation primitives. There's no automatic way to
166*890232f2SAndroid Build Coastguard Workeraccomplish this, by design, as we feel multithreaded construction
167*890232f2SAndroid Build Coastguard Workerof a single buffer will be rare, and synchronisation overhead would be costly.
168*890232f2SAndroid Build Coastguard Worker
169*890232f2SAndroid Build Coastguard WorkerUnlike most other languages, in Rust these properties are exposed to and
170*890232f2SAndroid Build Coastguard Workerenforced by the type system. `flatbuffers::Table` and the generated table types
171*890232f2SAndroid Build Coastguard Workerare `Send + Sync`, indicating they may be freely shared across threads and data
172*890232f2SAndroid Build Coastguard Workermay be accessed from any thread which receives a const (aka shared) reference.
173*890232f2SAndroid Build Coastguard WorkerThere are no functions which require a mutable (aka exclusive) reference, which
174*890232f2SAndroid Build Coastguard Workermeans all the available functions may be called like this.
175*890232f2SAndroid Build Coastguard Worker`flatbuffers::FlatBufferBuilder` is also `Send + Sync`, but all of the mutating
176*890232f2SAndroid Build Coastguard Workerfunctions require a mutable (aka exclusive) reference which can only be created
177*890232f2SAndroid Build Coastguard Workerwhen no other references to the `FlatBufferBuilder` exist, and may not be copied
178*890232f2SAndroid Build Coastguard Workerwithin the same thread, let alone to a second thread.
179*890232f2SAndroid Build Coastguard Worker
180*890232f2SAndroid Build Coastguard Worker## Useful tools created by others
181*890232f2SAndroid Build Coastguard Worker
182*890232f2SAndroid Build Coastguard Worker* [flatc-rust](https://github.com/frol/flatc-rust) - FlatBuffers compiler
183*890232f2SAndroid Build Coastguard Worker(flatc) as API for transparent `.fbs` to `.rs` code-generation via Cargo
184*890232f2SAndroid Build Coastguard Workerbuild scripts integration.
185*890232f2SAndroid Build Coastguard Worker
186*890232f2SAndroid Build Coastguard Worker<br>
187