use std::collections::BTreeMap;
use std::marker::PhantomData;
use crate::error::Error;
use super::bit_util::{bitmap_width, is_bit_set, round_up_to_word, slot_width};
use super::row::{Row, RowValue};
pub trait RowView<'a> {
fn as_bytes(&self) -> &'a [u8];
#[inline]
fn encoded_len(&self) -> usize {
self.as_bytes().len()
}
}
#[doc(hidden)]
#[derive(Clone, Copy)]
pub struct StructView<'a> {
bytes: &'a [u8],
bitmap_width: usize,
num_fields: usize,
fixed_end: usize,
}
impl<'a> StructView<'a> {
pub fn new(bytes: &'a [u8], num_fields: usize) -> Result<Self, Error> {
let bitmap_width = bitmap_width(num_fields)?;
let slots_size = num_fields
.checked_mul(8)
.ok_or_else(|| Error::invalid_data("row fixed region size overflow"))?;
let fixed_end = bitmap_width
.checked_add(slots_size)
.ok_or_else(|| Error::invalid_data("row fixed region size overflow"))?;
ensure_range(bytes, 0, fixed_end)?;
Ok(Self {
bytes,
bitmap_width,
num_fields,
fixed_end,
})
}
pub fn get<T: RowValue>(&self, index: usize) -> Result<T::View<'a>, Error> {
self.check_index(index)?;
let bitmap = &self.bytes[..self.bitmap_width];
if is_bit_set(bitmap, index) {
return T::read_null();
}
let slot_offset = self
.bitmap_width
.checked_add(index * 8)
.ok_or_else(|| Error::invalid_data("row field offset overflow"))?;
let value = match T::FIXED_SIZE {
Some(width) => {
slot_width(Some(width))?;
checked_slice(self.bytes, slot_offset, width)?
}
None => variable_slice(self.bytes, slot_offset, self.fixed_end)?,
};
T::read(value)
}
pub fn is_null(&self, index: usize) -> Result<bool, Error> {
self.check_index(index)?;
Ok(is_bit_set(&self.bytes[..self.bitmap_width], index))
}
fn check_index(&self, index: usize) -> Result<(), Error> {
if index >= self.num_fields {
Err(Error::buffer_out_of_bound(index, 1, self.num_fields))
} else {
Ok(())
}
}
}
impl<'a> RowView<'a> for StructView<'a> {
#[inline]
fn as_bytes(&self) -> &'a [u8] {
self.bytes
}
}
pub struct ArrayView<'a, T: RowValue> {
bytes: &'a [u8],
num_elements: usize,
bitmap_width: usize,
header_size: usize,
element_size: usize,
fixed_end: usize,
marker: PhantomData<T>,
}
impl<T: RowValue> Copy for ArrayView<'_, T> {}
impl<T: RowValue> Clone for ArrayView<'_, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, T: RowValue> ArrayView<'a, T> {
pub(crate) fn new(bytes: &'a [u8]) -> Result<Self, Error> {
let count = read_u64(bytes, 0)?;
let num_elements = usize::try_from(count)
.map_err(|_| Error::invalid_data("row array element count exceeds usize"))?;
let bitmap_width = bitmap_width(num_elements)?;
let header_size = 8usize
.checked_add(bitmap_width)
.ok_or_else(|| Error::invalid_data("row array header size overflow"))?;
let element_size = slot_width(T::FIXED_SIZE)?;
let element_bytes = num_elements
.checked_mul(element_size)
.ok_or_else(|| Error::invalid_data("row array fixed region size overflow"))?;
let aligned_element_bytes = round_up_to_word(element_bytes)?;
let fixed_end = header_size
.checked_add(aligned_element_bytes)
.ok_or_else(|| Error::invalid_data("row array fixed region size overflow"))?;
ensure_range(bytes, 0, fixed_end)?;
Ok(Self {
bytes,
num_elements,
bitmap_width,
header_size,
element_size,
fixed_end,
marker: PhantomData,
})
}
pub fn len(&self) -> usize {
self.num_elements
}
pub fn is_empty(&self) -> bool {
self.num_elements == 0
}
pub fn iter(&self) -> ArrayIter<'_, 'a, T> {
ArrayIter {
view: self,
index: 0,
}
}
pub fn get(&self, index: usize) -> Result<T::View<'a>, Error> {
self.check_index(index)?;
let bitmap = &self.bytes[8..8 + self.bitmap_width];
if is_bit_set(bitmap, index) {
return T::read_null();
}
let slot_offset = self
.header_size
.checked_add(index * self.element_size)
.ok_or_else(|| Error::invalid_data("row array element offset overflow"))?;
let value = match T::FIXED_SIZE {
Some(width) => checked_slice(self.bytes, slot_offset, width)?,
None => variable_slice(self.bytes, slot_offset, self.fixed_end)?,
};
T::read(value)
}
pub fn is_null(&self, index: usize) -> Result<bool, Error> {
self.check_index(index)?;
let bitmap_start = 8;
let bitmap = &self.bytes[bitmap_start..bitmap_start + self.bitmap_width];
Ok(is_bit_set(bitmap, index))
}
fn check_index(&self, index: usize) -> Result<(), Error> {
if index >= self.num_elements {
Err(Error::buffer_out_of_bound(index, 1, self.num_elements))
} else {
Ok(())
}
}
}
impl<'a, T: RowValue> RowView<'a> for ArrayView<'a, T> {
#[inline]
fn as_bytes(&self) -> &'a [u8] {
self.bytes
}
}
pub struct ArrayIter<'view, 'row, T: RowValue> {
view: &'view ArrayView<'row, T>,
index: usize,
}
impl<'row, T: RowValue> Iterator for ArrayIter<'_, 'row, T> {
type Item = Result<T::View<'row>, Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.index == self.view.len() {
return None;
}
let index = self.index;
self.index += 1;
Some(self.view.get(index))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.view.len() - self.index;
(remaining, Some(remaining))
}
}
impl<T: RowValue> ExactSizeIterator for ArrayIter<'_, '_, T> {}
impl<'view, 'row, T: RowValue> IntoIterator for &'view ArrayView<'row, T> {
type Item = Result<T::View<'row>, Error>;
type IntoIter = ArrayIter<'view, 'row, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
pub struct MapView<'a, K: RowValue, V: RowValue> {
bytes: &'a [u8],
keys: ArrayView<'a, K>,
values: ArrayView<'a, V>,
}
impl<K: RowValue, V: RowValue> Copy for MapView<'_, K, V> {}
impl<K: RowValue, V: RowValue> Clone for MapView<'_, K, V> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, K: RowValue, V: RowValue> MapView<'a, K, V> {
pub(crate) fn new(bytes: &'a [u8]) -> Result<Self, Error> {
let keys_size = read_u64(bytes, 0)?;
let keys_size = usize::try_from(keys_size)
.map_err(|_| Error::invalid_data("row map key array size exceeds usize"))?;
let keys_end = 8usize
.checked_add(keys_size)
.ok_or_else(|| Error::invalid_data("row map key array size overflow"))?;
ensure_range(bytes, 8, keys_size)?;
let keys = ArrayView::<K>::new(&bytes[8..keys_end])?;
let values = ArrayView::<V>::new(&bytes[keys_end..])?;
if keys.len() != values.len() {
return Err(Error::invalid_data(
"row map key and value arrays have different lengths",
));
}
Ok(Self {
bytes,
keys,
values,
})
}
pub fn len(&self) -> usize {
self.keys.len()
}
pub fn is_empty(&self) -> bool {
self.keys.is_empty()
}
pub fn key(&self, index: usize) -> Result<K::View<'a>, Error> {
self.keys.get(index)
}
pub fn value(&self, index: usize) -> Result<V::View<'a>, Error> {
self.values.get(index)
}
pub fn keys(&self) -> &ArrayView<'a, K> {
&self.keys
}
pub fn values(&self) -> &ArrayView<'a, V> {
&self.values
}
pub fn to_btree_map(
&self,
) -> Result<BTreeMap<<K as RowValue>::View<'a>, <V as RowValue>::View<'a>>, Error>
where
<K as RowValue>::View<'a>: Ord,
{
let mut map = BTreeMap::new();
for index in 0..self.keys.len() {
map.insert(self.keys.get(index)?, self.values.get(index)?);
}
Ok(map)
}
}
impl<'a, K: RowValue, V: RowValue> RowView<'a> for MapView<'a, K, V> {
#[inline]
fn as_bytes(&self) -> &'a [u8] {
self.bytes
}
}
fn variable_slice(bytes: &[u8], slot_offset: usize, fixed_end: usize) -> Result<&[u8], Error> {
let offset_and_size = read_u64(bytes, slot_offset)?;
let relative_offset = usize::try_from(offset_and_size >> 32)
.map_err(|_| Error::invalid_data("row variable offset exceeds usize"))?;
let size = (offset_and_size as u32) as usize;
if relative_offset < fixed_end {
return Err(Error::invalid_data(
"row variable value overlaps the fixed region",
));
}
checked_slice(bytes, relative_offset, size)
}
fn read_u64(bytes: &[u8], offset: usize) -> Result<u64, Error> {
let value = checked_slice(bytes, offset, 8)?;
let mut array = [0u8; 8];
array.copy_from_slice(value);
Ok(u64::from_le_bytes(array))
}
fn checked_slice(bytes: &[u8], offset: usize, size: usize) -> Result<&[u8], Error> {
let end = offset
.checked_add(size)
.ok_or_else(|| Error::buffer_out_of_bound(offset, size, bytes.len()))?;
if end > bytes.len() {
Err(Error::buffer_out_of_bound(offset, size, bytes.len()))
} else {
Ok(&bytes[offset..end])
}
}
fn ensure_range(bytes: &[u8], offset: usize, size: usize) -> Result<(), Error> {
checked_slice(bytes, offset, size).map(|_| ())
}
pub fn from_row<T: Row>(bytes: &[u8]) -> Result<T::View<'_>, Error> {
T::read(bytes)
}