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};
pub struct MapReader<B> {
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<B: Buffer> Clone for MapReader<B> {
fn clone(&self) -> Self {
MapReader { buffer: self.buffer.shallow_copy(), ..*self }
}
}
impl<B: Buffer> Default for MapReader<B> {
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(),
}
}
}
impl<B: Buffer> std::fmt::Debug for MapReader<B> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
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<B: Buffer> MapReader<B> {
pub fn len(&self) -> usize {
self.length
}
pub fn is_empty(&self) -> bool {
self.length == 0
}
fn lazy_strcmp(&self, key_addr: usize, key: &str) -> Ordering {
let k = self.buffer[key_addr..].iter().take_while(|&&b| b != b'\0');
k.cmp(key.as_bytes().iter())
}
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
}
pub fn index<I: MapReaderIndexer>(&self, i: I) -> Result<Reader<B>, Error> {
i.index_map_reader(self)
}
pub fn idx<I: MapReaderIndexer>(&self, i: I) -> Reader<B> {
i.index_map_reader(self).unwrap_or_default()
}
fn usize_index(&self, i: usize) -> Result<Reader<B>, 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<Reader<B>, Error> {
let i = self.index_key(k).ok_or(Error::KeyNotFound)?;
self.usize_index(i)
}
pub fn iter_values(&self) -> ReaderIterator<B> {
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,
})
}
pub fn iter_keys(
&self,
) -> impl Iterator<Item = B::BufferString> + DoubleEndedIterator + ExactSizeIterator + FusedIterator
{
self.keys_vector().iter().map(|k| k.as_str())
}
pub fn keys_vector(&self) -> VectorReader<B> {
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<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error>;
}
impl MapReaderIndexer for usize {
#[inline]
fn index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error> {
r.usize_index(self)
}
}
impl MapReaderIndexer for &str {
#[inline]
fn index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error> {
r.key_index(self)
}
}