blob: 7d6ada8abedfaf2a02855e56e7ed37f6c90afc43 [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 super::{deref_offset, unpack_type, Error, Reader, ReaderIterator, VectorReader};
16use crate::BitWidth;
James Kuszmaul8e62b022022-03-22 09:33:25 -070017use crate::Buffer;
Austin Schuh272c6132020-11-14 16:37:52 -080018use std::cmp::Ordering;
19use 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.
James Kuszmaul8e62b022022-03-22 09:33:25 -070026pub struct MapReader<B> {
27 pub(super) buffer: B,
Austin Schuh272c6132020-11-14 16:37:52 -080028 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
James Kuszmaul8e62b022022-03-22 09:33:25 -070035impl<B: Buffer> Clone for MapReader<B> {
36 fn clone(&self) -> Self {
37 MapReader {
38 buffer: self.buffer.shallow_copy(),
39 ..*self
40 }
41 }
42}
43
44impl<B: Buffer> Default for MapReader<B> {
45 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
Austin Schuh272c6132020-11-14 16:37:52 -080057// manual implementation of Debug because buffer slice can't be automatically displayed
James Kuszmaul8e62b022022-03-22 09:33:25 -070058impl<B: Buffer> std::fmt::Debug for MapReader<B> {
Austin Schuh272c6132020-11-14 16:37:52 -080059 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
James Kuszmaul8e62b022022-03-22 09:33:25 -070071impl<B: Buffer> MapReader<B> {
Austin Schuh272c6132020-11-14 16:37:52 -080072 /// Returns the number of key/value pairs are in the map.
73 pub fn len(&self) -> usize {
74 self.length
75 }
James Kuszmaul8e62b022022-03-22 09:33:25 -070076
Austin Schuh272c6132020-11-14 16:37:52 -080077 /// Returns true if the map has zero key/value pairs.
78 pub fn is_empty(&self) -> bool {
79 self.length == 0
80 }
James Kuszmaul8e62b022022-03-22 09:33:25 -070081
Austin Schuh272c6132020-11-14 16:37:52 -080082 // Using &CStr will eagerly compute the length of the key. &str needs length info AND utf8
83 // validation. This version is faster than both.
84 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 }
James Kuszmaul8e62b022022-03-22 09:33:25 -070089
Austin Schuh272c6132020-11-14 16:37:52 -080090 /// Returns the index of a given key in the map.
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 =
James Kuszmaul8e62b022022-03-22 09:33:25 -070097 deref_offset(&self.buffer, key_offset_address, self.keys_width).ok()?;
Austin Schuh272c6132020-11-14 16:37:52 -080098 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 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700106
Austin Schuh272c6132020-11-14 16:37:52 -0800107 /// Index into a map with a key or usize.
James Kuszmaul8e62b022022-03-22 09:33:25 -0700108 pub fn index<I: MapReaderIndexer>(&self, i: I) -> Result<Reader<B>, Error> {
Austin Schuh272c6132020-11-14 16:37:52 -0800109 i.index_map_reader(self)
110 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700111
Austin Schuh272c6132020-11-14 16:37:52 -0800112 /// Index into a map with a key or usize. If any errors occur a Null reader is returned.
James Kuszmaul8e62b022022-03-22 09:33:25 -0700113 pub fn idx<I: MapReaderIndexer>(&self, i: I) -> Reader<B> {
Austin Schuh272c6132020-11-14 16:37:52 -0800114 i.index_map_reader(self).unwrap_or_default()
115 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700116
117 fn usize_index(&self, i: usize) -> Result<Reader<B>, Error> {
Austin Schuh272c6132020-11-14 16:37:52 -0800118 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(
James Kuszmaul8e62b022022-03-22 09:33:25 -0700129 self.buffer.shallow_copy(),
Austin Schuh272c6132020-11-14 16:37:52 -0800130 data_address,
131 fxb_type,
132 width,
133 self.values_width,
134 )
135 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700136
137 fn key_index(&self, k: &str) -> Result<Reader<B>, Error> {
Austin Schuh272c6132020-11-14 16:37:52 -0800138 let i = self.index_key(k).ok_or(Error::KeyNotFound)?;
139 self.usize_index(i)
140 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700141
Austin Schuh272c6132020-11-14 16:37:52 -0800142 /// Iterate over the values of the map.
James Kuszmaul8e62b022022-03-22 09:33:25 -0700143 pub fn iter_values(&self) -> ReaderIterator<B> {
Austin Schuh272c6132020-11-14 16:37:52 -0800144 ReaderIterator::new(VectorReader {
145 reader: Reader {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700146 buffer: self.buffer.shallow_copy(),
Austin Schuh272c6132020-11-14 16:37:52 -0800147 fxb_type: crate::FlexBufferType::Map,
148 width: self.values_width,
149 address: self.values_address,
150 },
151 length: self.length,
152 })
153 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700154
Austin Schuh272c6132020-11-14 16:37:52 -0800155 /// Iterate over the keys of the map.
156 pub fn iter_keys(
157 &self,
James Kuszmaul8e62b022022-03-22 09:33:25 -0700158 ) -> impl Iterator<Item = B::BufferString> + DoubleEndedIterator + ExactSizeIterator + FusedIterator
Austin Schuh272c6132020-11-14 16:37:52 -0800159 {
160 self.keys_vector().iter().map(|k| k.as_str())
161 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700162
163 pub fn keys_vector(&self) -> VectorReader<B> {
Austin Schuh272c6132020-11-14 16:37:52 -0800164 VectorReader {
165 reader: Reader {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700166 buffer: self.buffer.shallow_copy(),
Austin Schuh272c6132020-11-14 16:37:52 -0800167 fxb_type: crate::FlexBufferType::VectorKey,
168 width: self.keys_width,
169 address: self.keys_address,
170 },
171 length: self.length,
172 }
173 }
174}
James Kuszmaul8e62b022022-03-22 09:33:25 -0700175
Austin Schuh272c6132020-11-14 16:37:52 -0800176pub trait MapReaderIndexer {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700177 fn index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error>;
Austin Schuh272c6132020-11-14 16:37:52 -0800178}
James Kuszmaul8e62b022022-03-22 09:33:25 -0700179
Austin Schuh272c6132020-11-14 16:37:52 -0800180impl MapReaderIndexer for usize {
181 #[inline]
James Kuszmaul8e62b022022-03-22 09:33:25 -0700182 fn index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error> {
Austin Schuh272c6132020-11-14 16:37:52 -0800183 r.usize_index(self)
184 }
185}
James Kuszmaul8e62b022022-03-22 09:33:25 -0700186
Austin Schuh272c6132020-11-14 16:37:52 -0800187impl MapReaderIndexer for &str {
188 #[inline]
James Kuszmaul8e62b022022-03-22 09:33:25 -0700189 fn index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error> {
Austin Schuh272c6132020-11-14 16:37:52 -0800190 r.key_index(self)
191 }
192}