• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use super::{deref_offset, unpack_type, Error, Reader, ReaderIterator, VectorReader};
16 use crate::BitWidth;
17 use crate::Buffer;
18 use std::cmp::Ordering;
19 use std::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator};
20 
21 /// Allows indexing on a flexbuffer map.
22 ///
23 /// MapReaders may be indexed with strings or usizes. `index` returns a result type,
24 /// which may indicate failure due to a missing key or bad data, `idx` returns an Null Reader in
25 /// cases of error.
26 pub struct MapReader<B> {
27     pub(super) buffer: B,
28     pub(super) values_address: usize,
29     pub(super) keys_address: usize,
30     pub(super) values_width: BitWidth,
31     pub(super) keys_width: BitWidth,
32     pub(super) length: usize,
33 }
34 
35 impl<B: Buffer> Clone for MapReader<B> {
clone(&self) -> Self36     fn clone(&self) -> Self {
37         MapReader {
38             buffer: self.buffer.shallow_copy(),
39             ..*self
40         }
41     }
42 }
43 
44 impl<B: Buffer> Default for MapReader<B> {
default() -> Self45     fn default() -> Self {
46         MapReader {
47             buffer: B::empty(),
48             values_address: usize::default(),
49             keys_address: usize::default(),
50             values_width: BitWidth::default(),
51             keys_width: BitWidth::default(),
52             length: usize::default(),
53         }
54     }
55 }
56 
57 // manual implementation of Debug because buffer slice can't be automatically displayed
58 impl<B: Buffer> std::fmt::Debug for MapReader<B> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result59     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60         // skips buffer field
61         f.debug_struct("MapReader")
62             .field("values_address", &self.values_address)
63             .field("keys_address", &self.keys_address)
64             .field("values_width", &self.values_width)
65             .field("keys_width", &self.keys_width)
66             .field("length", &self.length)
67             .finish()
68     }
69 }
70 
71 impl<B: Buffer> MapReader<B> {
72     /// Returns the number of key/value pairs are in the map.
len(&self) -> usize73     pub fn len(&self) -> usize {
74         self.length
75     }
76 
77     /// Returns true if the map has zero key/value pairs.
is_empty(&self) -> bool78     pub fn is_empty(&self) -> bool {
79         self.length == 0
80     }
81 
82     // Using &CStr will eagerly compute the length of the key. &str needs length info AND utf8
83     // validation. This version is faster than both.
lazy_strcmp(&self, key_addr: usize, key: &str) -> Ordering84     fn lazy_strcmp(&self, key_addr: usize, key: &str) -> Ordering {
85         // TODO: Can we know this won't OOB and panic?
86         let k = self.buffer[key_addr..].iter().take_while(|&&b| b != b'\0');
87         k.cmp(key.as_bytes().iter())
88     }
89 
90     /// Returns the index of a given key in the map.
index_key(&self, key: &str) -> Option<usize>91     pub fn index_key(&self, key: &str) -> Option<usize> {
92         let (mut low, mut high) = (0, self.length);
93         while low < high {
94             let i = (low + high) / 2;
95             let key_offset_address = self.keys_address + i * self.keys_width.n_bytes();
96             let key_address =
97                 deref_offset(&self.buffer, key_offset_address, self.keys_width).ok()?;
98             match self.lazy_strcmp(key_address, key) {
99                 Ordering::Equal => return Some(i),
100                 Ordering::Less => low = if i == low { i + 1 } else { i },
101                 Ordering::Greater => high = i,
102             }
103         }
104         None
105     }
106 
107     /// Index into a map with a key or usize.
index<I: MapReaderIndexer>(&self, i: I) -> Result<Reader<B>, Error>108     pub fn index<I: MapReaderIndexer>(&self, i: I) -> Result<Reader<B>, Error> {
109         i.index_map_reader(self)
110     }
111 
112     /// Index into a map with a key or usize. If any errors occur a Null reader is returned.
idx<I: MapReaderIndexer>(&self, i: I) -> Reader<B>113     pub fn idx<I: MapReaderIndexer>(&self, i: I) -> Reader<B> {
114         i.index_map_reader(self).unwrap_or_default()
115     }
116 
usize_index(&self, i: usize) -> Result<Reader<B>, Error>117     fn usize_index(&self, i: usize) -> Result<Reader<B>, Error> {
118         if i >= self.length {
119             return Err(Error::IndexOutOfBounds);
120         }
121         let data_address = self.values_address + self.values_width.n_bytes() * i;
122         let type_address = self.values_address + self.values_width.n_bytes() * self.length + i;
123         let (fxb_type, width) = self
124             .buffer
125             .get(type_address)
126             .ok_or(Error::FlexbufferOutOfBounds)
127             .and_then(|&b| unpack_type(b))?;
128         Reader::new(
129             self.buffer.shallow_copy(),
130             data_address,
131             fxb_type,
132             width,
133             self.values_width,
134         )
135     }
136 
key_index(&self, k: &str) -> Result<Reader<B>, Error>137     fn key_index(&self, k: &str) -> Result<Reader<B>, Error> {
138         let i = self.index_key(k).ok_or(Error::KeyNotFound)?;
139         self.usize_index(i)
140     }
141 
142     /// Iterate over the values of the map.
iter_values(&self) -> ReaderIterator<B>143     pub fn iter_values(&self) -> ReaderIterator<B> {
144         ReaderIterator::new(VectorReader {
145             reader: Reader {
146                 buffer: self.buffer.shallow_copy(),
147                 fxb_type: crate::FlexBufferType::Map,
148                 width: self.values_width,
149                 address: self.values_address,
150             },
151             length: self.length,
152         })
153     }
154 
155     /// Iterate over the keys of the map.
iter_keys( &self, ) -> impl Iterator<Item = B::BufferString> + DoubleEndedIterator + ExactSizeIterator + FusedIterator156     pub fn iter_keys(
157         &self,
158     ) -> impl Iterator<Item = B::BufferString> + DoubleEndedIterator + ExactSizeIterator + FusedIterator
159     {
160         self.keys_vector().iter().map(|k| k.as_str())
161     }
162 
keys_vector(&self) -> VectorReader<B>163     pub fn keys_vector(&self) -> VectorReader<B> {
164         VectorReader {
165             reader: Reader {
166                 buffer: self.buffer.shallow_copy(),
167                 fxb_type: crate::FlexBufferType::VectorKey,
168                 width: self.keys_width,
169                 address: self.keys_address,
170             },
171             length: self.length,
172         }
173     }
174 }
175 
176 pub trait MapReaderIndexer {
index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error>177     fn index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error>;
178 }
179 
180 impl MapReaderIndexer for usize {
181     #[inline]
index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error>182     fn index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error> {
183         r.usize_index(self)
184     }
185 }
186 
187 impl MapReaderIndexer for &str {
188     #[inline]
index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error>189     fn index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error> {
190         r.key_index(self)
191     }
192 }
193