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