diff --git a/rust/flatbuffers/src/builder.rs b/rust/flatbuffers/src/builder.rs index 698817e04..f755a4987 100644 --- a/rust/flatbuffers/src/builder.rs +++ b/rust/flatbuffers/src/builder.rs @@ -29,6 +29,8 @@ use vtable::{VTable, field_index_to_field_offset}; use vtable_writer::VTableWriter; use vector::{SafeSliceAccess, Vector}; +pub const N_SMALLVEC_STRING_VECTOR_CAPACITY: usize = 16; + #[derive(Clone, Copy, Debug)] struct FieldLoc { off: UOffsetT, @@ -268,10 +270,12 @@ impl<'fbb> FlatBufferBuilder<'fbb> { #[inline] pub fn create_vector_of_strings<'a, 'b>(&'a mut self, xs: &'b [&'b str]) -> WIPOffset>> { self.assert_not_nested("create_vector_of_strings can not be called when a table or vector is under construction"); - // internally, smallvec can be a stack-allocated or heap-allocated vector. - // we expect it to usually be stack-allocated. - let mut offsets: smallvec::SmallVec<[WIPOffset<&str>; 0]> = smallvec::SmallVec::with_capacity(xs.len()); + // internally, smallvec can be a stack-allocated or heap-allocated vector: + // if xs.len() > N_SMALLVEC_STRING_VECTOR_CAPACITY then it will overflow to the heap. + let mut offsets: smallvec::SmallVec<[WIPOffset<&str>; N_SMALLVEC_STRING_VECTOR_CAPACITY]> = smallvec::SmallVec::with_capacity(xs.len()); unsafe { offsets.set_len(xs.len()); } + + // note that this happens in reverse, because the buffer is built back-to-front: for (i, &s) in xs.iter().enumerate().rev() { let o = self.create_string(s); offsets[i] = o; diff --git a/tests/rust_usage_test/bin/alloc_check.rs b/tests/rust_usage_test/bin/alloc_check.rs index 54469a6e1..7fb3ef33f 100644 --- a/tests/rust_usage_test/bin/alloc_check.rs +++ b/tests/rust_usage_test/bin/alloc_check.rs @@ -35,6 +35,8 @@ pub use monster_test_generated::my_game; // verbatim from the test suite: fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder) { let mon = { + let _ = builder.create_vector_of_strings(&["these", "unused", "strings", "check", "the", "create_vector_of_strings", "function"]); + let s0 = builder.create_string("test1"); let s1 = builder.create_string("test2"); let fred_name = builder.create_string("Fred"); @@ -79,7 +81,7 @@ fn main() { create_serialized_example_with_generated_code(builder); } - // reset the builder, clearing its heap-allocted memory: + // reset the builder, clearing its heap-allocated memory: builder.reset(); {