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