mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-02 04:04:19 +00:00
* Fix doc comment warnings
Can't use doc comment "///" syntax on macros, that generates the following warning:
warning: unused doc comment
--> src\flexbuffer_type.rs:236:5
|
236 | /// returns true if and only if the flexbuffer type is `VectorFloat4`.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macros
|
= help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
So switched to just use ordinary "//" comments on these to be warning free
* Upgrade num_enum 0.4.1 -> 0.5.0
* Remove unused and non-working usage of test crates
* Remove usage of abandoned debug_stub_derive crate
Which brought in old pre-v1 syn and quote crates.
This replaces it with just manual Debug trait implementation instead for the 2 cases
158 lines
5.8 KiB
Rust
158 lines
5.8 KiB
Rust
// 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 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.
|
|
#[derive(Default, Clone)]
|
|
pub struct MapReader<'de> {
|
|
pub(super) buffer: &'de [u8],
|
|
pub(super) values_address: usize,
|
|
pub(super) keys_address: usize,
|
|
pub(super) values_width: BitWidth,
|
|
pub(super) keys_width: BitWidth,
|
|
pub(super) length: usize,
|
|
}
|
|
|
|
// manual implementation of Debug because buffer slice can't be automatically displayed
|
|
impl<'de> std::fmt::Debug for MapReader<'de> {
|
|
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<'de> MapReader<'de> {
|
|
/// 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<usize> {
|
|
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<I: MapReaderIndexer>(&self, i: I) -> Result<Reader<'de>, 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<I: MapReaderIndexer>(&self, i: I) -> Reader<'de> {
|
|
i.index_map_reader(self).unwrap_or_default()
|
|
}
|
|
fn usize_index(&self, i: usize) -> Result<Reader<'de>, 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,
|
|
data_address,
|
|
fxb_type,
|
|
width,
|
|
self.values_width,
|
|
)
|
|
}
|
|
fn key_index(&self, k: &str) -> Result<Reader<'de>, 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<'de> {
|
|
ReaderIterator::new(VectorReader {
|
|
reader: Reader {
|
|
buffer: self.buffer,
|
|
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<Item = &'de str> + DoubleEndedIterator + ExactSizeIterator + FusedIterator
|
|
{
|
|
self.keys_vector().iter().map(|k| k.as_str())
|
|
}
|
|
pub fn keys_vector(&self) -> VectorReader<'de> {
|
|
VectorReader {
|
|
reader: Reader {
|
|
buffer: self.buffer,
|
|
fxb_type: crate::FlexBufferType::VectorKey,
|
|
width: self.keys_width,
|
|
address: self.keys_address,
|
|
},
|
|
length: self.length,
|
|
}
|
|
}
|
|
}
|
|
pub trait MapReaderIndexer {
|
|
fn index_map_reader<'de>(self, r: &MapReader<'de>) -> Result<Reader<'de>, Error>;
|
|
}
|
|
impl MapReaderIndexer for usize {
|
|
#[inline]
|
|
fn index_map_reader<'de>(self, r: &MapReader<'de>) -> Result<Reader<'de>, Error> {
|
|
r.usize_index(self)
|
|
}
|
|
}
|
|
impl MapReaderIndexer for &str {
|
|
#[inline]
|
|
fn index_map_reader<'de>(self, r: &MapReader<'de>) -> Result<Reader<'de>, Error> {
|
|
r.key_index(self)
|
|
}
|
|
}
|