Coverage Report

Created: 2026-03-11 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/flatbuffers-25.12.19/src/builder.rs
Line
Count
Source
1
/*
2
 * Copyright 2018 Google Inc. All rights reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#[cfg(not(feature = "std"))]
18
use alloc::{vec, vec::Vec};
19
use core::cmp::max;
20
use core::convert::Infallible;
21
use core::fmt::{Debug, Display};
22
use core::iter::{DoubleEndedIterator, ExactSizeIterator};
23
use core::marker::PhantomData;
24
use core::ops::{Add, AddAssign, Deref, DerefMut, Index, IndexMut, Sub, SubAssign};
25
use core::ptr::write_bytes;
26
27
use crate::endian_scalar::emplace_scalar;
28
use crate::primitives::*;
29
use crate::push::{Push, PushAlignment};
30
use crate::read_scalar;
31
use crate::table::Table;
32
use crate::vector::Vector;
33
use crate::vtable::{field_index_to_field_offset, VTable};
34
use crate::vtable_writer::VTableWriter;
35
36
/// Trait to implement custom allocation strategies for [`FlatBufferBuilder`].
37
///
38
/// An implementation can be used with [`FlatBufferBuilder::new_in`], enabling a custom allocation
39
/// strategy for the [`FlatBufferBuilder`].
40
///
41
/// # Safety
42
///
43
/// The implementation of the allocator must match the defined behavior as described by the
44
/// comments.
45
pub unsafe trait Allocator: DerefMut<Target = [u8]> {
46
    /// A type describing allocation failures
47
    type Error: Display + Debug;
48
    /// Grows the buffer, with the old contents being moved to the end.
49
    ///
50
    /// NOTE: While not unsound, an implementation that doesn't grow the
51
    /// internal buffer will get stuck in an infinite loop.
52
    fn grow_downwards(&mut self) -> Result<(), Self::Error>;
53
54
    /// Returns the size of the internal buffer in bytes.
55
    fn len(&self) -> usize;
56
}
57
58
/// Default [`FlatBufferBuilder`] allocator backed by a [`Vec<u8>`].
59
#[derive(Default)]
60
pub struct DefaultAllocator(Vec<u8>);
61
62
impl DefaultAllocator {
63
    /// Builds the allocator from an existing buffer.
64
0
    pub fn from_vec(buffer: Vec<u8>) -> Self {
65
0
        Self(buffer)
66
0
    }
67
}
68
69
impl Deref for DefaultAllocator {
70
    type Target = [u8];
71
72
0
    fn deref(&self) -> &Self::Target {
73
0
        &self.0
74
0
    }
75
}
76
77
impl DerefMut for DefaultAllocator {
78
0
    fn deref_mut(&mut self) -> &mut Self::Target {
79
0
        &mut self.0
80
0
    }
81
}
82
83
// SAFETY: The methods are implemented as described by the documentation.
84
unsafe impl Allocator for DefaultAllocator {
85
    type Error = Infallible;
86
0
    fn grow_downwards(&mut self) -> Result<(), Self::Error> {
87
0
        let old_len = self.0.len();
88
0
        let new_len = max(1, old_len * 2);
89
90
0
        self.0.resize(new_len, 0);
91
92
0
        if new_len == 1 {
93
0
            return Ok(());
94
0
        }
95
96
        // calculate the midpoint, and safely copy the old end data to the new
97
        // end position:
98
0
        let middle = new_len / 2;
99
0
        {
100
0
            let (left, right) = &mut self.0[..].split_at_mut(middle);
101
0
            right.copy_from_slice(left);
102
0
        }
103
        // finally, zero out the old end data.
104
        {
105
0
            let ptr = self.0[..middle].as_mut_ptr();
106
            // Safety:
107
            // ptr is byte aligned and of length middle
108
0
            unsafe {
109
0
                write_bytes(ptr, 0, middle);
110
0
            }
111
        }
112
0
        Ok(())
113
0
    }
114
115
0
    fn len(&self) -> usize {
116
0
        self.0.len()
117
0
    }
118
}
119
120
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
121
struct FieldLoc {
122
    off: UOffsetT,
123
    id: VOffsetT,
124
}
125
126
/// FlatBufferBuilder builds a FlatBuffer through manipulating its internal
127
/// state. It has an owned `Vec<u8>` that grows as needed (up to the hardcoded
128
/// limit of 2GiB, which is set by the FlatBuffers format).
129
#[derive(Clone, Debug, Eq, PartialEq)]
130
pub struct FlatBufferBuilder<'fbb, A: Allocator = DefaultAllocator> {
131
    allocator: A,
132
    head: ReverseIndex,
133
134
    field_locs: Vec<FieldLoc>,
135
    written_vtable_revpos: Vec<UOffsetT>,
136
137
    nested: bool,
138
    finished: bool,
139
140
    min_align: usize,
141
    force_defaults: bool,
142
    strings_pool: Vec<WIPOffset<&'fbb str>>,
143
144
    _phantom: PhantomData<&'fbb ()>,
145
}
146
147
impl<'fbb> FlatBufferBuilder<'fbb, DefaultAllocator> {
148
    /// Create a FlatBufferBuilder that is ready for writing.
149
0
    pub fn new() -> Self {
150
0
        Self::with_capacity(0)
151
0
    }
152
    #[deprecated(note = "replaced with `with_capacity`", since = "0.8.5")]
153
0
    pub fn new_with_capacity(size: usize) -> Self {
154
0
        Self::with_capacity(size)
155
0
    }
156
    /// Create a FlatBufferBuilder that is ready for writing, with a
157
    /// ready-to-use capacity of the provided size.
158
    ///
159
    /// The maximum valid value is `FLATBUFFERS_MAX_BUFFER_SIZE`.
160
0
    pub fn with_capacity(size: usize) -> Self {
161
0
        Self::from_vec(vec![0; size])
162
0
    }
163
    /// Create a FlatBufferBuilder that is ready for writing, reusing
164
    /// an existing vector.
165
0
    pub fn from_vec(buffer: Vec<u8>) -> Self {
166
        // we need to check the size here because we create the backing buffer
167
        // directly, bypassing the typical way of using grow_allocator:
168
0
        assert!(
169
0
            buffer.len() <= FLATBUFFERS_MAX_BUFFER_SIZE,
170
            "cannot initialize buffer bigger than 2 gigabytes"
171
        );
172
0
        let allocator = DefaultAllocator::from_vec(buffer);
173
0
        Self::new_in(allocator)
174
0
    }
175
176
    /// Destroy the FlatBufferBuilder, returning its internal byte vector
177
    /// and the index into it that represents the start of valid data.
178
0
    pub fn collapse(self) -> (Vec<u8>, usize) {
179
0
        let index = self.head.to_forward_index(&self.allocator);
180
0
        (self.allocator.0, index)
181
0
    }
182
}
183
184
impl<'fbb, A: Allocator> FlatBufferBuilder<'fbb, A> {
185
    /// Create a [`FlatBufferBuilder`] that is ready for writing with a custom [`Allocator`].
186
0
    pub fn new_in(allocator: A) -> Self {
187
0
        let head = ReverseIndex::end();
188
0
        FlatBufferBuilder {
189
0
            allocator,
190
0
            head,
191
0
192
0
            field_locs: Vec::new(),
193
0
            written_vtable_revpos: Vec::new(),
194
0
195
0
            nested: false,
196
0
            finished: false,
197
0
198
0
            min_align: 0,
199
0
            force_defaults: false,
200
0
            strings_pool: Vec::new(),
201
0
202
0
            _phantom: PhantomData,
203
0
        }
204
0
    }
205
206
    /// Destroy the [`FlatBufferBuilder`], returning its [`Allocator`] and the index
207
    /// into it that represents the start of valid data.
208
0
    pub fn collapse_in(self) -> (A, usize) {
209
0
        let index = self.head.to_forward_index(&self.allocator);
210
0
        (self.allocator, index)
211
0
    }
212
213
    /// Reset the FlatBufferBuilder internal state. Use this method after a
214
    /// call to a `finish` function in order to re-use a FlatBufferBuilder.
215
    ///
216
    /// This function is the only way to reset the `finished` state and start
217
    /// again.
218
    ///
219
    /// If you are using a FlatBufferBuilder repeatedly, make sure to use this
220
    /// function, because it re-uses the FlatBufferBuilder's existing
221
    /// heap-allocated `Vec<u8>` internal buffer. This offers significant speed
222
    /// improvements as compared to creating a new FlatBufferBuilder for every
223
    /// new object.
224
0
    pub fn reset(&mut self) {
225
        // memset only the part of the buffer that could be dirty:
226
0
        self.allocator[self.head.range_to_end()].iter_mut().for_each(|x| *x = 0);
227
228
0
        self.head = ReverseIndex::end();
229
0
        self.written_vtable_revpos.clear();
230
231
0
        self.nested = false;
232
0
        self.finished = false;
233
234
0
        self.min_align = 0;
235
0
        self.strings_pool.clear();
236
0
    }
237
238
    /// Push a Push'able value onto the front of the in-progress data.
239
    ///
240
    /// This function uses traits to provide a unified API for writing
241
    /// scalars, tables, vectors, and WIPOffsets.
242
    #[inline]
243
0
    pub fn push<P: Push>(&mut self, x: P) -> WIPOffset<P::Output> {
244
0
        let sz = P::size();
245
0
        self.align(sz, P::alignment());
246
0
        self.make_space(sz);
247
0
        {
248
0
            let (dst, rest) = self.allocator[self.head.range_to_end()].split_at_mut(sz);
249
0
            // Safety:
250
0
            // Called make_space above
251
0
            unsafe { x.push(dst, rest.len()) };
252
0
        }
253
0
        WIPOffset::new(self.used_space() as UOffsetT)
254
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::kind_generated::Kind>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::point_generated::Point>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::value_generated::Value>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::polygon_generated::Polygon>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::geometry_generated::Geometry>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::key_value_generated::KeyValue>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::line_string_generated::LineString>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::object_field_generated::ObjectField>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<&str>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::geometry_kind_type_generated::GeometryKindType>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<u8>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<flatbuffers::primitives::UnionWIPOffset>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::kind_generated::Kind>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::value_generated::Value>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::line_string_generated::LineString>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::record_id_key_generated::RecordIdKey>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::uint_64_value_generated::UInt64Value>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<flatbuffers::primitives::WIPOffset<&str>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::kind_type_generated::KindType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::value_type_generated::ValueType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::value_bound_generated::ValueBound>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::literal_type_generated::LiteralType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::geometry_type_generated::GeometryType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::record_id_key_type_generated::RecordIdKeyType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::record_id_key_bound_generated::RecordIdKeyBound>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<bool>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<f64>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<u8>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<u32>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<i64>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push::<u64>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::push::<_>
255
256
    /// Push a Push'able value onto the front of the in-progress data, and
257
    /// store a reference to it in the in-progress vtable. If the value matches
258
    /// the default, then this is a no-op.
259
    #[inline]
260
0
    pub fn push_slot<X: Push + PartialEq>(&mut self, slotoff: VOffsetT, x: X, default: X) {
261
0
        self.assert_nested("push_slot");
262
0
        if x != default || self.force_defaults {
263
0
            self.push_slot_always(slotoff, x);
264
0
        }
265
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::kind_type_generated::KindType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::value_type_generated::ValueType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::value_bound_generated::ValueBound>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::literal_type_generated::LiteralType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::geometry_type_generated::GeometryType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::record_id_key_type_generated::RecordIdKeyType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::record_id_key_bound_generated::RecordIdKeyBound>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot::<bool>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot::<f64>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot::<u32>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot::<i64>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot::<u64>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::push_slot::<_>
266
267
    /// Push a Push'able value onto the front of the in-progress data, and
268
    /// store a reference to it in the in-progress vtable.
269
    #[inline]
270
0
    pub fn push_slot_always<X: Push>(&mut self, slotoff: VOffsetT, x: X) {
271
0
        self.assert_nested("push_slot_always");
272
0
        let off = self.push(x);
273
0
        self.track_field(slotoff, off.value());
274
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::kind_generated::Kind>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::point_generated::Point>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::value_generated::Value>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::polygon_generated::Polygon>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::geometry_generated::Geometry>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::key_value_generated::KeyValue>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::line_string_generated::LineString>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::object_field_generated::ObjectField>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<flatbuffers::primitives::ForwardsUOffset<&str>>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::geometry_kind_type_generated::GeometryKindType>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<flatbuffers::vector::Vector<u8>>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<flatbuffers::primitives::UnionWIPOffset>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::kind_generated::Kind>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::value_generated::Value>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::line_string_generated::LineString>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::record_id_key_generated::RecordIdKey>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::uint_64_value_generated::UInt64Value>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<flatbuffers::primitives::WIPOffset<&str>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::kind_type_generated::KindType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::value_type_generated::ValueType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::value_bound_generated::ValueBound>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::literal_type_generated::LiteralType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::geometry_type_generated::GeometryType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::record_id_key_type_generated::RecordIdKeyType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::record_id_key_bound_generated::RecordIdKeyBound>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<bool>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<f64>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<u32>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<i64>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_slot_always::<u64>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::push_slot_always::<_>
275
276
    /// Retrieve the number of vtables that have been serialized into the
277
    /// FlatBuffer. This is primarily used to check vtable deduplication.
278
    #[inline]
279
0
    pub fn num_written_vtables(&self) -> usize {
280
0
        self.written_vtable_revpos.len()
281
0
    }
282
283
    /// Start a Table write.
284
    ///
285
    /// Asserts that the builder is not in a nested state.
286
    ///
287
    /// Users probably want to use `push_slot` to add values after calling this.
288
    #[inline]
289
0
    pub fn start_table(&mut self) -> WIPOffset<TableUnfinishedWIPOffset> {
290
0
        self.assert_not_nested(
291
            "start_table can not be called when a table or vector is under construction",
292
        );
293
0
        self.nested = true;
294
295
0
        WIPOffset::new(self.used_space() as UOffsetT)
296
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::start_table
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::start_table
297
298
    /// End a Table write.
299
    ///
300
    /// Asserts that the builder is in a nested state.
301
    #[inline]
302
0
    pub fn end_table(
303
0
        &mut self,
304
0
        off: WIPOffset<TableUnfinishedWIPOffset>,
305
0
    ) -> WIPOffset<TableFinishedWIPOffset> {
306
0
        self.assert_nested("end_table");
307
308
0
        let o = self.write_vtable(off);
309
310
0
        self.nested = false;
311
0
        self.field_locs.clear();
312
313
0
        WIPOffset::new(o.value())
314
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::end_table
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::end_table
315
316
    /// Start a Vector write.
317
    ///
318
    /// Asserts that the builder is not in a nested state.
319
    ///
320
    /// Most users will prefer to call `create_vector`.
321
    /// Speed optimizing users who choose to create vectors manually using this
322
    /// function will want to use `push` to add values.
323
    #[inline]
324
0
    pub fn start_vector<T: Push>(&mut self, num_items: usize) {
325
0
        self.assert_not_nested(
326
            "start_vector can not be called when a table or vector is under construction",
327
        );
328
0
        self.nested = true;
329
0
        self.align(num_items * T::size(), T::alignment().max_of(SIZE_UOFFSET));
330
0
    }
331
332
    /// End a Vector write.
333
    ///
334
    /// Note that the `num_elems` parameter is the number of written items, not
335
    /// the byte count.
336
    ///
337
    /// Asserts that the builder is in a nested state.
338
    #[inline]
339
0
    pub fn end_vector<T: Push>(&mut self, num_elems: usize) -> WIPOffset<Vector<'fbb, T>> {
340
0
        self.assert_nested("end_vector");
341
0
        self.nested = false;
342
0
        let o = self.push::<UOffsetT>(num_elems as UOffsetT);
343
0
        WIPOffset::new(o.value())
344
0
    }
345
346
    #[inline]
347
0
    pub fn create_shared_string<'a: 'b, 'b>(&'a mut self, s: &'b str) -> WIPOffset<&'fbb str> {
348
0
        self.assert_not_nested(
349
            "create_shared_string can not be called when a table or vector is under construction",
350
        );
351
352
        // Saves a ref to allocator since rust doesnt like us refrencing it
353
        // in the binary_search_by code.
354
0
        let buf = &self.allocator;
355
356
0
        let found = self.strings_pool.binary_search_by(|offset| {
357
0
            let ptr = offset.value() as usize;
358
            // Gets The pointer to the size of the string
359
0
            let str_memory = &buf[buf.len() - ptr..];
360
            // Gets the size of the written string from buffer
361
0
            let size =
362
0
                u32::from_le_bytes([str_memory[0], str_memory[1], str_memory[2], str_memory[3]])
363
0
                    as usize;
364
            // Size of the string size
365
0
            let string_size: usize = 4;
366
            // Fetches actual string bytes from index of string after string size
367
            // to the size of string plus string size
368
0
            let iter = str_memory[string_size..size + string_size].iter();
369
            // Compares bytes of fetched string and current writable string
370
0
            iter.cloned().cmp(s.bytes())
371
0
        });
372
373
0
        match found {
374
0
            Ok(index) => self.strings_pool[index],
375
0
            Err(index) => {
376
0
                let address = WIPOffset::new(self.create_byte_string(s.as_bytes()).value());
377
0
                self.strings_pool.insert(index, address);
378
0
                address
379
            }
380
        }
381
0
    }
382
383
    /// Create a utf8 string.
384
    ///
385
    /// The wire format represents this as a zero-terminated byte vector.
386
    #[inline]
387
0
    pub fn create_string<'a: 'b, 'b>(&'a mut self, s: &'b str) -> WIPOffset<&'fbb str> {
388
0
        self.assert_not_nested(
389
            "create_string can not be called when a table or vector is under construction",
390
        );
391
0
        WIPOffset::new(self.create_byte_string(s.as_bytes()).value())
392
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::create_string
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::create_string
393
394
    /// Create a zero-terminated byte vector.
395
    #[inline]
396
0
    pub fn create_byte_string(&mut self, data: &[u8]) -> WIPOffset<&'fbb [u8]> {
397
0
        self.assert_not_nested(
398
            "create_byte_string can not be called when a table or vector is under construction",
399
        );
400
0
        self.align(data.len() + 1, PushAlignment::new(SIZE_UOFFSET));
401
0
        self.push(0u8);
402
0
        self.push_bytes_unprefixed(data);
403
0
        self.push(data.len() as UOffsetT);
404
0
        WIPOffset::new(self.used_space() as UOffsetT)
405
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::create_byte_string
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::create_byte_string
406
407
    /// Create a vector of Push-able objects.
408
    ///
409
    /// Speed-sensitive users may wish to reduce memory usage by creating the
410
    /// vector manually: use `start_vector`, `push`, and `end_vector`.
411
    #[inline]
412
0
    pub fn create_vector<'a: 'b, 'b, T: Push + 'b>(
413
0
        &'a mut self,
414
0
        items: &'b [T],
415
0
    ) -> WIPOffset<Vector<'fbb, T::Output>> {
416
0
        let elem_size = T::size();
417
0
        let slice_size = items.len() * elem_size;
418
0
        self.align(slice_size, T::alignment().max_of(SIZE_UOFFSET));
419
0
        self.ensure_capacity(slice_size + UOffsetT::size());
420
421
0
        self.head -= slice_size;
422
0
        let mut written_len = self.head.distance_to_end();
423
424
0
        let buf = &mut self.allocator[self.head.range_to(self.head + slice_size)];
425
0
        for (item, out) in items.iter().zip(buf.chunks_exact_mut(elem_size)) {
426
0
            written_len -= elem_size;
427
0
428
0
            // Safety:
429
0
            // Called ensure_capacity and aligned to T above
430
0
            unsafe { item.push(out, written_len) };
431
0
        }
432
433
0
        WIPOffset::new(self.push::<UOffsetT>(items.len() as UOffsetT).value())
434
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::create_vector::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::kind_generated::Kind>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::create_vector::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::point_generated::Point>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::create_vector::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::value_generated::Value>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::create_vector::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::polygon_generated::Polygon>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::create_vector::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::geometry_generated::Geometry>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::create_vector::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::key_value_generated::KeyValue>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::create_vector::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::line_string_generated::LineString>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::create_vector::<flatbuffers::primitives::WIPOffset<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::object_field_generated::ObjectField>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::create_vector::<flatbuffers::primitives::WIPOffset<&str>>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::create_vector::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::geometry_kind_type_generated::GeometryKindType>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::create_vector::<u8>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::create_vector::<_>
435
436
    /// Create a vector of Push-able objects.
437
    ///
438
    /// Speed-sensitive users may wish to reduce memory usage by creating the
439
    /// vector manually: use `start_vector`, `push`, and `end_vector`.
440
    #[inline]
441
0
    pub fn create_vector_from_iter<T: Push>(
442
0
        &mut self,
443
0
        items: impl ExactSizeIterator<Item = T> + DoubleEndedIterator,
444
0
    ) -> WIPOffset<Vector<'fbb, T::Output>> {
445
0
        let elem_size = T::size();
446
0
        self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET));
447
0
        let mut actual = 0;
448
0
        for item in items.rev() {
449
0
            self.push(item);
450
0
            actual += 1;
451
0
        }
452
0
        WIPOffset::new(self.push::<UOffsetT>(actual).value())
453
0
    }
454
455
    /// Set whether default values are stored.
456
    ///
457
    /// In order to save space, fields that are set to their default value
458
    /// aren't stored in the buffer. Setting `force_defaults` to `true`
459
    /// disables this optimization.
460
    ///
461
    /// By default, `force_defaults` is `false`.
462
    #[inline]
463
0
    pub fn force_defaults(&mut self, force_defaults: bool) {
464
0
        self.force_defaults = force_defaults;
465
0
    }
466
467
    /// Get the byte slice for the data that has been written, regardless of
468
    /// whether it has been finished.
469
    #[inline]
470
0
    pub fn unfinished_data(&self) -> &[u8] {
471
0
        &self.allocator[self.head.range_to_end()]
472
0
    }
473
    /// Get the byte slice for the data that has been written after a call to
474
    /// one of the `finish` functions.
475
    /// # Panics
476
    /// Panics if the buffer is not finished.
477
    #[inline]
478
0
    pub fn finished_data(&self) -> &[u8] {
479
0
        self.assert_finished("finished_bytes cannot be called when the buffer is not yet finished");
480
0
        &self.allocator[self.head.range_to_end()]
481
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::finished_data
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::finished_data
482
    /// Returns a mutable view of a finished buffer and location of where the flatbuffer starts.
483
    /// Note that modifying the flatbuffer data may corrupt it.
484
    /// # Panics
485
    /// Panics if the flatbuffer is not finished.
486
    #[inline]
487
0
    pub fn mut_finished_buffer(&mut self) -> (&mut [u8], usize) {
488
0
        let index = self.head.to_forward_index(&self.allocator);
489
0
        (&mut self.allocator[..], index)
490
0
    }
491
    /// Assert that a field is present in the just-finished Table.
492
    ///
493
    /// This is somewhat low-level and is mostly used by the generated code.
494
    #[inline]
495
0
    pub fn required(
496
0
        &self,
497
0
        tab_revloc: WIPOffset<TableFinishedWIPOffset>,
498
0
        slot_byte_loc: VOffsetT,
499
0
        assert_msg_name: &'static str,
500
0
    ) {
501
0
        let idx = self.used_space() - tab_revloc.value() as usize;
502
503
        // Safety:
504
        // The value of TableFinishedWIPOffset is the offset from the end of the allocator
505
        // to an SOffsetT pointing to a valid VTable
506
        //
507
        // `self.allocator.len() = self.used_space() + self.head`
508
        // `self.allocator.len() - tab_revloc = self.used_space() - tab_revloc + self.head`
509
        // `self.allocator.len() - tab_revloc = idx + self.head`
510
0
        let tab = unsafe { Table::new(&self.allocator[self.head.range_to_end()], idx) };
511
0
        let o = tab.vtable().get(slot_byte_loc) as usize;
512
0
        assert!(o != 0, "missing required field {}", assert_msg_name);
513
0
    }
514
515
    /// Finalize the FlatBuffer by: aligning it, pushing an optional file
516
    /// identifier on to it, pushing a size prefix on to it, and marking the
517
    /// internal state of the FlatBufferBuilder as `finished`. Afterwards,
518
    /// users can call `finished_data` to get the resulting data.
519
    #[inline]
520
0
    pub fn finish_size_prefixed<T>(&mut self, root: WIPOffset<T>, file_identifier: Option<&str>) {
521
0
        self.finish_with_opts(root, file_identifier, true);
522
0
    }
523
524
    /// Finalize the FlatBuffer by: aligning it, pushing an optional file
525
    /// identifier on to it, and marking the internal state of the
526
    /// FlatBufferBuilder as `finished`. Afterwards, users can call
527
    /// `finished_data` to get the resulting data.
528
    #[inline]
529
0
    pub fn finish<T>(&mut self, root: WIPOffset<T>, file_identifier: Option<&str>) {
530
0
        self.finish_with_opts(root, file_identifier, false);
531
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::finish::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::kind_generated::Kind>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::finish::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::value_generated::Value>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::finish::<_>
532
533
    /// Finalize the FlatBuffer by: aligning it and marking the internal state
534
    /// of the FlatBufferBuilder as `finished`. Afterwards, users can call
535
    /// `finished_data` to get the resulting data.
536
    #[inline]
537
0
    pub fn finish_minimal<T>(&mut self, root: WIPOffset<T>) {
538
0
        self.finish_with_opts(root, None, false);
539
0
    }
540
541
    #[inline]
542
0
    fn used_space(&self) -> usize {
543
0
        self.head.distance_to_end()
544
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::used_space
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::used_space
545
546
    #[inline]
547
0
    fn track_field(&mut self, slot_off: VOffsetT, off: UOffsetT) {
548
0
        let fl = FieldLoc { id: slot_off, off };
549
0
        self.field_locs.push(fl);
550
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::track_field
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::track_field
551
552
    /// Write the VTable, if it is new.
553
0
    fn write_vtable(
554
0
        &mut self,
555
0
        table_tail_revloc: WIPOffset<TableUnfinishedWIPOffset>,
556
0
    ) -> WIPOffset<VTableWIPOffset> {
557
0
        self.assert_nested("write_vtable");
558
559
        // Write the vtable offset, which is the start of any Table.
560
        // We fill its value later.
561
0
        let object_revloc_to_vtable: WIPOffset<VTableWIPOffset> =
562
0
            WIPOffset::new(self.push::<UOffsetT>(0xF0F0_F0F0).value());
563
564
        // Layout of the data this function will create when a new vtable is
565
        // needed.
566
        // --------------------------------------------------------------------
567
        // vtable starts here
568
        // | x, x -- vtable len (bytes) [u16]
569
        // | x, x -- object inline len (bytes) [u16]
570
        // | x, x -- zero, or num bytes from start of object to field #0   [u16]
571
        // | ...
572
        // | x, x -- zero, or num bytes from start of object to field #n-1 [u16]
573
        // vtable ends here
574
        // table starts here
575
        // | x, x, x, x -- offset (negative direction) to the vtable [i32]
576
        // |               aka "vtableoffset"
577
        // | -- table inline data begins here, we don't touch it --
578
        // table ends here -- aka "table_start"
579
        // --------------------------------------------------------------------
580
        //
581
        // Layout of the data this function will create when we re-use an
582
        // existing vtable.
583
        //
584
        // We always serialize this particular vtable, then compare it to the
585
        // other vtables we know about to see if there is a duplicate. If there
586
        // is, then we erase the serialized vtable we just made.
587
        // We serialize it first so that we are able to do byte-by-byte
588
        // comparisons with already-serialized vtables. This 1) saves
589
        // bookkeeping space (we only keep revlocs to existing vtables), 2)
590
        // allows us to convert to little-endian once, then do
591
        // fast memcmp comparisons, and 3) by ensuring we are comparing real
592
        // serialized vtables, we can be more assured that we are doing the
593
        // comparisons correctly.
594
        //
595
        // --------------------------------------------------------------------
596
        // table starts here
597
        // | x, x, x, x -- offset (negative direction) to an existing vtable [i32]
598
        // |               aka "vtableoffset"
599
        // | -- table inline data begins here, we don't touch it --
600
        // table starts here: aka "table_start"
601
        // --------------------------------------------------------------------
602
603
        // fill the WIP vtable with zeros:
604
0
        let vtable_byte_len = get_vtable_byte_len(&self.field_locs);
605
0
        self.make_space(vtable_byte_len);
606
607
        // compute the length of the table (not vtable!) in bytes:
608
0
        let table_object_size = object_revloc_to_vtable.value() - table_tail_revloc.value();
609
0
        debug_assert!(table_object_size < 0x10000); // vTable use 16bit offsets.
610
611
        // Write the VTable (we may delete it afterwards, if it is a duplicate):
612
0
        let vt_start_pos = self.head;
613
0
        let vt_end_pos = self.head + vtable_byte_len;
614
        {
615
            // write the vtable header:
616
0
            let vtfw =
617
0
                &mut VTableWriter::init(&mut self.allocator[vt_start_pos.range_to(vt_end_pos)]);
618
0
            vtfw.write_vtable_byte_length(vtable_byte_len as VOffsetT);
619
0
            vtfw.write_object_inline_size(table_object_size as VOffsetT);
620
621
            // serialize every FieldLoc to the vtable:
622
0
            for &fl in self.field_locs.iter() {
623
0
                let pos: VOffsetT = (object_revloc_to_vtable.value() - fl.off) as VOffsetT;
624
0
                vtfw.write_field_offset(fl.id, pos);
625
0
            }
626
        }
627
0
        let new_vt_bytes = &self.allocator[vt_start_pos.range_to(vt_end_pos)];
628
0
        let found = self.written_vtable_revpos.binary_search_by(|old_vtable_revpos: &UOffsetT| {
629
0
            let old_vtable_pos = self.allocator.len() - *old_vtable_revpos as usize;
630
            // Safety:
631
            // Already written vtables are valid by construction
632
0
            let old_vtable = unsafe { VTable::init(&self.allocator, old_vtable_pos) };
633
0
            new_vt_bytes.cmp(old_vtable.as_bytes())
634
0
        });
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::write_vtable::{closure#0}
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::write_vtable::{closure#0}
635
0
        let final_vtable_revpos = match found {
636
0
            Ok(i) => {
637
                // The new vtable is a duplicate so clear it.
638
0
                VTableWriter::init(&mut self.allocator[vt_start_pos.range_to(vt_end_pos)]).clear();
639
0
                self.head += vtable_byte_len;
640
0
                self.written_vtable_revpos[i]
641
            }
642
0
            Err(i) => {
643
                // This is a new vtable. Add it to the cache.
644
0
                let new_vt_revpos = self.used_space() as UOffsetT;
645
0
                self.written_vtable_revpos.insert(i, new_vt_revpos);
646
0
                new_vt_revpos
647
            }
648
        };
649
        // Write signed offset from table to its vtable.
650
0
        let table_pos = self.allocator.len() - object_revloc_to_vtable.value() as usize;
651
0
        if cfg!(debug_assertions) {
652
            // Safety:
653
            // Verified slice length
654
0
            let tmp_soffset_to_vt = unsafe {
655
0
                read_scalar::<UOffsetT>(&self.allocator[table_pos..table_pos + SIZE_UOFFSET])
656
            };
657
0
            assert_eq!(tmp_soffset_to_vt, 0xF0F0_F0F0);
658
0
        }
659
660
0
        let buf = &mut self.allocator[table_pos..table_pos + SIZE_SOFFSET];
661
        // Safety:
662
        // Verified length of buf above
663
0
        unsafe {
664
0
            emplace_scalar::<SOffsetT>(
665
0
                buf,
666
0
                final_vtable_revpos as SOffsetT - object_revloc_to_vtable.value() as SOffsetT,
667
0
            );
668
0
        }
669
670
0
        self.field_locs.clear();
671
672
0
        object_revloc_to_vtable
673
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::write_vtable
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::write_vtable
674
675
    // Only call this when you know it is safe to double the size of the buffer.
676
    #[inline]
677
0
    fn grow_allocator(&mut self) {
678
0
        let starting_active_size = self.used_space();
679
0
        self.allocator.grow_downwards().expect("Flatbuffer allocation failure");
680
681
0
        let ending_active_size = self.used_space();
682
0
        debug_assert_eq!(starting_active_size, ending_active_size);
683
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::grow_allocator
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::grow_allocator
684
685
    // with or without a size prefix changes how we load the data, so finish*
686
    // functions are split along those lines.
687
0
    fn finish_with_opts<T>(
688
0
        &mut self,
689
0
        root: WIPOffset<T>,
690
0
        file_identifier: Option<&str>,
691
0
        size_prefixed: bool,
692
0
    ) {
693
0
        self.assert_not_finished("buffer cannot be finished when it is already finished");
694
0
        self.assert_not_nested(
695
            "buffer cannot be finished when a table or vector is under construction",
696
        );
697
0
        self.written_vtable_revpos.clear();
698
699
0
        let to_align = {
700
            // for the root offset:
701
0
            let a = SIZE_UOFFSET;
702
            // for the size prefix:
703
0
            let b = if size_prefixed { SIZE_UOFFSET } else { 0 };
704
            // for the file identifier (a string that is not zero-terminated):
705
0
            let c = if file_identifier.is_some() { FILE_IDENTIFIER_LENGTH } else { 0 };
706
0
            a + b + c
707
        };
708
709
0
        {
710
0
            let ma = PushAlignment::new(self.min_align);
711
0
            self.align(to_align, ma);
712
0
        }
713
714
0
        if let Some(ident) = file_identifier {
715
0
            debug_assert_eq!(ident.len(), FILE_IDENTIFIER_LENGTH);
716
0
            self.push_bytes_unprefixed(ident.as_bytes());
717
0
        }
718
719
0
        self.push(root);
720
721
0
        if size_prefixed {
722
0
            let sz = self.used_space() as UOffsetT;
723
0
            self.push::<UOffsetT>(sz);
724
0
        }
725
0
        self.finished = true;
726
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::finish_with_opts::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::kind_generated::Kind>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::finish_with_opts::<surrealdb_protocol::fb::generated::surrealdb::protocol::v_1::value_generated::Value>
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::finish_with_opts::<_>
727
728
    #[inline]
729
0
    fn align(&mut self, len: usize, alignment: PushAlignment) {
730
0
        self.track_min_align(alignment.value());
731
0
        let s = self.used_space() as usize;
732
0
        self.make_space(padding_bytes(s + len, alignment.value()));
733
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::align
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::align
734
735
    #[inline]
736
0
    fn track_min_align(&mut self, alignment: usize) {
737
0
        self.min_align = max(self.min_align, alignment);
738
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::track_min_align
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::track_min_align
739
740
    #[inline]
741
0
    fn push_bytes_unprefixed(&mut self, x: &[u8]) -> UOffsetT {
742
0
        let n = self.make_space(x.len());
743
0
        self.allocator[n.range_to(n + x.len())].copy_from_slice(x);
744
745
0
        n.to_forward_index(&self.allocator) as UOffsetT
746
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::push_bytes_unprefixed
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::push_bytes_unprefixed
747
748
    #[inline]
749
0
    fn make_space(&mut self, want: usize) -> ReverseIndex {
750
0
        self.ensure_capacity(want);
751
0
        self.head -= want;
752
0
        self.head
753
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::make_space
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::make_space
754
755
    #[inline]
756
0
    fn ensure_capacity(&mut self, want: usize) -> usize {
757
0
        if self.unused_ready_space() >= want {
758
0
            return want;
759
0
        }
760
0
        assert!(want <= FLATBUFFERS_MAX_BUFFER_SIZE, "cannot grow buffer beyond 2 gigabytes");
761
762
0
        while self.unused_ready_space() < want {
763
0
            self.grow_allocator();
764
0
        }
765
0
        want
766
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::ensure_capacity
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::ensure_capacity
767
    #[inline]
768
0
    fn unused_ready_space(&self) -> usize {
769
0
        self.allocator.len() - self.head.distance_to_end()
770
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::unused_ready_space
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::unused_ready_space
771
    #[inline]
772
0
    fn assert_nested(&self, fn_name: &'static str) {
773
        // we don't assert that self.field_locs.len() >0 because the vtable
774
        // could be empty (e.g. for empty tables, or for all-default values).
775
0
        debug_assert!(
776
0
            self.nested,
777
            "incorrect FlatBufferBuilder usage: {} must be called while in a nested state",
778
            fn_name
779
        );
780
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::assert_nested
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::assert_nested
781
    #[inline]
782
0
    fn assert_not_nested(&self, msg: &'static str) {
783
0
        debug_assert!(!self.nested, "{}", msg);
784
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::assert_not_nested
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::assert_not_nested
785
    #[inline]
786
0
    fn assert_finished(&self, msg: &'static str) {
787
0
        debug_assert!(self.finished, "{}", msg);
788
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::assert_finished
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::assert_finished
789
    #[inline]
790
0
    fn assert_not_finished(&self, msg: &'static str) {
791
0
        debug_assert!(!self.finished, "{}", msg);
792
0
    }
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder>::assert_not_finished
Unexecuted instantiation: <flatbuffers::builder::FlatBufferBuilder<_>>::assert_not_finished
793
}
794
795
/// Compute the length of the vtable needed to represent the provided FieldLocs.
796
/// If there are no FieldLocs, then provide the minimum number of bytes
797
/// required: enough to write the VTable header.
798
#[inline]
799
0
fn get_vtable_byte_len(field_locs: &[FieldLoc]) -> usize {
800
0
    let max_voffset = field_locs.iter().map(|fl| fl.id).max();
801
0
    match max_voffset {
802
0
        None => field_index_to_field_offset(0) as usize,
803
0
        Some(mv) => mv as usize + SIZE_VOFFSET,
804
    }
805
0
}
Unexecuted instantiation: flatbuffers::builder::get_vtable_byte_len
Unexecuted instantiation: flatbuffers::builder::get_vtable_byte_len
806
807
#[inline]
808
0
fn padding_bytes(buf_size: usize, scalar_size: usize) -> usize {
809
    // ((!buf_size) + 1) & (scalar_size - 1)
810
0
    (!buf_size).wrapping_add(1) & (scalar_size.wrapping_sub(1))
811
0
}
Unexecuted instantiation: flatbuffers::builder::padding_bytes
Unexecuted instantiation: flatbuffers::builder::padding_bytes
812
813
impl<'fbb> Default for FlatBufferBuilder<'fbb> {
814
0
    fn default() -> Self {
815
0
        Self::with_capacity(0)
816
0
    }
817
}
818
819
/// An index that indexes from the reverse of a slice.
820
///
821
/// Note that while the internal representation is an index
822
/// from the end of a buffer, operations like `Add` and `Sub`
823
/// behave like a regular index:
824
///
825
/// # Examples
826
///
827
/// ```ignore
828
/// let buf = [0, 1, 2, 3, 4, 5];
829
/// let idx = ReverseIndex::end() - 2;
830
/// assert_eq!(&buf[idx.range_to_end()], &[4, 5]);
831
/// assert_eq!(idx.to_forward_index(&buf), 4);
832
/// ```
833
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
834
struct ReverseIndex(usize);
835
836
impl ReverseIndex {
837
    /// Returns an index set to the end.
838
    ///
839
    /// Note: Indexing this will result in an out of bounds error.
840
0
    pub fn end() -> Self {
841
0
        Self(0)
842
0
    }
843
844
    /// Returns a struct equivalent to the range `self..`
845
0
    pub fn range_to_end(self) -> ReverseIndexRange {
846
0
        ReverseIndexRange(self, ReverseIndex::end())
847
0
    }
848
849
    /// Returns a struct equivalent to the range `self..end`
850
0
    pub fn range_to(self, end: ReverseIndex) -> ReverseIndexRange {
851
0
        ReverseIndexRange(self, end)
852
0
    }
853
854
    /// Transforms this reverse index into a regular index for the given buffer.
855
0
    pub fn to_forward_index<T>(self, buf: &[T]) -> usize {
856
0
        buf.len() - self.0
857
0
    }
858
859
    /// Returns the number of elements until the end of the range.
860
0
    pub fn distance_to_end(&self) -> usize {
861
0
        self.0
862
0
    }
863
}
864
865
impl Sub<usize> for ReverseIndex {
866
    type Output = Self;
867
868
0
    fn sub(self, rhs: usize) -> Self::Output {
869
0
        Self(self.0 + rhs)
870
0
    }
871
}
872
873
impl SubAssign<usize> for ReverseIndex {
874
0
    fn sub_assign(&mut self, rhs: usize) {
875
0
        *self = *self - rhs;
876
0
    }
877
}
878
879
impl Add<usize> for ReverseIndex {
880
    type Output = Self;
881
882
0
    fn add(self, rhs: usize) -> Self::Output {
883
0
        Self(self.0 - rhs)
884
0
    }
885
}
886
887
impl AddAssign<usize> for ReverseIndex {
888
0
    fn add_assign(&mut self, rhs: usize) {
889
0
        *self = *self + rhs;
890
0
    }
891
}
892
impl<T> Index<ReverseIndex> for [T] {
893
    type Output = T;
894
895
0
    fn index(&self, index: ReverseIndex) -> &Self::Output {
896
0
        let index = index.to_forward_index(self);
897
0
        &self[index]
898
0
    }
899
}
900
901
impl<T> IndexMut<ReverseIndex> for [T] {
902
0
    fn index_mut(&mut self, index: ReverseIndex) -> &mut Self::Output {
903
0
        let index = index.to_forward_index(self);
904
0
        &mut self[index]
905
0
    }
906
}
907
908
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
909
struct ReverseIndexRange(ReverseIndex, ReverseIndex);
910
911
impl<T> Index<ReverseIndexRange> for [T] {
912
    type Output = [T];
913
914
0
    fn index(&self, index: ReverseIndexRange) -> &Self::Output {
915
0
        let start = index.0.to_forward_index(self);
916
0
        let end = index.1.to_forward_index(self);
917
0
        &self[start..end]
918
0
    }
Unexecuted instantiation: <[u8] as core::ops::index::Index<flatbuffers::builder::ReverseIndexRange>>::index
Unexecuted instantiation: <[_] as core::ops::index::Index<flatbuffers::builder::ReverseIndexRange>>::index
919
}
920
921
impl<T> IndexMut<ReverseIndexRange> for [T] {
922
0
    fn index_mut(&mut self, index: ReverseIndexRange) -> &mut Self::Output {
923
0
        let start = index.0.to_forward_index(self);
924
0
        let end = index.1.to_forward_index(self);
925
0
        &mut self[start..end]
926
0
    }
Unexecuted instantiation: <[u8] as core::ops::index::IndexMut<flatbuffers::builder::ReverseIndexRange>>::index_mut
Unexecuted instantiation: <[_] as core::ops::index::IndexMut<flatbuffers::builder::ReverseIndexRange>>::index_mut
927
}
928
929
#[cfg(test)]
930
mod tests {
931
    use super::*;
932
933
    #[test]
934
    fn reverse_index_test() {
935
        let buf = [0, 1, 2, 3, 4, 5];
936
        let idx = ReverseIndex::end() - 2;
937
        assert_eq!(&buf[idx.range_to_end()], &[4, 5]);
938
        assert_eq!(&buf[idx.range_to(idx + 1)], &[4]);
939
        assert_eq!(idx.to_forward_index(&buf), 4);
940
    }
941
}