blob: 8e9c247c25524547fee158ed227f918a648f1029 [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;
James Kuszmaul8e62b022022-03-22 09:33:25 -070017use crate::{Blob, Buffer};
Austin Schuh272c6132020-11-14 16:37:52 -080018use std::convert::{TryFrom, TryInto};
19use std::fmt;
20use std::ops::Rem;
21use std::str::FromStr;
22mod de;
23mod iter;
24mod map;
James Kuszmaul8e62b022022-03-22 09:33:25 -070025mod serialize;
Austin Schuh272c6132020-11-14 16:37:52 -080026mod vector;
27pub use de::DeserializationError;
28pub use iter::ReaderIterator;
29pub use map::{MapReader, MapReaderIndexer};
30pub use vector::VectorReader;
31
32/// All the possible errors when reading a flexbuffer.
33#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
34pub enum Error {
35 /// One of the following data errors occured:
36 ///
37 /// * The read flexbuffer had an offset that pointed outside the flexbuffer.
38 /// * The 'negative indicies' where length and map keys are stored were out of bounds
39 /// * The buffer was too small to contain a flexbuffer root.
40 FlexbufferOutOfBounds,
41 /// Failed to parse a valid FlexbufferType and Bitwidth from a type byte.
42 InvalidPackedType,
43 /// Flexbuffer type of the read data does not match function used.
44 UnexpectedFlexbufferType {
45 expected: FlexBufferType,
46 actual: FlexBufferType,
47 },
48 /// BitWidth type of the read data does not match function used.
49 UnexpectedBitWidth {
50 expected: BitWidth,
51 actual: BitWidth,
52 },
53 /// Read a flexbuffer offset or length that overflowed usize.
54 ReadUsizeOverflowed,
55 /// Tried to index a type that's not one of the Flexbuffer vector types.
56 CannotIndexAsVector,
57 /// Tried to index a Flexbuffer vector or map out of bounds.
58 IndexOutOfBounds,
59 /// A Map was indexed with a key that it did not contain.
60 KeyNotFound,
61 /// Failed to parse a Utf8 string.
62 /// The Option will be `None` if and only if this Error was deserialized.
63 // NOTE: std::str::Utf8Error does not implement Serialize, Deserialize, nor Default. We tell
64 // serde to skip the field and default to None. We prefer to have the boxed error so it can be
65 // used with std::error::Error::source, though another (worse) option could be to drop that
66 // information.
67 Utf8Error(#[serde(skip)] Option<Box<std::str::Utf8Error>>),
68 /// get_slice failed because the given data buffer is misaligned.
69 AlignmentError,
70 InvalidRootWidth,
71 InvalidMapKeysVectorWidth,
72}
73impl std::convert::From<std::str::Utf8Error> for Error {
74 fn from(e: std::str::Utf8Error) -> Self {
75 Self::Utf8Error(Some(Box::new(e)))
76 }
77}
78impl fmt::Display for Error {
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 match self {
81 Self::UnexpectedBitWidth { expected, actual } => write!(
82 f,
83 "Error reading flexbuffer: Expected bitwidth: {:?}, found bitwidth: {:?}",
84 expected, actual
85 ),
86 Self::UnexpectedFlexbufferType { expected, actual } => write!(
87 f,
88 "Error reading flexbuffer: Expected type: {:?}, found type: {:?}",
89 expected, actual
90 ),
91 _ => write!(f, "Error reading flexbuffer: {:?}", self),
92 }
93 }
94}
95impl std::error::Error for Error {
96 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
97 if let Self::Utf8Error(Some(e)) = self {
98 Some(e)
99 } else {
100 None
101 }
102 }
103}
104
105pub trait ReadLE: crate::private::Sealed + std::marker::Sized {
106 const VECTOR_TYPE: FlexBufferType;
107 const WIDTH: BitWidth;
108}
109macro_rules! rle {
110 ($T: ty, $VECTOR_TYPE: ident, $WIDTH: ident) => {
111 impl ReadLE for $T {
112 const VECTOR_TYPE: FlexBufferType = FlexBufferType::$VECTOR_TYPE;
113 const WIDTH: BitWidth = BitWidth::$WIDTH;
114 }
115 };
116}
117rle!(u8, VectorUInt, W8);
118rle!(u16, VectorUInt, W16);
119rle!(u32, VectorUInt, W32);
120rle!(u64, VectorUInt, W64);
121rle!(i8, VectorInt, W8);
122rle!(i16, VectorInt, W16);
123rle!(i32, VectorInt, W32);
124rle!(i64, VectorInt, W64);
125rle!(f32, VectorFloat, W32);
126rle!(f64, VectorFloat, W64);
127
128macro_rules! as_default {
129 ($as: ident, $get: ident, $T: ty) => {
130 pub fn $as(&self) -> $T {
131 self.$get().unwrap_or_default()
132 }
133 };
134}
135
136/// `Reader`s allow access to data stored in a Flexbuffer.
137///
138/// Each reader represents a single address in the buffer so data is read lazily. Start a reader
139/// by calling `get_root` on your flexbuffer `&[u8]`.
140///
141/// - The `get_T` methods return a `Result<T, Error>`. They return an OK value if and only if the
142/// flexbuffer type matches `T`. This is analogous to the behavior of Rust's json library, though
143/// with Result instead of Option.
144/// - The `as_T` methods will try their best to return to a value of type `T`
145/// (by casting or even parsing a string if necessary) but ultimately returns `T::default` if it
146/// fails. This behavior is analogous to that of flexbuffers C++.
James Kuszmaul8e62b022022-03-22 09:33:25 -0700147pub struct Reader<B> {
Austin Schuh272c6132020-11-14 16:37:52 -0800148 fxb_type: FlexBufferType,
149 width: BitWidth,
150 address: usize,
James Kuszmaul8e62b022022-03-22 09:33:25 -0700151 buffer: B,
152}
153
154impl<B: Buffer> Clone for Reader<B> {
155 fn clone(&self) -> Self {
156 Reader {
157 fxb_type: self.fxb_type,
158 width: self.width,
159 address: self.address,
160 buffer: self.buffer.shallow_copy(),
161 }
162 }
163}
164
165impl<B: Buffer> Default for Reader<B> {
166 fn default() -> Self {
167 Reader {
168 fxb_type: FlexBufferType::default(),
169 width: BitWidth::default(),
170 address: usize::default(),
171 buffer: B::empty(),
172 }
173 }
Austin Schuh272c6132020-11-14 16:37:52 -0800174}
175
176// manual implementation of Debug because buffer slice can't be automatically displayed
James Kuszmaul8e62b022022-03-22 09:33:25 -0700177impl<B> std::fmt::Debug for Reader<B> {
Austin Schuh272c6132020-11-14 16:37:52 -0800178 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
179 // skips buffer field
180 f.debug_struct("Reader")
181 .field("fxb_type", &self.fxb_type)
182 .field("width", &self.width)
183 .field("address", &self.address)
184 .finish()
185 }
186}
187
Austin Schuh272c6132020-11-14 16:37:52 -0800188macro_rules! try_cast_fn {
189 ($name: ident, $full_width: ident, $Ty: ident) => {
190 pub fn $name(&self) -> $Ty {
191 self.$full_width().try_into().unwrap_or_default()
192 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700193 };
Austin Schuh272c6132020-11-14 16:37:52 -0800194}
195
196fn safe_sub(a: usize, b: usize) -> Result<usize, Error> {
197 a.checked_sub(b).ok_or(Error::FlexbufferOutOfBounds)
198}
199
200fn deref_offset(buffer: &[u8], address: usize, width: BitWidth) -> Result<usize, Error> {
201 let off = read_usize(buffer, address, width);
202 safe_sub(address, off)
203}
204
James Kuszmaul8e62b022022-03-22 09:33:25 -0700205impl<B: Buffer> Reader<B> {
Austin Schuh272c6132020-11-14 16:37:52 -0800206 fn new(
James Kuszmaul8e62b022022-03-22 09:33:25 -0700207 buffer: B,
Austin Schuh272c6132020-11-14 16:37:52 -0800208 mut address: usize,
209 mut fxb_type: FlexBufferType,
210 width: BitWidth,
211 parent_width: BitWidth,
212 ) -> Result<Self, Error> {
213 if fxb_type.is_reference() {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700214 address = deref_offset(&buffer, address, parent_width)?;
Austin Schuh272c6132020-11-14 16:37:52 -0800215 // Indirects were dereferenced.
216 if let Some(t) = fxb_type.to_direct() {
217 fxb_type = t;
218 }
219 }
220 Ok(Reader {
221 address,
222 fxb_type,
223 width,
224 buffer,
225 })
226 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700227
Austin Schuh272c6132020-11-14 16:37:52 -0800228 /// Parses the flexbuffer from the given buffer. Assumes the flexbuffer root is the last byte
229 /// of the buffer.
James Kuszmaul8e62b022022-03-22 09:33:25 -0700230 pub fn get_root(buffer: B) -> Result<Self, Error> {
Austin Schuh272c6132020-11-14 16:37:52 -0800231 let end = buffer.len();
232 if end < 3 {
233 return Err(Error::FlexbufferOutOfBounds);
234 }
235 // Last byte is the root width.
236 let root_width = BitWidth::from_nbytes(buffer[end - 1]).ok_or(Error::InvalidRootWidth)?;
237 // Second last byte is root type.
238 let (fxb_type, width) = unpack_type(buffer[end - 2])?;
239 // Location of root data. (BitWidth bits before root type)
240 let address = safe_sub(end - 2, root_width.n_bytes())?;
241 Self::new(buffer, address, fxb_type, width, root_width)
242 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700243
244 /// Convenience function to get the underlying buffer. By using `shallow_copy`, this preserves
245 /// the lifetime that the underlying buffer has.
246 pub fn buffer(&self) -> B {
247 self.buffer.shallow_copy()
248 }
249
Austin Schuh272c6132020-11-14 16:37:52 -0800250 /// Returns the FlexBufferType of this Reader.
251 pub fn flexbuffer_type(&self) -> FlexBufferType {
252 self.fxb_type
253 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700254
Austin Schuh272c6132020-11-14 16:37:52 -0800255 /// Returns the bitwidth of this Reader.
256 pub fn bitwidth(&self) -> BitWidth {
257 self.width
258 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700259
Austin Schuh272c6132020-11-14 16:37:52 -0800260 /// Returns the length of the Flexbuffer. If the type has no length, or if an error occurs,
261 /// 0 is returned.
262 pub fn length(&self) -> usize {
263 if let Some(len) = self.fxb_type.fixed_length_vector_length() {
264 len
265 } else if self.fxb_type.has_length_slot() && self.address >= self.width.n_bytes() {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700266 read_usize(
267 &self.buffer,
268 self.address - self.width.n_bytes(),
269 self.width,
270 )
Austin Schuh272c6132020-11-14 16:37:52 -0800271 } else {
272 0
273 }
274 }
275 /// Returns true if the flexbuffer is aligned to 8 bytes. This guarantees, for valid
276 /// flexbuffers, that the data is correctly aligned in memory and slices can be read directly
277 /// e.g. with `get_f64s` or `get_i16s`.
James Kuszmaul8e62b022022-03-22 09:33:25 -0700278 #[inline]
Austin Schuh272c6132020-11-14 16:37:52 -0800279 pub fn is_aligned(&self) -> bool {
280 (self.buffer.as_ptr() as usize).rem(8) == 0
281 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700282
283 as_default!(as_vector, get_vector, VectorReader<B>);
284 as_default!(as_map, get_map, MapReader<B>);
Austin Schuh272c6132020-11-14 16:37:52 -0800285
286 fn expect_type(&self, ty: FlexBufferType) -> Result<(), Error> {
287 if self.fxb_type == ty {
288 Ok(())
289 } else {
290 Err(Error::UnexpectedFlexbufferType {
291 expected: ty,
292 actual: self.fxb_type,
293 })
294 }
295 }
296 fn expect_bw(&self, bw: BitWidth) -> Result<(), Error> {
297 if self.width == bw {
298 Ok(())
299 } else {
300 Err(Error::UnexpectedBitWidth {
301 expected: bw,
302 actual: self.width,
303 })
304 }
305 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700306
307 /// Directly reads a slice of type `T` where `T` is one of `u8,u16,u32,u64,i8,i16,i32,i64,f32,f64`.
Austin Schuh272c6132020-11-14 16:37:52 -0800308 /// Returns Err if the type, bitwidth, or memory alignment does not match. Since the bitwidth is
309 /// dynamic, its better to use a VectorReader unless you know your data and performance is critical.
310 #[cfg(target_endian = "little")]
James Kuszmaul8e62b022022-03-22 09:33:25 -0700311 #[deprecated(
312 since = "0.3.0",
313 note = "This function is unsafe - if this functionality is needed use `Reader::buffer::align_to`"
314 )]
315 pub fn get_slice<T: ReadLE>(&self) -> Result<&[T], Error> {
Austin Schuh272c6132020-11-14 16:37:52 -0800316 if self.flexbuffer_type().typed_vector_type() != T::VECTOR_TYPE.typed_vector_type() {
317 self.expect_type(T::VECTOR_TYPE)?;
318 }
319 if self.bitwidth().n_bytes() != std::mem::size_of::<T>() {
320 self.expect_bw(T::WIDTH)?;
321 }
322 let end = self.address + self.length() * std::mem::size_of::<T>();
James Kuszmaul8e62b022022-03-22 09:33:25 -0700323 let slice: &[u8] = self
Austin Schuh272c6132020-11-14 16:37:52 -0800324 .buffer
325 .get(self.address..end)
326 .ok_or(Error::FlexbufferOutOfBounds)?;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700327
Austin Schuh272c6132020-11-14 16:37:52 -0800328 // `align_to` is required because the point of this function is to directly hand back a
329 // slice of scalars. This can fail because Rust's default allocator is not 16byte aligned
330 // (though in practice this only happens for small buffers).
331 let (pre, mid, suf) = unsafe { slice.align_to::<T>() };
332 if pre.is_empty() && suf.is_empty() {
333 Ok(mid)
334 } else {
335 Err(Error::AlignmentError)
336 }
337 }
338
James Kuszmaul8e62b022022-03-22 09:33:25 -0700339 /// Returns the value of the reader if it is a boolean.
340 /// Otherwise Returns error.
Austin Schuh272c6132020-11-14 16:37:52 -0800341 pub fn get_bool(&self) -> Result<bool, Error> {
342 self.expect_type(FlexBufferType::Bool)?;
343 Ok(
344 self.buffer[self.address..self.address + self.width.n_bytes()]
345 .iter()
346 .any(|&b| b != 0),
347 )
348 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700349
350 /// Gets the length of the key if this type is a key.
351 ///
352 /// Otherwise, returns an error.
353 #[inline]
354 fn get_key_len(&self) -> Result<usize, Error> {
Austin Schuh272c6132020-11-14 16:37:52 -0800355 self.expect_type(FlexBufferType::Key)?;
356 let (length, _) = self.buffer[self.address..]
357 .iter()
358 .enumerate()
359 .find(|(_, &b)| b == b'\0')
360 .unwrap_or((0, &0));
James Kuszmaul8e62b022022-03-22 09:33:25 -0700361 Ok(length)
Austin Schuh272c6132020-11-14 16:37:52 -0800362 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700363
364 /// Retrieves the string value up until the first `\0` character.
365 pub fn get_key(&self) -> Result<B::BufferString, Error> {
366 let bytes = self
367 .buffer
368 .slice(self.address..self.address + self.get_key_len()?)
369 .ok_or(Error::IndexOutOfBounds)?;
370 Ok(bytes.buffer_str()?)
371 }
372
373 pub fn get_blob(&self) -> Result<Blob<B>, Error> {
Austin Schuh272c6132020-11-14 16:37:52 -0800374 self.expect_type(FlexBufferType::Blob)?;
375 Ok(Blob(
James Kuszmaul8e62b022022-03-22 09:33:25 -0700376 self.buffer
377 .slice(self.address..self.address + self.length())
378 .ok_or(Error::IndexOutOfBounds)?,
Austin Schuh272c6132020-11-14 16:37:52 -0800379 ))
380 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700381
382 pub fn as_blob(&self) -> Blob<B> {
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800383 self.get_blob().unwrap_or_else(|_| Blob(B::empty()))
Austin Schuh272c6132020-11-14 16:37:52 -0800384 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700385
386 /// Retrieves str pointer, errors if invalid UTF-8, or the provided index
387 /// is out of bounds.
388 pub fn get_str(&self) -> Result<B::BufferString, Error> {
Austin Schuh272c6132020-11-14 16:37:52 -0800389 self.expect_type(FlexBufferType::String)?;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700390 let bytes = self
391 .buffer
392 .slice(self.address..self.address + self.length());
393 Ok(bytes.ok_or(Error::ReadUsizeOverflowed)?.buffer_str()?)
Austin Schuh272c6132020-11-14 16:37:52 -0800394 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700395
Austin Schuh272c6132020-11-14 16:37:52 -0800396 fn get_map_info(&self) -> Result<(usize, BitWidth), Error> {
397 self.expect_type(FlexBufferType::Map)?;
398 if 3 * self.width.n_bytes() >= self.address {
399 return Err(Error::FlexbufferOutOfBounds);
400 }
401 let keys_offset_address = self.address - 3 * self.width.n_bytes();
402 let keys_width = {
403 let kw_addr = self.address - 2 * self.width.n_bytes();
James Kuszmaul8e62b022022-03-22 09:33:25 -0700404 let kw = read_usize(&self.buffer, kw_addr, self.width);
Austin Schuh272c6132020-11-14 16:37:52 -0800405 BitWidth::from_nbytes(kw).ok_or(Error::InvalidMapKeysVectorWidth)
406 }?;
407 Ok((keys_offset_address, keys_width))
408 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700409
410 pub fn get_map(&self) -> Result<MapReader<B>, Error> {
Austin Schuh272c6132020-11-14 16:37:52 -0800411 let (keys_offset_address, keys_width) = self.get_map_info()?;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700412 let keys_address = deref_offset(&self.buffer, keys_offset_address, self.width)?;
Austin Schuh272c6132020-11-14 16:37:52 -0800413 // TODO(cneo): Check that vectors length equals keys length.
414 Ok(MapReader {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700415 buffer: self.buffer.shallow_copy(),
Austin Schuh272c6132020-11-14 16:37:52 -0800416 values_address: self.address,
417 values_width: self.width,
418 keys_address,
419 keys_width,
420 length: self.length(),
421 })
422 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700423
Austin Schuh272c6132020-11-14 16:37:52 -0800424 /// Tries to read a FlexBufferType::UInt. Returns Err if the type is not a UInt or if the
425 /// address is out of bounds.
426 pub fn get_u64(&self) -> Result<u64, Error> {
427 self.expect_type(FlexBufferType::UInt)?;
428 let cursor = self
429 .buffer
430 .get(self.address..self.address + self.width.n_bytes());
431 match self.width {
432 BitWidth::W8 => cursor.map(|s| s[0] as u8).map(Into::into),
433 BitWidth::W16 => cursor
434 .and_then(|s| s.try_into().ok())
435 .map(<u16>::from_le_bytes)
436 .map(Into::into),
437 BitWidth::W32 => cursor
438 .and_then(|s| s.try_into().ok())
439 .map(<u32>::from_le_bytes)
440 .map(Into::into),
441 BitWidth::W64 => cursor
442 .and_then(|s| s.try_into().ok())
443 .map(<u64>::from_le_bytes),
444 }
445 .ok_or(Error::FlexbufferOutOfBounds)
446 }
447 /// Tries to read a FlexBufferType::Int. Returns Err if the type is not a UInt or if the
448 /// address is out of bounds.
449 pub fn get_i64(&self) -> Result<i64, Error> {
450 self.expect_type(FlexBufferType::Int)?;
451 let cursor = self
452 .buffer
453 .get(self.address..self.address + self.width.n_bytes());
454 match self.width {
455 BitWidth::W8 => cursor.map(|s| s[0] as i8).map(Into::into),
456 BitWidth::W16 => cursor
457 .and_then(|s| s.try_into().ok())
458 .map(<i16>::from_le_bytes)
459 .map(Into::into),
460 BitWidth::W32 => cursor
461 .and_then(|s| s.try_into().ok())
462 .map(<i32>::from_le_bytes)
463 .map(Into::into),
464 BitWidth::W64 => cursor
465 .and_then(|s| s.try_into().ok())
466 .map(<i64>::from_le_bytes),
467 }
468 .ok_or(Error::FlexbufferOutOfBounds)
469 }
470 /// Tries to read a FlexBufferType::Float. Returns Err if the type is not a UInt, if the
471 /// address is out of bounds, or if its a f16 or f8 (not currently supported).
472 pub fn get_f64(&self) -> Result<f64, Error> {
473 self.expect_type(FlexBufferType::Float)?;
474 let cursor = self
475 .buffer
476 .get(self.address..self.address + self.width.n_bytes());
477 match self.width {
478 BitWidth::W8 | BitWidth::W16 => return Err(Error::InvalidPackedType),
479 BitWidth::W32 => cursor
480 .and_then(|s| s.try_into().ok())
481 .map(f32_from_le_bytes)
482 .map(Into::into),
483 BitWidth::W64 => cursor
484 .and_then(|s| s.try_into().ok())
485 .map(f64_from_le_bytes),
486 }
487 .ok_or(Error::FlexbufferOutOfBounds)
488 }
489 pub fn as_bool(&self) -> bool {
490 use FlexBufferType::*;
491 match self.fxb_type {
492 Bool => self.get_bool().unwrap_or_default(),
493 UInt => self.as_u64() != 0,
494 Int => self.as_i64() != 0,
495 Float => self.as_f64().abs() > std::f64::EPSILON,
496 String | Key => !self.as_str().is_empty(),
497 Null => false,
498 Blob => self.length() != 0,
499 ty if ty.is_vector() => self.length() != 0,
500 _ => unreachable!(),
501 }
502 }
503 /// Returns a u64, casting if necessary. For Maps and Vectors, their length is
504 /// returned. If anything fails, 0 is returned.
505 pub fn as_u64(&self) -> u64 {
506 match self.fxb_type {
507 FlexBufferType::UInt => self.get_u64().unwrap_or_default(),
508 FlexBufferType::Int => self
509 .get_i64()
510 .unwrap_or_default()
511 .try_into()
512 .unwrap_or_default(),
513 FlexBufferType::Float => self.get_f64().unwrap_or_default() as u64,
514 FlexBufferType::String => {
515 if let Ok(s) = self.get_str() {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700516 if let Ok(f) = u64::from_str(&s) {
Austin Schuh272c6132020-11-14 16:37:52 -0800517 return f;
518 }
519 }
520 0
521 }
522 _ if self.fxb_type.is_vector() => self.length() as u64,
523 _ => 0,
524 }
525 }
526 try_cast_fn!(as_u32, as_u64, u32);
527 try_cast_fn!(as_u16, as_u64, u16);
528 try_cast_fn!(as_u8, as_u64, u8);
529
530 /// Returns an i64, casting if necessary. For Maps and Vectors, their length is
531 /// returned. If anything fails, 0 is returned.
532 pub fn as_i64(&self) -> i64 {
533 match self.fxb_type {
534 FlexBufferType::Int => self.get_i64().unwrap_or_default(),
535 FlexBufferType::UInt => self
536 .get_u64()
537 .unwrap_or_default()
538 .try_into()
539 .unwrap_or_default(),
540 FlexBufferType::Float => self.get_f64().unwrap_or_default() as i64,
541 FlexBufferType::String => {
542 if let Ok(s) = self.get_str() {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700543 if let Ok(f) = i64::from_str(&s) {
Austin Schuh272c6132020-11-14 16:37:52 -0800544 return f;
545 }
546 }
547 0
548 }
549 _ if self.fxb_type.is_vector() => self.length() as i64,
550 _ => 0,
551 }
552 }
553 try_cast_fn!(as_i32, as_i64, i32);
554 try_cast_fn!(as_i16, as_i64, i16);
555 try_cast_fn!(as_i8, as_i64, i8);
556
557 /// Returns an f64, casting if necessary. For Maps and Vectors, their length is
558 /// returned. If anything fails, 0 is returned.
559 pub fn as_f64(&self) -> f64 {
560 match self.fxb_type {
561 FlexBufferType::Int => self.get_i64().unwrap_or_default() as f64,
562 FlexBufferType::UInt => self.get_u64().unwrap_or_default() as f64,
563 FlexBufferType::Float => self.get_f64().unwrap_or_default(),
564 FlexBufferType::String => {
565 if let Ok(s) = self.get_str() {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700566 if let Ok(f) = f64::from_str(&s) {
Austin Schuh272c6132020-11-14 16:37:52 -0800567 return f;
568 }
569 }
570 0.0
571 }
572 _ if self.fxb_type.is_vector() => self.length() as f64,
573 _ => 0.0,
574 }
575 }
576 pub fn as_f32(&self) -> f32 {
577 self.as_f64() as f32
578 }
579
580 /// Returns empty string if you're not trying to read a string.
James Kuszmaul8e62b022022-03-22 09:33:25 -0700581 pub fn as_str(&self) -> B::BufferString {
Austin Schuh272c6132020-11-14 16:37:52 -0800582 match self.fxb_type {
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800583 FlexBufferType::String => self.get_str().unwrap_or_else(|_| B::empty_str()),
584 FlexBufferType::Key => self.get_key().unwrap_or_else(|_| B::empty_str()),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700585 _ => B::empty_str(),
Austin Schuh272c6132020-11-14 16:37:52 -0800586 }
587 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700588
589 pub fn get_vector(&self) -> Result<VectorReader<B>, Error> {
Austin Schuh272c6132020-11-14 16:37:52 -0800590 if !self.fxb_type.is_vector() {
591 self.expect_type(FlexBufferType::Vector)?;
592 };
593 Ok(VectorReader {
594 reader: self.clone(),
595 length: self.length(),
596 })
597 }
598}
599
James Kuszmaul8e62b022022-03-22 09:33:25 -0700600impl<B: Buffer> fmt::Display for Reader<B> {
Austin Schuh272c6132020-11-14 16:37:52 -0800601 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
602 use FlexBufferType::*;
603 match self.flexbuffer_type() {
604 Null => write!(f, "null"),
605 UInt => write!(f, "{}", self.as_u64()),
606 Int => write!(f, "{}", self.as_i64()),
607 Float => write!(f, "{}", self.as_f64()),
James Kuszmaul8e62b022022-03-22 09:33:25 -0700608 Key | String => write!(f, "{:?}", &self.as_str() as &str),
Austin Schuh272c6132020-11-14 16:37:52 -0800609 Bool => write!(f, "{}", self.as_bool()),
610 Blob => write!(f, "blob"),
611 Map => {
612 write!(f, "{{")?;
613 let m = self.as_map();
614 let mut pairs = m.iter_keys().zip(m.iter_values());
615 if let Some((k, v)) = pairs.next() {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700616 write!(f, "{:?}: {}", &k as &str, v)?;
Austin Schuh272c6132020-11-14 16:37:52 -0800617 for (k, v) in pairs {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700618 write!(f, ", {:?}: {}", &k as &str, v)?;
Austin Schuh272c6132020-11-14 16:37:52 -0800619 }
620 }
621 write!(f, "}}")
622 }
623 t if t.is_vector() => {
624 write!(f, "[")?;
625 let mut elems = self.as_vector().iter();
626 if let Some(first) = elems.next() {
627 write!(f, "{}", first)?;
628 for e in elems {
629 write!(f, ", {}", e)?;
630 }
631 }
632 write!(f, "]")
633 }
634 _ => unreachable!("Display not implemented for {:?}", self),
635 }
636 }
637}
638
639// TODO(cneo): Use <f..>::from_le_bytes when we move past rustc 1.39.
640fn f32_from_le_bytes(bytes: [u8; 4]) -> f32 {
641 let bits = <u32>::from_le_bytes(bytes);
642 <f32>::from_bits(bits)
643}
James Kuszmaul8e62b022022-03-22 09:33:25 -0700644
Austin Schuh272c6132020-11-14 16:37:52 -0800645fn f64_from_le_bytes(bytes: [u8; 8]) -> f64 {
646 let bits = <u64>::from_le_bytes(bytes);
647 <f64>::from_bits(bits)
648}
649
650fn read_usize(buffer: &[u8], address: usize, width: BitWidth) -> usize {
651 let cursor = &buffer[address..];
652 match width {
653 BitWidth::W8 => cursor[0] as usize,
654 BitWidth::W16 => cursor
655 .get(0..2)
656 .and_then(|s| s.try_into().ok())
657 .map(<u16>::from_le_bytes)
658 .unwrap_or_default() as usize,
659 BitWidth::W32 => cursor
660 .get(0..4)
661 .and_then(|s| s.try_into().ok())
662 .map(<u32>::from_le_bytes)
663 .unwrap_or_default() as usize,
664 BitWidth::W64 => cursor
665 .get(0..8)
666 .and_then(|s| s.try_into().ok())
667 .map(<u64>::from_le_bytes)
668 .unwrap_or_default() as usize,
669 }
670}
671
672fn unpack_type(ty: u8) -> Result<(FlexBufferType, BitWidth), Error> {
673 let w = BitWidth::try_from(ty & 3u8).map_err(|_| Error::InvalidPackedType)?;
674 let t = FlexBufferType::try_from(ty >> 2).map_err(|_| Error::InvalidPackedType)?;
675 Ok((t, w))
676}