xref: /aosp_15_r20/external/flatbuffers/rust/flexbuffers/src/builder/mod.rs (revision 890232f25432b36107d06881e0a25aaa6b473652)
1*890232f2SAndroid Build Coastguard Worker // Copyright 2019 Google LLC
2*890232f2SAndroid Build Coastguard Worker //
3*890232f2SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*890232f2SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*890232f2SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*890232f2SAndroid Build Coastguard Worker //
7*890232f2SAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*890232f2SAndroid Build Coastguard Worker //
9*890232f2SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*890232f2SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*890232f2SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*890232f2SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*890232f2SAndroid Build Coastguard Worker // limitations under the License.
14*890232f2SAndroid Build Coastguard Worker 
15*890232f2SAndroid Build Coastguard Worker use crate::bitwidth::{align, BitWidth};
16*890232f2SAndroid Build Coastguard Worker mod value;
17*890232f2SAndroid Build Coastguard Worker use crate::FlexBufferType;
18*890232f2SAndroid Build Coastguard Worker use std::cmp::max;
19*890232f2SAndroid Build Coastguard Worker use value::{find_vector_type, store_value, Value};
20*890232f2SAndroid Build Coastguard Worker mod map;
21*890232f2SAndroid Build Coastguard Worker mod push;
22*890232f2SAndroid Build Coastguard Worker mod ser;
23*890232f2SAndroid Build Coastguard Worker mod vector;
24*890232f2SAndroid Build Coastguard Worker use map::sort_map_by_keys;
25*890232f2SAndroid Build Coastguard Worker pub use map::MapBuilder;
26*890232f2SAndroid Build Coastguard Worker pub use push::Pushable;
27*890232f2SAndroid Build Coastguard Worker pub use ser::{Error, FlexbufferSerializer};
28*890232f2SAndroid Build Coastguard Worker pub use vector::VectorBuilder;
29*890232f2SAndroid Build Coastguard Worker 
30*890232f2SAndroid Build Coastguard Worker macro_rules! push_slice {
31*890232f2SAndroid Build Coastguard Worker     ($push_name: ident, $scalar: ty, $Val: ident, $new_vec: ident) => {
32*890232f2SAndroid Build Coastguard Worker         fn $push_name<T, S>(&mut self, xs: S)
33*890232f2SAndroid Build Coastguard Worker         where
34*890232f2SAndroid Build Coastguard Worker             T: Into<$scalar> + Copy,
35*890232f2SAndroid Build Coastguard Worker             S: AsRef<[T]>,
36*890232f2SAndroid Build Coastguard Worker         {
37*890232f2SAndroid Build Coastguard Worker             let mut value = Value::$new_vec(xs.as_ref().len());
38*890232f2SAndroid Build Coastguard Worker             let mut width = xs
39*890232f2SAndroid Build Coastguard Worker                 .as_ref()
40*890232f2SAndroid Build Coastguard Worker                 .iter()
41*890232f2SAndroid Build Coastguard Worker                 .map(|x| BitWidth::from((*x).into()))
42*890232f2SAndroid Build Coastguard Worker                 .max()
43*890232f2SAndroid Build Coastguard Worker                 .unwrap_or_default();
44*890232f2SAndroid Build Coastguard Worker             if !value.is_fixed_length_vector() {
45*890232f2SAndroid Build Coastguard Worker                 let length = Value::UInt(xs.as_ref().len() as u64);
46*890232f2SAndroid Build Coastguard Worker                 width = std::cmp::max(width, length.width_or_child_width());
47*890232f2SAndroid Build Coastguard Worker                 align(&mut self.buffer, width);
48*890232f2SAndroid Build Coastguard Worker                 store_value(&mut self.buffer, length, width);
49*890232f2SAndroid Build Coastguard Worker             } else {
50*890232f2SAndroid Build Coastguard Worker                 align(&mut self.buffer, width);
51*890232f2SAndroid Build Coastguard Worker             }
52*890232f2SAndroid Build Coastguard Worker             let address = self.buffer.len();
53*890232f2SAndroid Build Coastguard Worker             for &x in xs.as_ref().iter() {
54*890232f2SAndroid Build Coastguard Worker                 store_value(&mut self.buffer, Value::$Val(x.into()), width);
55*890232f2SAndroid Build Coastguard Worker             }
56*890232f2SAndroid Build Coastguard Worker             value.set_address_or_panic(address);
57*890232f2SAndroid Build Coastguard Worker             value.set_child_width_or_panic(width);
58*890232f2SAndroid Build Coastguard Worker             self.values.push(value);
59*890232f2SAndroid Build Coastguard Worker         }
60*890232f2SAndroid Build Coastguard Worker     };
61*890232f2SAndroid Build Coastguard Worker }
62*890232f2SAndroid Build Coastguard Worker macro_rules! push_indirect {
63*890232f2SAndroid Build Coastguard Worker     ($push_name: ident, $scalar: ty, $Direct: ident, $Indirect: ident) => {
64*890232f2SAndroid Build Coastguard Worker         fn $push_name<T: Into<$scalar>>(&mut self, x: T) {
65*890232f2SAndroid Build Coastguard Worker             let x = Value::$Direct(x.into());
66*890232f2SAndroid Build Coastguard Worker             let child_width = x.width_or_child_width();
67*890232f2SAndroid Build Coastguard Worker             let address = self.buffer.len();
68*890232f2SAndroid Build Coastguard Worker             store_value(&mut self.buffer, x, child_width);
69*890232f2SAndroid Build Coastguard Worker             self.values.push(Value::Reference {
70*890232f2SAndroid Build Coastguard Worker                 address,
71*890232f2SAndroid Build Coastguard Worker                 child_width,
72*890232f2SAndroid Build Coastguard Worker                 fxb_type: FlexBufferType::$Indirect,
73*890232f2SAndroid Build Coastguard Worker             });
74*890232f2SAndroid Build Coastguard Worker         }
75*890232f2SAndroid Build Coastguard Worker     };
76*890232f2SAndroid Build Coastguard Worker }
77*890232f2SAndroid Build Coastguard Worker 
78*890232f2SAndroid Build Coastguard Worker bitflags! {
79*890232f2SAndroid Build Coastguard Worker     /// Options for sharing data within a flexbuffer.
80*890232f2SAndroid Build Coastguard Worker     ///
81*890232f2SAndroid Build Coastguard Worker     /// These increase serialization time but decrease the size of the resulting buffer. By
82*890232f2SAndroid Build Coastguard Worker     /// default, `SHARE_KEYS`. You may wish to turn on `SHARE_STRINGS` if you know your data has
83*890232f2SAndroid Build Coastguard Worker     /// many duplicate strings or `SHARE_KEY_VECTORS` if your data has many maps with identical
84*890232f2SAndroid Build Coastguard Worker     /// keys.
85*890232f2SAndroid Build Coastguard Worker     ///
86*890232f2SAndroid Build Coastguard Worker     /// ## Not Yet Implemented
87*890232f2SAndroid Build Coastguard Worker     /// - `SHARE_STRINGS`
88*890232f2SAndroid Build Coastguard Worker     /// - `SHARE_KEY_VECTORS`
89*890232f2SAndroid Build Coastguard Worker     pub struct BuilderOptions: u8 {
90*890232f2SAndroid Build Coastguard Worker         const SHARE_NONE = 0;
91*890232f2SAndroid Build Coastguard Worker         const SHARE_KEYS = 1;
92*890232f2SAndroid Build Coastguard Worker         const SHARE_STRINGS = 2;
93*890232f2SAndroid Build Coastguard Worker         const SHARE_KEYS_AND_STRINGS = 3;
94*890232f2SAndroid Build Coastguard Worker         const SHARE_KEY_VECTORS = 4;
95*890232f2SAndroid Build Coastguard Worker         const SHARE_ALL = 7;
96*890232f2SAndroid Build Coastguard Worker     }
97*890232f2SAndroid Build Coastguard Worker }
98*890232f2SAndroid Build Coastguard Worker impl Default for BuilderOptions {
default() -> Self99*890232f2SAndroid Build Coastguard Worker     fn default() -> Self {
100*890232f2SAndroid Build Coastguard Worker         Self::SHARE_KEYS
101*890232f2SAndroid Build Coastguard Worker     }
102*890232f2SAndroid Build Coastguard Worker }
103*890232f2SAndroid Build Coastguard Worker 
104*890232f2SAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy)]
105*890232f2SAndroid Build Coastguard Worker // Address of a Key inside of the buffer.
106*890232f2SAndroid Build Coastguard Worker struct CachedKey(usize);
107*890232f2SAndroid Build Coastguard Worker 
108*890232f2SAndroid Build Coastguard Worker /// **Use this struct to build a Flexbuffer.**
109*890232f2SAndroid Build Coastguard Worker ///
110*890232f2SAndroid Build Coastguard Worker /// Flexbuffers may only have a single root value, which may be constructed
111*890232f2SAndroid Build Coastguard Worker /// with  one of the following functions.
112*890232f2SAndroid Build Coastguard Worker /// * `build_singleton` will push 1 value to the buffer and serialize it as the root.
113*890232f2SAndroid Build Coastguard Worker /// * `start_vector` returns a `VectorBuilder`, into which many (potentially
114*890232f2SAndroid Build Coastguard Worker /// heterogenous) values can be pushed. The vector itself is the root and is serialized
115*890232f2SAndroid Build Coastguard Worker /// when the `VectorBuilder` is dropped (or `end` is called).
116*890232f2SAndroid Build Coastguard Worker /// * `start_map` returns a `MapBuilder`, which is similar to a `VectorBuilder` except
117*890232f2SAndroid Build Coastguard Worker /// every value must be pushed with an associated key. The map is serialized when the
118*890232f2SAndroid Build Coastguard Worker /// `MapBuilder` is dropped (or `end` is called).
119*890232f2SAndroid Build Coastguard Worker ///
120*890232f2SAndroid Build Coastguard Worker /// These functions reset and overwrite the Builder which means, while there are no
121*890232f2SAndroid Build Coastguard Worker /// active `MapBuilder` or `VectorBuilder`, the internal buffer is empty or contains a
122*890232f2SAndroid Build Coastguard Worker /// finished Flexbuffer. The internal buffer is accessed with `view`.
123*890232f2SAndroid Build Coastguard Worker #[derive(Debug, Clone)]
124*890232f2SAndroid Build Coastguard Worker pub struct Builder {
125*890232f2SAndroid Build Coastguard Worker     buffer: Vec<u8>,
126*890232f2SAndroid Build Coastguard Worker     values: Vec<Value>,
127*890232f2SAndroid Build Coastguard Worker     key_pool: Option<Vec<CachedKey>>,
128*890232f2SAndroid Build Coastguard Worker }
129*890232f2SAndroid Build Coastguard Worker impl Default for Builder {
default() -> Self130*890232f2SAndroid Build Coastguard Worker     fn default() -> Self {
131*890232f2SAndroid Build Coastguard Worker         let opts = Default::default();
132*890232f2SAndroid Build Coastguard Worker         Builder::new(opts)
133*890232f2SAndroid Build Coastguard Worker     }
134*890232f2SAndroid Build Coastguard Worker }
135*890232f2SAndroid Build Coastguard Worker 
136*890232f2SAndroid Build Coastguard Worker impl<'a> Builder {
new(opts: BuilderOptions) -> Self137*890232f2SAndroid Build Coastguard Worker     pub fn new(opts: BuilderOptions) -> Self {
138*890232f2SAndroid Build Coastguard Worker         let key_pool = if opts.contains(BuilderOptions::SHARE_KEYS) {
139*890232f2SAndroid Build Coastguard Worker             Some(vec![])
140*890232f2SAndroid Build Coastguard Worker         } else {
141*890232f2SAndroid Build Coastguard Worker             None
142*890232f2SAndroid Build Coastguard Worker         };
143*890232f2SAndroid Build Coastguard Worker         Builder {
144*890232f2SAndroid Build Coastguard Worker             key_pool,
145*890232f2SAndroid Build Coastguard Worker             values: Vec::new(),
146*890232f2SAndroid Build Coastguard Worker             buffer: Vec::new(),
147*890232f2SAndroid Build Coastguard Worker         }
148*890232f2SAndroid Build Coastguard Worker     }
149*890232f2SAndroid Build Coastguard Worker     /// Shows the internal flexbuffer. It will either be empty or populated with the most
150*890232f2SAndroid Build Coastguard Worker     /// recently built flexbuffer.
view(&self) -> &[u8]151*890232f2SAndroid Build Coastguard Worker     pub fn view(&self) -> &[u8] {
152*890232f2SAndroid Build Coastguard Worker         &self.buffer
153*890232f2SAndroid Build Coastguard Worker     }
154*890232f2SAndroid Build Coastguard Worker     /// Returns the internal buffer, replacing it with a new vector. The returned buffer will
155*890232f2SAndroid Build Coastguard Worker     /// either be empty or populated with the most recently built flexbuffer.
take_buffer(&mut self) -> Vec<u8>156*890232f2SAndroid Build Coastguard Worker     pub fn take_buffer(&mut self) -> Vec<u8> {
157*890232f2SAndroid Build Coastguard Worker         let mut b = Vec::new();
158*890232f2SAndroid Build Coastguard Worker         std::mem::swap(&mut self.buffer, &mut b);
159*890232f2SAndroid Build Coastguard Worker         b
160*890232f2SAndroid Build Coastguard Worker     }
161*890232f2SAndroid Build Coastguard Worker     /// Resets the internal state. Automatically called before building a new flexbuffer.
reset(&mut self)162*890232f2SAndroid Build Coastguard Worker     pub fn reset(&mut self) {
163*890232f2SAndroid Build Coastguard Worker         self.buffer.clear();
164*890232f2SAndroid Build Coastguard Worker         self.values.clear();
165*890232f2SAndroid Build Coastguard Worker         if let Some(pool) = self.key_pool.as_mut() {
166*890232f2SAndroid Build Coastguard Worker             pool.clear();
167*890232f2SAndroid Build Coastguard Worker         }
168*890232f2SAndroid Build Coastguard Worker     }
push_key(&mut self, key: &str)169*890232f2SAndroid Build Coastguard Worker     fn push_key(&mut self, key: &str) {
170*890232f2SAndroid Build Coastguard Worker         debug_assert!(
171*890232f2SAndroid Build Coastguard Worker             key.bytes().all(|b| b != b'\0'),
172*890232f2SAndroid Build Coastguard Worker             "Keys must not have internal nulls."
173*890232f2SAndroid Build Coastguard Worker         );
174*890232f2SAndroid Build Coastguard Worker         // Search key pool if there is one.
175*890232f2SAndroid Build Coastguard Worker         let found = self.key_pool.as_ref().map(|pool| {
176*890232f2SAndroid Build Coastguard Worker             pool.binary_search_by(|&CachedKey(addr)| {
177*890232f2SAndroid Build Coastguard Worker                 let old_key = map::get_key(&self.buffer, addr);
178*890232f2SAndroid Build Coastguard Worker                 old_key.cloned().cmp(key.bytes())
179*890232f2SAndroid Build Coastguard Worker             })
180*890232f2SAndroid Build Coastguard Worker         });
181*890232f2SAndroid Build Coastguard Worker         let address = if let Some(Ok(idx)) = found {
182*890232f2SAndroid Build Coastguard Worker             // Found key in key pool.
183*890232f2SAndroid Build Coastguard Worker             self.key_pool.as_ref().unwrap()[idx].0
184*890232f2SAndroid Build Coastguard Worker         } else {
185*890232f2SAndroid Build Coastguard Worker             // Key not in pool (or no pool).
186*890232f2SAndroid Build Coastguard Worker             let address = self.buffer.len();
187*890232f2SAndroid Build Coastguard Worker             self.buffer.extend_from_slice(key.as_bytes());
188*890232f2SAndroid Build Coastguard Worker             self.buffer.push(b'\0');
189*890232f2SAndroid Build Coastguard Worker             address
190*890232f2SAndroid Build Coastguard Worker         };
191*890232f2SAndroid Build Coastguard Worker         if let Some(Err(idx)) = found {
192*890232f2SAndroid Build Coastguard Worker             // Insert into key pool.
193*890232f2SAndroid Build Coastguard Worker             let pool = self.key_pool.as_mut().unwrap();
194*890232f2SAndroid Build Coastguard Worker             pool.insert(idx, CachedKey(address));
195*890232f2SAndroid Build Coastguard Worker         }
196*890232f2SAndroid Build Coastguard Worker         self.values.push(Value::Key(address));
197*890232f2SAndroid Build Coastguard Worker     }
push_uint<T: Into<u64>>(&mut self, x: T)198*890232f2SAndroid Build Coastguard Worker     fn push_uint<T: Into<u64>>(&mut self, x: T) {
199*890232f2SAndroid Build Coastguard Worker         self.values.push(Value::UInt(x.into()));
200*890232f2SAndroid Build Coastguard Worker     }
push_int<T: Into<i64>>(&mut self, x: T)201*890232f2SAndroid Build Coastguard Worker     fn push_int<T: Into<i64>>(&mut self, x: T) {
202*890232f2SAndroid Build Coastguard Worker         self.values.push(Value::Int(x.into()));
203*890232f2SAndroid Build Coastguard Worker     }
push_float<T: Into<f64>>(&mut self, x: T)204*890232f2SAndroid Build Coastguard Worker     fn push_float<T: Into<f64>>(&mut self, x: T) {
205*890232f2SAndroid Build Coastguard Worker         self.values.push(Value::Float(x.into()));
206*890232f2SAndroid Build Coastguard Worker     }
push_null(&mut self)207*890232f2SAndroid Build Coastguard Worker     fn push_null(&mut self) {
208*890232f2SAndroid Build Coastguard Worker         self.values.push(Value::Null);
209*890232f2SAndroid Build Coastguard Worker     }
push_bool(&mut self, x: bool)210*890232f2SAndroid Build Coastguard Worker     fn push_bool(&mut self, x: bool) {
211*890232f2SAndroid Build Coastguard Worker         self.values.push(Value::Bool(x));
212*890232f2SAndroid Build Coastguard Worker     }
store_blob(&mut self, xs: &[u8]) -> Value213*890232f2SAndroid Build Coastguard Worker     fn store_blob(&mut self, xs: &[u8]) -> Value {
214*890232f2SAndroid Build Coastguard Worker         let length = Value::UInt(xs.len() as u64);
215*890232f2SAndroid Build Coastguard Worker         let width = length.width_or_child_width();
216*890232f2SAndroid Build Coastguard Worker         align(&mut self.buffer, width);
217*890232f2SAndroid Build Coastguard Worker         store_value(&mut self.buffer, length, width);
218*890232f2SAndroid Build Coastguard Worker         let address = self.buffer.len();
219*890232f2SAndroid Build Coastguard Worker         self.buffer.extend_from_slice(xs);
220*890232f2SAndroid Build Coastguard Worker         Value::Reference {
221*890232f2SAndroid Build Coastguard Worker             fxb_type: FlexBufferType::Blob,
222*890232f2SAndroid Build Coastguard Worker             address,
223*890232f2SAndroid Build Coastguard Worker             child_width: width,
224*890232f2SAndroid Build Coastguard Worker         }
225*890232f2SAndroid Build Coastguard Worker     }
push_str(&mut self, x: &str)226*890232f2SAndroid Build Coastguard Worker     fn push_str(&mut self, x: &str) {
227*890232f2SAndroid Build Coastguard Worker         let mut string = self.store_blob(x.as_bytes());
228*890232f2SAndroid Build Coastguard Worker         self.buffer.push(b'\0');
229*890232f2SAndroid Build Coastguard Worker         string.set_fxb_type_or_panic(FlexBufferType::String);
230*890232f2SAndroid Build Coastguard Worker         self.values.push(string);
231*890232f2SAndroid Build Coastguard Worker     }
push_blob(&mut self, x: &[u8])232*890232f2SAndroid Build Coastguard Worker     fn push_blob(&mut self, x: &[u8]) {
233*890232f2SAndroid Build Coastguard Worker         let blob = self.store_blob(x);
234*890232f2SAndroid Build Coastguard Worker         self.values.push(blob);
235*890232f2SAndroid Build Coastguard Worker     }
push_bools(&mut self, xs: &[bool])236*890232f2SAndroid Build Coastguard Worker     fn push_bools(&mut self, xs: &[bool]) {
237*890232f2SAndroid Build Coastguard Worker         let length = Value::UInt(xs.len() as u64);
238*890232f2SAndroid Build Coastguard Worker         let width = length.width_or_child_width();
239*890232f2SAndroid Build Coastguard Worker         align(&mut self.buffer, width);
240*890232f2SAndroid Build Coastguard Worker         store_value(&mut self.buffer, length, width);
241*890232f2SAndroid Build Coastguard Worker         let address = self.buffer.len();
242*890232f2SAndroid Build Coastguard Worker         for &b in xs.iter() {
243*890232f2SAndroid Build Coastguard Worker             self.buffer.push(b as u8);
244*890232f2SAndroid Build Coastguard Worker             self.buffer.resize(self.buffer.len() + width as usize, 0);
245*890232f2SAndroid Build Coastguard Worker         }
246*890232f2SAndroid Build Coastguard Worker         self.values.push(Value::Reference {
247*890232f2SAndroid Build Coastguard Worker             fxb_type: FlexBufferType::VectorBool,
248*890232f2SAndroid Build Coastguard Worker             address,
249*890232f2SAndroid Build Coastguard Worker             child_width: width,
250*890232f2SAndroid Build Coastguard Worker         });
251*890232f2SAndroid Build Coastguard Worker     }
252*890232f2SAndroid Build Coastguard Worker 
253*890232f2SAndroid Build Coastguard Worker     push_slice!(push_uints, u64, UInt, new_uint_vector);
254*890232f2SAndroid Build Coastguard Worker     push_slice!(push_ints, i64, Int, new_int_vector);
255*890232f2SAndroid Build Coastguard Worker     push_slice!(push_floats, f64, Float, new_float_vector);
256*890232f2SAndroid Build Coastguard Worker     push_indirect!(push_indirect_int, i64, Int, IndirectInt);
257*890232f2SAndroid Build Coastguard Worker     push_indirect!(push_indirect_uint, u64, UInt, IndirectUInt);
258*890232f2SAndroid Build Coastguard Worker     push_indirect!(push_indirect_float, f64, Float, IndirectFloat);
259*890232f2SAndroid Build Coastguard Worker 
260*890232f2SAndroid Build Coastguard Worker     /// Resets the builder and starts a new flexbuffer with a vector at the root.
261*890232f2SAndroid Build Coastguard Worker     /// The exact Flexbuffer vector type is dynamically inferred.
start_vector(&'a mut self) -> VectorBuilder<'a>262*890232f2SAndroid Build Coastguard Worker     pub fn start_vector(&'a mut self) -> VectorBuilder<'a> {
263*890232f2SAndroid Build Coastguard Worker         self.reset();
264*890232f2SAndroid Build Coastguard Worker         VectorBuilder {
265*890232f2SAndroid Build Coastguard Worker             builder: self,
266*890232f2SAndroid Build Coastguard Worker             start: None,
267*890232f2SAndroid Build Coastguard Worker         }
268*890232f2SAndroid Build Coastguard Worker     }
269*890232f2SAndroid Build Coastguard Worker     /// Resets the builder and builds a new flexbuffer with a map at the root.
start_map(&'a mut self) -> MapBuilder<'a>270*890232f2SAndroid Build Coastguard Worker     pub fn start_map(&'a mut self) -> MapBuilder<'a> {
271*890232f2SAndroid Build Coastguard Worker         self.reset();
272*890232f2SAndroid Build Coastguard Worker         MapBuilder {
273*890232f2SAndroid Build Coastguard Worker             builder: self,
274*890232f2SAndroid Build Coastguard Worker             start: None,
275*890232f2SAndroid Build Coastguard Worker         }
276*890232f2SAndroid Build Coastguard Worker     }
277*890232f2SAndroid Build Coastguard Worker     /// Resets the builder and builds a new flexbuffer with the pushed value at the root.
build_singleton<P: Pushable>(&mut self, p: P)278*890232f2SAndroid Build Coastguard Worker     pub fn build_singleton<P: Pushable>(&mut self, p: P) {
279*890232f2SAndroid Build Coastguard Worker         self.reset();
280*890232f2SAndroid Build Coastguard Worker         p.push_to_builder(self);
281*890232f2SAndroid Build Coastguard Worker         let root = self.values.pop().unwrap();
282*890232f2SAndroid Build Coastguard Worker         store_root(&mut self.buffer, root);
283*890232f2SAndroid Build Coastguard Worker     }
push<P: Pushable>(&mut self, p: P)284*890232f2SAndroid Build Coastguard Worker     fn push<P: Pushable>(&mut self, p: P) {
285*890232f2SAndroid Build Coastguard Worker         p.push_to_builder(self);
286*890232f2SAndroid Build Coastguard Worker     }
287*890232f2SAndroid Build Coastguard Worker     /// Stores the values past `previous_end` as a map or vector depending on `is_map`.
288*890232f2SAndroid Build Coastguard Worker     /// If `previous_end` is None then this was a root map / vector and the last value
289*890232f2SAndroid Build Coastguard Worker     /// is stored as the root.
end_map_or_vector(&mut self, is_map: bool, previous_end: Option<usize>)290*890232f2SAndroid Build Coastguard Worker     fn end_map_or_vector(&mut self, is_map: bool, previous_end: Option<usize>) {
291*890232f2SAndroid Build Coastguard Worker         let split = previous_end.unwrap_or(0);
292*890232f2SAndroid Build Coastguard Worker         let value = if is_map {
293*890232f2SAndroid Build Coastguard Worker             let key_vals = &mut self.values[split..];
294*890232f2SAndroid Build Coastguard Worker             sort_map_by_keys(key_vals, &self.buffer);
295*890232f2SAndroid Build Coastguard Worker             let key_vector = store_vector(&mut self.buffer, key_vals, StoreOption::MapKeys);
296*890232f2SAndroid Build Coastguard Worker             store_vector(&mut self.buffer, key_vals, StoreOption::Map(key_vector))
297*890232f2SAndroid Build Coastguard Worker         } else {
298*890232f2SAndroid Build Coastguard Worker             store_vector(&mut self.buffer, &self.values[split..], StoreOption::Vector)
299*890232f2SAndroid Build Coastguard Worker         };
300*890232f2SAndroid Build Coastguard Worker         self.values.truncate(split);
301*890232f2SAndroid Build Coastguard Worker         if previous_end.is_some() {
302*890232f2SAndroid Build Coastguard Worker             self.values.push(value);
303*890232f2SAndroid Build Coastguard Worker         } else {
304*890232f2SAndroid Build Coastguard Worker             store_root(&mut self.buffer, value);
305*890232f2SAndroid Build Coastguard Worker         }
306*890232f2SAndroid Build Coastguard Worker     }
307*890232f2SAndroid Build Coastguard Worker }
308*890232f2SAndroid Build Coastguard Worker 
309*890232f2SAndroid Build Coastguard Worker /// Builds a Flexbuffer with the single pushed value as the root.
singleton<P: Pushable>(p: P) -> Vec<u8>310*890232f2SAndroid Build Coastguard Worker pub fn singleton<P: Pushable>(p: P) -> Vec<u8> {
311*890232f2SAndroid Build Coastguard Worker     let mut b = Builder::default();
312*890232f2SAndroid Build Coastguard Worker     b.build_singleton(p);
313*890232f2SAndroid Build Coastguard Worker     let Builder { buffer, .. } = b;
314*890232f2SAndroid Build Coastguard Worker     buffer
315*890232f2SAndroid Build Coastguard Worker }
316*890232f2SAndroid Build Coastguard Worker 
317*890232f2SAndroid Build Coastguard Worker /// Stores the root value, root type and root width.
318*890232f2SAndroid Build Coastguard Worker /// This should be called to finish the Flexbuffer.
store_root(buffer: &mut Vec<u8>, root: Value)319*890232f2SAndroid Build Coastguard Worker fn store_root(buffer: &mut Vec<u8>, root: Value) {
320*890232f2SAndroid Build Coastguard Worker     let root_width = root.width_in_vector(buffer.len(), 0);
321*890232f2SAndroid Build Coastguard Worker     align(buffer, root_width);
322*890232f2SAndroid Build Coastguard Worker     store_value(buffer, root, root_width);
323*890232f2SAndroid Build Coastguard Worker     buffer.push(root.packed_type(root_width));
324*890232f2SAndroid Build Coastguard Worker     buffer.push(root_width.n_bytes() as u8);
325*890232f2SAndroid Build Coastguard Worker }
326*890232f2SAndroid Build Coastguard Worker 
327*890232f2SAndroid Build Coastguard Worker pub enum StoreOption {
328*890232f2SAndroid Build Coastguard Worker     Vector,
329*890232f2SAndroid Build Coastguard Worker     Map(Value),
330*890232f2SAndroid Build Coastguard Worker     MapKeys,
331*890232f2SAndroid Build Coastguard Worker }
332*890232f2SAndroid Build Coastguard Worker /// Writes a Flexbuffer Vector or Map.
333*890232f2SAndroid Build Coastguard Worker /// StoreOption::Map(Keys) must be a Value::Key or this will panic.
334*890232f2SAndroid Build Coastguard Worker // #[inline(always)]
store_vector(buffer: &mut Vec<u8>, values: &[Value], opt: StoreOption) -> Value335*890232f2SAndroid Build Coastguard Worker pub fn store_vector(buffer: &mut Vec<u8>, values: &[Value], opt: StoreOption) -> Value {
336*890232f2SAndroid Build Coastguard Worker     let (skip, stride) = match opt {
337*890232f2SAndroid Build Coastguard Worker         StoreOption::Vector => (0, 1),
338*890232f2SAndroid Build Coastguard Worker         StoreOption::MapKeys => (0, 2),
339*890232f2SAndroid Build Coastguard Worker         StoreOption::Map(_) => (1, 2),
340*890232f2SAndroid Build Coastguard Worker     };
341*890232f2SAndroid Build Coastguard Worker     let iter_values = || values.iter().skip(skip).step_by(stride);
342*890232f2SAndroid Build Coastguard Worker 
343*890232f2SAndroid Build Coastguard Worker     // Figure out vector type and how long is the prefix.
344*890232f2SAndroid Build Coastguard Worker     let mut result = if let StoreOption::Map(_) = opt {
345*890232f2SAndroid Build Coastguard Worker         Value::new_map()
346*890232f2SAndroid Build Coastguard Worker     } else {
347*890232f2SAndroid Build Coastguard Worker         find_vector_type(iter_values())
348*890232f2SAndroid Build Coastguard Worker     };
349*890232f2SAndroid Build Coastguard Worker     let length_slot = if !result.is_fixed_length_vector() {
350*890232f2SAndroid Build Coastguard Worker         let length = iter_values().count();
351*890232f2SAndroid Build Coastguard Worker         Some(Value::UInt(length as u64))
352*890232f2SAndroid Build Coastguard Worker     } else {
353*890232f2SAndroid Build Coastguard Worker         None
354*890232f2SAndroid Build Coastguard Worker     };
355*890232f2SAndroid Build Coastguard Worker     // Measure required width and align to it.
356*890232f2SAndroid Build Coastguard Worker     let mut width = BitWidth::W8;
357*890232f2SAndroid Build Coastguard Worker     if let StoreOption::Map(keys) = opt {
358*890232f2SAndroid Build Coastguard Worker         width = max(width, keys.width_in_vector(buffer.len(), 0))
359*890232f2SAndroid Build Coastguard Worker     }
360*890232f2SAndroid Build Coastguard Worker     if let Some(l) = length_slot {
361*890232f2SAndroid Build Coastguard Worker         width = max(width, l.width_or_child_width());
362*890232f2SAndroid Build Coastguard Worker     }
363*890232f2SAndroid Build Coastguard Worker     let prefix_length = result.prefix_length();
364*890232f2SAndroid Build Coastguard Worker     for (i, &val) in iter_values().enumerate() {
365*890232f2SAndroid Build Coastguard Worker         width = max(width, val.width_in_vector(buffer.len(), i + prefix_length));
366*890232f2SAndroid Build Coastguard Worker     }
367*890232f2SAndroid Build Coastguard Worker     align(buffer, width);
368*890232f2SAndroid Build Coastguard Worker     #[allow(deprecated)]
369*890232f2SAndroid Build Coastguard Worker     {
370*890232f2SAndroid Build Coastguard Worker         debug_assert_ne!(
371*890232f2SAndroid Build Coastguard Worker             result.fxb_type(),
372*890232f2SAndroid Build Coastguard Worker             FlexBufferType::VectorString,
373*890232f2SAndroid Build Coastguard Worker             "VectorString is deprecated and cannot be written.\
374*890232f2SAndroid Build Coastguard Worker              (https://github.com/google/flatbuffers/issues/5627)"
375*890232f2SAndroid Build Coastguard Worker         );
376*890232f2SAndroid Build Coastguard Worker     }
377*890232f2SAndroid Build Coastguard Worker     // Write Prefix.
378*890232f2SAndroid Build Coastguard Worker     if let StoreOption::Map(keys) = opt {
379*890232f2SAndroid Build Coastguard Worker         let key_width = Value::UInt(keys.width_or_child_width().n_bytes() as u64);
380*890232f2SAndroid Build Coastguard Worker         store_value(buffer, keys, width);
381*890232f2SAndroid Build Coastguard Worker         store_value(buffer, key_width, width);
382*890232f2SAndroid Build Coastguard Worker     }
383*890232f2SAndroid Build Coastguard Worker     if let Some(len) = length_slot {
384*890232f2SAndroid Build Coastguard Worker         store_value(buffer, len, width);
385*890232f2SAndroid Build Coastguard Worker     }
386*890232f2SAndroid Build Coastguard Worker     // Write data.
387*890232f2SAndroid Build Coastguard Worker     let address = buffer.len();
388*890232f2SAndroid Build Coastguard Worker     for &v in iter_values() {
389*890232f2SAndroid Build Coastguard Worker         store_value(buffer, v, width);
390*890232f2SAndroid Build Coastguard Worker     }
391*890232f2SAndroid Build Coastguard Worker     // Write types
392*890232f2SAndroid Build Coastguard Worker     if result.is_typed_vector_or_map() {
393*890232f2SAndroid Build Coastguard Worker         for v in iter_values() {
394*890232f2SAndroid Build Coastguard Worker             buffer.push(v.packed_type(width));
395*890232f2SAndroid Build Coastguard Worker         }
396*890232f2SAndroid Build Coastguard Worker     }
397*890232f2SAndroid Build Coastguard Worker     // Return Value representing this Vector.
398*890232f2SAndroid Build Coastguard Worker     result.set_address_or_panic(address);
399*890232f2SAndroid Build Coastguard Worker     result.set_child_width_or_panic(width);
400*890232f2SAndroid Build Coastguard Worker     result
401*890232f2SAndroid Build Coastguard Worker }
402