edlcodegen_core/flatbuffer_support.rs
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4/// Default capacity (in bytes) for new FlatBuffer builders.
5const INITIAL_DEFAULT_SIZE_IN_BYTES: usize = 4096;
6
7/// Trait defining the common interface for FlatBuffer-compatible types.
8///
9/// This trait allows any type implementing it to:
10/// - **Pack** itself into a FlatBuffer builder, producing an flatbuffer offset object.
11/// - **Unpack** itself from a serialized byte buffer back into a flatbuffer struct/enum.
12pub trait FlatbufferPack<'a> {
13 /// The generated FlatBuffer table type corresponding to this flatbuffer struct/enum.
14 type TableType: flatbuffers::Follow<'a> + 'a;
15
16 /// Packs the native struct into a FlatBuffer builder.
17 ///
18 /// Returns a `WIPOffset` object pointing to the serialized object within the builder.
19 fn pack(
20 &self,
21 builder: &mut flatbuffers::FlatBufferBuilder<'a>,
22 ) -> flatbuffers::WIPOffset<Self::TableType>;
23
24 /// Unpacks the FlatBuffer binary data into a native struct instance.
25 ///
26 /// # Errors
27 /// Returns [`flatbuffers::InvalidFlatbuffer`] if the input buffer is
28 /// malformed or missing required fields.
29 fn unpack(data: &'a [u8]) -> Result<Self, flatbuffers::InvalidFlatbuffer>
30 where
31 Self: Sized;
32}
33
34/// Convenience helper that packs a FlatBuffer-compatible struct.
35///
36/// This function builds a FlatBuffer using a default initial buffer size,
37/// finishes the buffer, and returns the builder.
38pub fn pack_flatbuffer<'a, T: FlatbufferPack<'a>>(
39 native: &T,
40) -> flatbuffers::FlatBufferBuilder<'a> {
41 let mut builder = flatbuffers::FlatBufferBuilder::with_capacity(INITIAL_DEFAULT_SIZE_IN_BYTES);
42 let offset = native.pack(&mut builder);
43 builder.finish(offset, None);
44 builder
45}
46
47/// Implements the [`FlatbufferPack`] trait for a native FlatBuffer struct and
48/// table pair.
49///
50/// # Overview
51/// This macro bridges the generated native Rust type (e.g., `MyTableT`) and
52/// its corresponding FlatBuffer table type (e.g., `MyTable<'a>`).
53///
54/// It enables both packing and unpacking to be used generically across the
55/// framework without writing boilerplate implementations.
56///
57/// # Parameters
58/// - `$native_fb_stuct`: The generated native struct type (usually `<Name>T`)
59/// that represents the FlatBuffer object in Rust.
60/// - `$flatbuffer_table_obj`: The corresponding FlatBuffer table type (usually
61/// `<Name<'a>>`) generated by the FlatBuffers compiler.
62#[allow(unused_macros)]
63#[macro_export]
64macro_rules! impl_flatbuffer_pack {
65 ($native_fb_stuct:ty, $flatbuffer_table_obj:ty) => {
66 impl<'a> FlatbufferPack<'a> for $native_fb_stuct {
67 type TableType = $flatbuffer_table_obj;
68 fn pack(
69 &self,
70 builder: &mut flatbuffers::FlatBufferBuilder<'a>,
71 ) -> flatbuffers::WIPOffset<$flatbuffer_table_obj> {
72 self.pack(builder)
73 }
74
75 fn unpack(data: &'a [u8]) -> Result<Self, flatbuffers::InvalidFlatbuffer> {
76 flatbuffers::root::<$flatbuffer_table_obj>(data).map(|root| root.unpack())
77 }
78 }
79 };
80}