blob: 4a3f472d23fbd45d7179a992c3632c381fc2d2b7 [file] [log] [blame]
Austin Schuh272c6132020-11-14 16:37:52 -08001// 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
15use crate::bitwidth::BitWidth;
16use crate::flexbuffer_type::FlexBufferType;
17use crate::Blob;
18use std::convert::{TryFrom, TryInto};
19use std::fmt;
20use std::ops::Rem;
21use std::str::FromStr;
22mod de;
23mod iter;
24mod map;
25mod vector;
26pub use de::DeserializationError;
27pub use iter::ReaderIterator;
28pub use map::{MapReader, MapReaderIndexer};
29pub use vector::VectorReader;
30
31/// All the possible errors when reading a flexbuffer.
32#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
33pub enum Error {
34 /// One of the following data errors occured:
35 ///
36 /// * The read flexbuffer had an offset that pointed outside the flexbuffer.
37 /// * The 'negative indicies' where length and map keys are stored were out of bounds
38 /// * The buffer was too small to contain a flexbuffer root.
39 FlexbufferOutOfBounds,
40 /// Failed to parse a valid FlexbufferType and Bitwidth from a type byte.
41 InvalidPackedType,
42 /// Flexbuffer type of the read data does not match function used.
43 UnexpectedFlexbufferType {
44 expected: FlexBufferType,
45 actual: FlexBufferType,
46 },
47 /// BitWidth type of the read data does not match function used.
48 UnexpectedBitWidth {
49 expected: BitWidth,
50 actual: BitWidth,
51 },
52 /// Read a flexbuffer offset or length that overflowed usize.
53 ReadUsizeOverflowed,
54 /// Tried to index a type that's not one of the Flexbuffer vector types.
55 CannotIndexAsVector,
56 /// Tried to index a Flexbuffer vector or map out of bounds.
57 IndexOutOfBounds,
58 /// A Map was indexed with a key that it did not contain.
59 KeyNotFound,
60 /// Failed to parse a Utf8 string.
61 /// The Option will be `None` if and only if this Error was deserialized.
62 // NOTE: std::str::Utf8Error does not implement Serialize, Deserialize, nor Default. We tell
63 // serde to skip the field and default to None. We prefer to have the boxed error so it can be
64 // used with std::error::Error::source, though another (worse) option could be to drop that
65 // information.
66 Utf8Error(#[serde(skip)] Option<Box<std::str::Utf8Error>>),
67 /// get_slice failed because the given data buffer is misaligned.
68 AlignmentError,
69 InvalidRootWidth,
70 InvalidMapKeysVectorWidth,
71}
72impl std::convert::From<std::str::Utf8Error> for Error {
73 fn from(e: std::str::Utf8Error) -> Self {
74 Self::Utf8Error(Some(Box::new(e)))
75 }
76}
77impl fmt::Display for Error {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 match self {
80 Self::UnexpectedBitWidth { expected, actual } => write!(
81 f,
82 "Error reading flexbuffer: Expected bitwidth: {:?}, found bitwidth: {:?}",
83 expected, actual
84 ),
85 Self::UnexpectedFlexbufferType { expected, actual } => write!(
86 f,
87 "Error reading flexbuffer: Expected type: {:?}, found type: {:?}",
88 expected, actual
89 ),
90 _ => write!(f, "Error reading flexbuffer: {:?}", self),
91 }
92 }
93}
94impl std::error::Error for Error {
95 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
96 if let Self::Utf8Error(Some(e)) = self {
97 Some(e)
98 } else {
99 None
100 }
101 }
102}
103
104pub trait ReadLE: crate::private::Sealed + std::marker::Sized {
105 const VECTOR_TYPE: FlexBufferType;
106 const WIDTH: BitWidth;
107}
108macro_rules! rle {
109 ($T: ty, $VECTOR_TYPE: ident, $WIDTH: ident) => {
110 impl ReadLE for $T {
111 const VECTOR_TYPE: FlexBufferType = FlexBufferType::$VECTOR_TYPE;
112 const WIDTH: BitWidth = BitWidth::$WIDTH;
113 }
114 };
115}
116rle!(u8, VectorUInt, W8);
117rle!(u16, VectorUInt, W16);
118rle!(u32, VectorUInt, W32);
119rle!(u64, VectorUInt, W64);
120rle!(i8, VectorInt, W8);
121rle!(i16, VectorInt, W16);
122rle!(i32, VectorInt, W32);
123rle!(i64, VectorInt, W64);
124rle!(f32, VectorFloat, W32);
125rle!(f64, VectorFloat, W64);
126
127macro_rules! as_default {
128 ($as: ident, $get: ident, $T: ty) => {
129 pub fn $as(&self) -> $T {
130 self.$get().unwrap_or_default()
131 }
132 };
133}
134
135/// `Reader`s allow access to data stored in a Flexbuffer.
136///
137/// Each reader represents a single address in the buffer so data is read lazily. Start a reader
138/// by calling `get_root` on your flexbuffer `&[u8]`.
139///
140/// - The `get_T` methods return a `Result<T, Error>`. They return an OK value if and only if the
141/// flexbuffer type matches `T`. This is analogous to the behavior of Rust's json library, though
142/// with Result instead of Option.
143/// - The `as_T` methods will try their best to return to a value of type `T`
144/// (by casting or even parsing a string if necessary) but ultimately returns `T::default` if it
145/// fails. This behavior is analogous to that of flexbuffers C++.
146#[derive(Default, Clone)]
147pub struct Reader<'de> {
148 fxb_type: FlexBufferType,
149 width: BitWidth,
150 address: usize,
151 buffer: &'de [u8],
152}
153
154// manual implementation of Debug because buffer slice can't be automatically displayed
155impl<'de> std::fmt::Debug for Reader<'de> {
156 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
157 // skips buffer field
158 f.debug_struct("Reader")
159 .field("fxb_type", &self.fxb_type)
160 .field("width", &self.width)
161 .field("address", &self.address)
162 .finish()
163 }
164}
165
166
167macro_rules! try_cast_fn {
168 ($name: ident, $full_width: ident, $Ty: ident) => {
169 pub fn $name(&self) -> $Ty {
170 self.$full_width().try_into().unwrap_or_default()
171 }
172 }
173}
174
175fn safe_sub(a: usize, b: usize) -> Result<usize, Error> {
176 a.checked_sub(b).ok_or(Error::FlexbufferOutOfBounds)
177}
178
179fn deref_offset(buffer: &[u8], address: usize, width: BitWidth) -> Result<usize, Error> {
180 let off = read_usize(buffer, address, width);
181 safe_sub(address, off)
182}
183
184impl<'de> Reader<'de> {
185 fn new(
186 buffer: &'de [u8],
187 mut address: usize,
188 mut fxb_type: FlexBufferType,
189 width: BitWidth,
190 parent_width: BitWidth,
191 ) -> Result<Self, Error> {
192 if fxb_type.is_reference() {
193 address = deref_offset(buffer, address, parent_width)?;
194 // Indirects were dereferenced.
195 if let Some(t) = fxb_type.to_direct() {
196 fxb_type = t;
197 }
198 }
199 Ok(Reader {
200 address,
201 fxb_type,
202 width,
203 buffer,
204 })
205 }
206 /// Parses the flexbuffer from the given buffer. Assumes the flexbuffer root is the last byte
207 /// of the buffer.
208 pub fn get_root(buffer: &'de [u8]) -> Result<Self, Error> {
209 let end = buffer.len();
210 if end < 3 {
211 return Err(Error::FlexbufferOutOfBounds);
212 }
213 // Last byte is the root width.
214 let root_width = BitWidth::from_nbytes(buffer[end - 1]).ok_or(Error::InvalidRootWidth)?;
215 // Second last byte is root type.
216 let (fxb_type, width) = unpack_type(buffer[end - 2])?;
217 // Location of root data. (BitWidth bits before root type)
218 let address = safe_sub(end - 2, root_width.n_bytes())?;
219 Self::new(buffer, address, fxb_type, width, root_width)
220 }
221 /// Returns the FlexBufferType of this Reader.
222 pub fn flexbuffer_type(&self) -> FlexBufferType {
223 self.fxb_type
224 }
225 /// Returns the bitwidth of this Reader.
226 pub fn bitwidth(&self) -> BitWidth {
227 self.width
228 }
229 /// Returns the length of the Flexbuffer. If the type has no length, or if an error occurs,
230 /// 0 is returned.
231 pub fn length(&self) -> usize {
232 if let Some(len) = self.fxb_type.fixed_length_vector_length() {
233 len
234 } else if self.fxb_type.has_length_slot() && self.address >= self.width.n_bytes() {
235 read_usize(self.buffer, self.address - self.width.n_bytes(), self.width)
236 } else {
237 0
238 }
239 }
240 /// Returns true if the flexbuffer is aligned to 8 bytes. This guarantees, for valid
241 /// flexbuffers, that the data is correctly aligned in memory and slices can be read directly
242 /// e.g. with `get_f64s` or `get_i16s`.
243 pub fn is_aligned(&self) -> bool {
244 (self.buffer.as_ptr() as usize).rem(8) == 0
245 }
246 as_default!(as_vector, get_vector, VectorReader<'de>);
247 as_default!(as_map, get_map, MapReader<'de>);
248
249 fn expect_type(&self, ty: FlexBufferType) -> Result<(), Error> {
250 if self.fxb_type == ty {
251 Ok(())
252 } else {
253 Err(Error::UnexpectedFlexbufferType {
254 expected: ty,
255 actual: self.fxb_type,
256 })
257 }
258 }
259 fn expect_bw(&self, bw: BitWidth) -> Result<(), Error> {
260 if self.width == bw {
261 Ok(())
262 } else {
263 Err(Error::UnexpectedBitWidth {
264 expected: bw,
265 actual: self.width,
266 })
267 }
268 }
269 /// Directly reads a slice of type `T`where `T` is one of `u8,u16,u32,u64,i8,i16,i32,i64,f32,f64`.
270 /// Returns Err if the type, bitwidth, or memory alignment does not match. Since the bitwidth is
271 /// dynamic, its better to use a VectorReader unless you know your data and performance is critical.
272 #[cfg(target_endian = "little")]
273 pub fn get_slice<T: ReadLE>(&self) -> Result<&'de [T], Error> {
274 if self.flexbuffer_type().typed_vector_type() != T::VECTOR_TYPE.typed_vector_type() {
275 self.expect_type(T::VECTOR_TYPE)?;
276 }
277 if self.bitwidth().n_bytes() != std::mem::size_of::<T>() {
278 self.expect_bw(T::WIDTH)?;
279 }
280 let end = self.address + self.length() * std::mem::size_of::<T>();
281 let slice = &self
282 .buffer
283 .get(self.address..end)
284 .ok_or(Error::FlexbufferOutOfBounds)?;
285 // `align_to` is required because the point of this function is to directly hand back a
286 // slice of scalars. This can fail because Rust's default allocator is not 16byte aligned
287 // (though in practice this only happens for small buffers).
288 let (pre, mid, suf) = unsafe { slice.align_to::<T>() };
289 if pre.is_empty() && suf.is_empty() {
290 Ok(mid)
291 } else {
292 Err(Error::AlignmentError)
293 }
294 }
295
296 pub fn get_bool(&self) -> Result<bool, Error> {
297 self.expect_type(FlexBufferType::Bool)?;
298 Ok(
299 self.buffer[self.address..self.address + self.width.n_bytes()]
300 .iter()
301 .any(|&b| b != 0),
302 )
303 }
304 pub fn get_key(&self) -> Result<&'de str, Error> {
305 self.expect_type(FlexBufferType::Key)?;
306 let (length, _) = self.buffer[self.address..]
307 .iter()
308 .enumerate()
309 .find(|(_, &b)| b == b'\0')
310 .unwrap_or((0, &0));
311 let bytes = &self.buffer[self.address..self.address + length];
312 Ok(std::str::from_utf8(bytes)?)
313 }
314 pub fn get_blob(&self) -> Result<Blob<'de>, Error> {
315 self.expect_type(FlexBufferType::Blob)?;
316 Ok(Blob(
317 &self.buffer[self.address..self.address + self.length()],
318 ))
319 }
320 pub fn as_blob(&self) -> Blob<'de> {
321 self.get_blob().unwrap_or(Blob(&[]))
322 }
323 pub fn get_str(&self) -> Result<&'de str, Error> {
324 self.expect_type(FlexBufferType::String)?;
325 let bytes = &self.buffer[self.address..self.address + self.length()];
326 Ok(std::str::from_utf8(bytes)?)
327 }
328 fn get_map_info(&self) -> Result<(usize, BitWidth), Error> {
329 self.expect_type(FlexBufferType::Map)?;
330 if 3 * self.width.n_bytes() >= self.address {
331 return Err(Error::FlexbufferOutOfBounds);
332 }
333 let keys_offset_address = self.address - 3 * self.width.n_bytes();
334 let keys_width = {
335 let kw_addr = self.address - 2 * self.width.n_bytes();
336 let kw = read_usize(self.buffer, kw_addr, self.width);
337 BitWidth::from_nbytes(kw).ok_or(Error::InvalidMapKeysVectorWidth)
338 }?;
339 Ok((keys_offset_address, keys_width))
340 }
341 pub fn get_map(&self) -> Result<MapReader<'de>, Error> {
342 let (keys_offset_address, keys_width) = self.get_map_info()?;
343 let keys_address = deref_offset(self.buffer, keys_offset_address, self.width)?;
344 // TODO(cneo): Check that vectors length equals keys length.
345 Ok(MapReader {
346 buffer: self.buffer,
347 values_address: self.address,
348 values_width: self.width,
349 keys_address,
350 keys_width,
351 length: self.length(),
352 })
353 }
354 /// Tries to read a FlexBufferType::UInt. Returns Err if the type is not a UInt or if the
355 /// address is out of bounds.
356 pub fn get_u64(&self) -> Result<u64, Error> {
357 self.expect_type(FlexBufferType::UInt)?;
358 let cursor = self
359 .buffer
360 .get(self.address..self.address + self.width.n_bytes());
361 match self.width {
362 BitWidth::W8 => cursor.map(|s| s[0] as u8).map(Into::into),
363 BitWidth::W16 => cursor
364 .and_then(|s| s.try_into().ok())
365 .map(<u16>::from_le_bytes)
366 .map(Into::into),
367 BitWidth::W32 => cursor
368 .and_then(|s| s.try_into().ok())
369 .map(<u32>::from_le_bytes)
370 .map(Into::into),
371 BitWidth::W64 => cursor
372 .and_then(|s| s.try_into().ok())
373 .map(<u64>::from_le_bytes),
374 }
375 .ok_or(Error::FlexbufferOutOfBounds)
376 }
377 /// Tries to read a FlexBufferType::Int. Returns Err if the type is not a UInt or if the
378 /// address is out of bounds.
379 pub fn get_i64(&self) -> Result<i64, Error> {
380 self.expect_type(FlexBufferType::Int)?;
381 let cursor = self
382 .buffer
383 .get(self.address..self.address + self.width.n_bytes());
384 match self.width {
385 BitWidth::W8 => cursor.map(|s| s[0] as i8).map(Into::into),
386 BitWidth::W16 => cursor
387 .and_then(|s| s.try_into().ok())
388 .map(<i16>::from_le_bytes)
389 .map(Into::into),
390 BitWidth::W32 => cursor
391 .and_then(|s| s.try_into().ok())
392 .map(<i32>::from_le_bytes)
393 .map(Into::into),
394 BitWidth::W64 => cursor
395 .and_then(|s| s.try_into().ok())
396 .map(<i64>::from_le_bytes),
397 }
398 .ok_or(Error::FlexbufferOutOfBounds)
399 }
400 /// Tries to read a FlexBufferType::Float. Returns Err if the type is not a UInt, if the
401 /// address is out of bounds, or if its a f16 or f8 (not currently supported).
402 pub fn get_f64(&self) -> Result<f64, Error> {
403 self.expect_type(FlexBufferType::Float)?;
404 let cursor = self
405 .buffer
406 .get(self.address..self.address + self.width.n_bytes());
407 match self.width {
408 BitWidth::W8 | BitWidth::W16 => return Err(Error::InvalidPackedType),
409 BitWidth::W32 => cursor
410 .and_then(|s| s.try_into().ok())
411 .map(f32_from_le_bytes)
412 .map(Into::into),
413 BitWidth::W64 => cursor
414 .and_then(|s| s.try_into().ok())
415 .map(f64_from_le_bytes),
416 }
417 .ok_or(Error::FlexbufferOutOfBounds)
418 }
419 pub fn as_bool(&self) -> bool {
420 use FlexBufferType::*;
421 match self.fxb_type {
422 Bool => self.get_bool().unwrap_or_default(),
423 UInt => self.as_u64() != 0,
424 Int => self.as_i64() != 0,
425 Float => self.as_f64().abs() > std::f64::EPSILON,
426 String | Key => !self.as_str().is_empty(),
427 Null => false,
428 Blob => self.length() != 0,
429 ty if ty.is_vector() => self.length() != 0,
430 _ => unreachable!(),
431 }
432 }
433 /// Returns a u64, casting if necessary. For Maps and Vectors, their length is
434 /// returned. If anything fails, 0 is returned.
435 pub fn as_u64(&self) -> u64 {
436 match self.fxb_type {
437 FlexBufferType::UInt => self.get_u64().unwrap_or_default(),
438 FlexBufferType::Int => self
439 .get_i64()
440 .unwrap_or_default()
441 .try_into()
442 .unwrap_or_default(),
443 FlexBufferType::Float => self.get_f64().unwrap_or_default() as u64,
444 FlexBufferType::String => {
445 if let Ok(s) = self.get_str() {
446 if let Ok(f) = u64::from_str(s) {
447 return f;
448 }
449 }
450 0
451 }
452 _ if self.fxb_type.is_vector() => self.length() as u64,
453 _ => 0,
454 }
455 }
456 try_cast_fn!(as_u32, as_u64, u32);
457 try_cast_fn!(as_u16, as_u64, u16);
458 try_cast_fn!(as_u8, as_u64, u8);
459
460 /// Returns an i64, casting if necessary. For Maps and Vectors, their length is
461 /// returned. If anything fails, 0 is returned.
462 pub fn as_i64(&self) -> i64 {
463 match self.fxb_type {
464 FlexBufferType::Int => self.get_i64().unwrap_or_default(),
465 FlexBufferType::UInt => self
466 .get_u64()
467 .unwrap_or_default()
468 .try_into()
469 .unwrap_or_default(),
470 FlexBufferType::Float => self.get_f64().unwrap_or_default() as i64,
471 FlexBufferType::String => {
472 if let Ok(s) = self.get_str() {
473 if let Ok(f) = i64::from_str(s) {
474 return f;
475 }
476 }
477 0
478 }
479 _ if self.fxb_type.is_vector() => self.length() as i64,
480 _ => 0,
481 }
482 }
483 try_cast_fn!(as_i32, as_i64, i32);
484 try_cast_fn!(as_i16, as_i64, i16);
485 try_cast_fn!(as_i8, as_i64, i8);
486
487 /// Returns an f64, casting if necessary. For Maps and Vectors, their length is
488 /// returned. If anything fails, 0 is returned.
489 pub fn as_f64(&self) -> f64 {
490 match self.fxb_type {
491 FlexBufferType::Int => self.get_i64().unwrap_or_default() as f64,
492 FlexBufferType::UInt => self.get_u64().unwrap_or_default() as f64,
493 FlexBufferType::Float => self.get_f64().unwrap_or_default(),
494 FlexBufferType::String => {
495 if let Ok(s) = self.get_str() {
496 if let Ok(f) = f64::from_str(s) {
497 return f;
498 }
499 }
500 0.0
501 }
502 _ if self.fxb_type.is_vector() => self.length() as f64,
503 _ => 0.0,
504 }
505 }
506 pub fn as_f32(&self) -> f32 {
507 self.as_f64() as f32
508 }
509
510 /// Returns empty string if you're not trying to read a string.
511 pub fn as_str(&self) -> &'de str {
512 match self.fxb_type {
513 FlexBufferType::String => self.get_str().unwrap_or_default(),
514 FlexBufferType::Key => self.get_key().unwrap_or_default(),
515 _ => "",
516 }
517 }
518 pub fn get_vector(&self) -> Result<VectorReader<'de>, Error> {
519 if !self.fxb_type.is_vector() {
520 self.expect_type(FlexBufferType::Vector)?;
521 };
522 Ok(VectorReader {
523 reader: self.clone(),
524 length: self.length(),
525 })
526 }
527}
528
529impl<'de> fmt::Display for Reader<'de> {
530 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
531 use FlexBufferType::*;
532 match self.flexbuffer_type() {
533 Null => write!(f, "null"),
534 UInt => write!(f, "{}", self.as_u64()),
535 Int => write!(f, "{}", self.as_i64()),
536 Float => write!(f, "{}", self.as_f64()),
537 Key | String => write!(f, "{:?}", self.as_str()),
538 Bool => write!(f, "{}", self.as_bool()),
539 Blob => write!(f, "blob"),
540 Map => {
541 write!(f, "{{")?;
542 let m = self.as_map();
543 let mut pairs = m.iter_keys().zip(m.iter_values());
544 if let Some((k, v)) = pairs.next() {
545 write!(f, "{:?}: {}", k, v)?;
546 for (k, v) in pairs {
547 write!(f, ", {:?}: {}", k, v)?;
548 }
549 }
550 write!(f, "}}")
551 }
552 t if t.is_vector() => {
553 write!(f, "[")?;
554 let mut elems = self.as_vector().iter();
555 if let Some(first) = elems.next() {
556 write!(f, "{}", first)?;
557 for e in elems {
558 write!(f, ", {}", e)?;
559 }
560 }
561 write!(f, "]")
562 }
563 _ => unreachable!("Display not implemented for {:?}", self),
564 }
565 }
566}
567
568// TODO(cneo): Use <f..>::from_le_bytes when we move past rustc 1.39.
569fn f32_from_le_bytes(bytes: [u8; 4]) -> f32 {
570 let bits = <u32>::from_le_bytes(bytes);
571 <f32>::from_bits(bits)
572}
573fn f64_from_le_bytes(bytes: [u8; 8]) -> f64 {
574 let bits = <u64>::from_le_bytes(bytes);
575 <f64>::from_bits(bits)
576}
577
578fn read_usize(buffer: &[u8], address: usize, width: BitWidth) -> usize {
579 let cursor = &buffer[address..];
580 match width {
581 BitWidth::W8 => cursor[0] as usize,
582 BitWidth::W16 => cursor
583 .get(0..2)
584 .and_then(|s| s.try_into().ok())
585 .map(<u16>::from_le_bytes)
586 .unwrap_or_default() as usize,
587 BitWidth::W32 => cursor
588 .get(0..4)
589 .and_then(|s| s.try_into().ok())
590 .map(<u32>::from_le_bytes)
591 .unwrap_or_default() as usize,
592 BitWidth::W64 => cursor
593 .get(0..8)
594 .and_then(|s| s.try_into().ok())
595 .map(<u64>::from_le_bytes)
596 .unwrap_or_default() as usize,
597 }
598}
599
600fn unpack_type(ty: u8) -> Result<(FlexBufferType, BitWidth), Error> {
601 let w = BitWidth::try_from(ty & 3u8).map_err(|_| Error::InvalidPackedType)?;
602 let t = FlexBufferType::try_from(ty >> 2).map_err(|_| Error::InvalidPackedType)?;
603 Ok((t, w))
604}