Skip to main content

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}