// Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use super::{deref_offset, unpack_type, Error, Reader, ReaderIterator, VectorReader}; use crate::BitWidth; use crate::Buffer; use std::cmp::Ordering; use std::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator}; /// Allows indexing on a flexbuffer map. /// /// MapReaders may be indexed with strings or usizes. `index` returns a result type, /// which may indicate failure due to a missing key or bad data, `idx` returns an Null Reader in /// cases of error. pub struct MapReader { pub(super) buffer: B, pub(super) values_address: usize, pub(super) keys_address: usize, pub(super) values_width: BitWidth, pub(super) keys_width: BitWidth, pub(super) length: usize, } impl Clone for MapReader { fn clone(&self) -> Self { MapReader { buffer: self.buffer.shallow_copy(), ..*self } } } impl Default for MapReader { fn default() -> Self { MapReader { buffer: B::empty(), values_address: usize::default(), keys_address: usize::default(), values_width: BitWidth::default(), keys_width: BitWidth::default(), length: usize::default(), } } } // manual implementation of Debug because buffer slice can't be automatically displayed impl std::fmt::Debug for MapReader { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // skips buffer field f.debug_struct("MapReader") .field("values_address", &self.values_address) .field("keys_address", &self.keys_address) .field("values_width", &self.values_width) .field("keys_width", &self.keys_width) .field("length", &self.length) .finish() } } impl MapReader { /// Returns the number of key/value pairs are in the map. pub fn len(&self) -> usize { self.length } /// Returns true if the map has zero key/value pairs. pub fn is_empty(&self) -> bool { self.length == 0 } // Using &CStr will eagerly compute the length of the key. &str needs length info AND utf8 // validation. This version is faster than both. fn lazy_strcmp(&self, key_addr: usize, key: &str) -> Ordering { // TODO: Can we know this won't OOB and panic? let k = self.buffer[key_addr..].iter().take_while(|&&b| b != b'\0'); k.cmp(key.as_bytes().iter()) } /// Returns the index of a given key in the map. pub fn index_key(&self, key: &str) -> Option { let (mut low, mut high) = (0, self.length); while low < high { let i = (low + high) / 2; let key_offset_address = self.keys_address + i * self.keys_width.n_bytes(); let key_address = deref_offset(&self.buffer, key_offset_address, self.keys_width).ok()?; match self.lazy_strcmp(key_address, key) { Ordering::Equal => return Some(i), Ordering::Less => low = if i == low { i + 1 } else { i }, Ordering::Greater => high = i, } } None } /// Index into a map with a key or usize. pub fn index(&self, i: I) -> Result, Error> { i.index_map_reader(self) } /// Index into a map with a key or usize. If any errors occur a Null reader is returned. pub fn idx(&self, i: I) -> Reader { i.index_map_reader(self).unwrap_or_default() } fn usize_index(&self, i: usize) -> Result, Error> { if i >= self.length { return Err(Error::IndexOutOfBounds); } let data_address = self.values_address + self.values_width.n_bytes() * i; let type_address = self.values_address + self.values_width.n_bytes() * self.length + i; let (fxb_type, width) = self .buffer .get(type_address) .ok_or(Error::FlexbufferOutOfBounds) .and_then(|&b| unpack_type(b))?; Reader::new( self.buffer.shallow_copy(), data_address, fxb_type, width, self.values_width, ) } fn key_index(&self, k: &str) -> Result, Error> { let i = self.index_key(k).ok_or(Error::KeyNotFound)?; self.usize_index(i) } /// Iterate over the values of the map. pub fn iter_values(&self) -> ReaderIterator { ReaderIterator::new(VectorReader { reader: Reader { buffer: self.buffer.shallow_copy(), fxb_type: crate::FlexBufferType::Map, width: self.values_width, address: self.values_address, }, length: self.length, }) } /// Iterate over the keys of the map. pub fn iter_keys( &self, ) -> impl Iterator + DoubleEndedIterator + ExactSizeIterator + FusedIterator { self.keys_vector().iter().map(|k| k.as_str()) } pub fn keys_vector(&self) -> VectorReader { VectorReader { reader: Reader { buffer: self.buffer.shallow_copy(), fxb_type: crate::FlexBufferType::VectorKey, width: self.keys_width, address: self.keys_address, }, length: self.length, } } } pub trait MapReaderIndexer { fn index_map_reader(self, r: &MapReader) -> Result, Error>; } impl MapReaderIndexer for usize { #[inline] fn index_map_reader(self, r: &MapReader) -> Result, Error> { r.usize_index(self) } } impl MapReaderIndexer for &str { #[inline] fn index_map_reader(self, r: &MapReader) -> Result, Error> { r.key_index(self) } }