diff --git a/rust/flatbuffers/src/builder.rs b/rust/flatbuffers/src/builder.rs index 0b20f9eee..702b07cb5 100644 --- a/rust/flatbuffers/src/builder.rs +++ b/rust/flatbuffers/src/builder.rs @@ -52,6 +52,7 @@ pub struct FlatBufferBuilder<'fbb> { finished: bool, min_align: usize, + force_defaults: bool, _phantom: PhantomData<&'fbb ()>, } @@ -85,6 +86,7 @@ impl<'fbb> FlatBufferBuilder<'fbb> { finished: false, min_align: 0, + force_defaults: false, _phantom: PhantomData, } @@ -148,10 +150,9 @@ impl<'fbb> FlatBufferBuilder<'fbb> { #[inline] pub fn push_slot(&mut self, slotoff: VOffsetT, x: X, default: X) { self.assert_nested("push_slot"); - if x == default { - return; + if x != default || self.force_defaults { + self.push_slot_always(slotoff, x); } - self.push_slot_always(slotoff, x); } /// Push a Push'able value onto the front of the in-progress data, and @@ -327,6 +328,18 @@ impl<'fbb> FlatBufferBuilder<'fbb> { WIPOffset::new(self.push::(items.len() as UOffsetT).value()) } + /// Set whether default values are stored. + /// + /// In order to save space, fields that are set to their default value + /// aren't stored in the buffer. Setting `force_defaults` to `true` + /// disables this optimization. + /// + /// By default, `force_defaults` is `false`. + #[inline] + pub fn force_defaults(&mut self, force_defaults: bool) { + self.force_defaults = force_defaults; + } + /// Get the byte slice for the data that has been written, regardless of /// whether it has been finished. #[inline] diff --git a/tests/rust_usage_test/tests/integration_test.rs b/tests/rust_usage_test/tests/integration_test.rs index 5e5afcbd6..1aea51c68 100644 --- a/tests/rust_usage_test/tests/integration_test.rs +++ b/tests/rust_usage_test/tests/integration_test.rs @@ -2460,6 +2460,25 @@ mod byte_layouts { ]); } + #[test] + fn layout_09b_vtable_with_one_default_bool_force_defaults() { + let mut b = flatbuffers::FlatBufferBuilder::new(); + check(&b, &[]); + let off = b.start_table(); + check(&b, &[]); + b.force_defaults(true); + b.push_slot(fi2fo(0), false, false); + b.end_table(off); + check(&b, &[ + 6, 0, // vtable bytes + 8, 0, // length of object including vtable offset + 7, 0, // start of bool value + 6, 0, 0, 0, // offset for start of vtable (int32) + 0, 0, 0, // padded to 4 bytes + 0, // bool value + ]); + } + #[test] fn layout_10_vtable_with_one_int16() { let mut b = flatbuffers::FlatBufferBuilder::new();