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