use std::marker::PhantomData;
use super::Unpacker;
pub trait View<'a>: Sized {
type View;
type ListView;
fn unpack_view(u: &mut Unpacker<'a>) -> Option<Self::View>;
fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView>;
}
pub fn read_view<'a, T: View<'a>>(bytes: &'a [u8]) -> Option<T::View> {
let mut u = Unpacker::open(bytes)?;
let v = T::unpack_view(&mut u)?;
u.at_end().then_some(v)
}
pub struct List<'a, T> {
u: Unpacker<'a>,
len: usize,
item: PhantomData<fn() -> T>,
}
impl<'a, T> Clone for List<'a, T> {
fn clone(&self) -> Self {
List {
u: self.u.fork(self.u.position()),
len: self.len,
item: PhantomData,
}
}
}
impl<T> std::fmt::Debug for List<'_, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "List({} items)", self.len)
}
}
impl<'a, T: View<'a>> List<'a, T> {
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn iter(&self) -> ListIter<'a, T> {
ListIter {
u: self.u.fork(self.u.position()),
left: self.len,
item: PhantomData,
}
}
pub fn get(&self, i: usize) -> Option<T::View> {
self.iter().nth(i)
}
}
pub struct ListIter<'a, T> {
u: Unpacker<'a>,
left: usize,
item: PhantomData<fn() -> T>,
}
impl<'a, T: View<'a>> Iterator for ListIter<'a, T> {
type Item = T::View;
fn next(&mut self) -> Option<T::View> {
self.left = self.left.checked_sub(1)?;
T::unpack_view(&mut self.u)
}
}
pub fn list<'a, T: View<'a>>(u: &mut Unpacker<'a>) -> Option<List<'a, T>> {
let (len, end) = u.list()?;
let at = u.position();
u.skip_to(end)?;
Some(List {
u: u.fork(at),
len,
item: PhantomData,
})
}
impl<'a> View<'a> for bool {
type View = bool;
type ListView = List<'a, bool>;
fn unpack_view(u: &mut Unpacker<'a>) -> Option<bool> {
u.get_bool()
}
fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView> {
list(u)
}
}
impl<'a> View<'a> for String {
type View = &'a str;
type ListView = List<'a, Self>;
fn unpack_view(u: &mut Unpacker<'a>) -> Option<&'a str> {
u.get_str()
}
fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView> {
list(u)
}
}
impl<'a> View<'a> for Box<str> {
type View = &'a str;
type ListView = List<'a, Self>;
fn unpack_view(u: &mut Unpacker<'a>) -> Option<&'a str> {
u.get_str()
}
fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView> {
list(u)
}
}
impl<'a> View<'a> for crate::Atom {
type View = crate::Atom;
type ListView = List<'a, crate::Atom>;
fn unpack_view(u: &mut Unpacker<'a>) -> Option<crate::Atom> {
<crate::Atom as crate::Schema>::unpack(u)
}
fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView> {
list(u)
}
}
impl<'a, T: View<'a>> View<'a> for Option<T> {
type View = Option<T::View>;
type ListView = List<'a, Option<T>>;
fn unpack_view(u: &mut Unpacker<'a>) -> Option<Option<T::View>> {
if u.get_bool()? {
T::unpack_view(u).map(Some)
} else {
Some(None)
}
}
fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView> {
list(u)
}
}
impl<'a, T: View<'a>> View<'a> for Box<T> {
type View = T::View;
type ListView = T::ListView;
fn unpack_view(u: &mut Unpacker<'a>) -> Option<T::View> {
T::unpack_view(u)
}
fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<T::ListView> {
T::unpack_list_view(u)
}
}
impl<'a, T: View<'a>> View<'a> for Vec<T> {
type View = T::ListView;
type ListView = List<'a, Vec<T>>;
fn unpack_view(u: &mut Unpacker<'a>) -> Option<T::ListView> {
T::unpack_list_view(u)
}
fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView> {
list(u)
}
}
#[derive(Debug, Clone, Copy)]
pub struct Ints<'a, T> {
bytes: &'a [u8],
len: usize,
bits: u32,
signed: bool,
item: PhantomData<fn() -> T>,
}
impl<T: TryFrom<i128>> Ints<'_, T> {
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn get(&self, i: usize) -> Option<T> {
if i >= self.len {
return None;
}
let raw = super::lanes::get(self.bytes, self.len, self.bits, i);
let n = if self.signed {
i128::from(crate::binary::unzigzag(raw))
} else {
i128::from(raw)
};
T::try_from(n).ok()
}
pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
(0..self.len).map_while(|i| self.get(i))
}
}
#[derive(Debug, Clone, Copy)]
pub struct Floats<'a, T> {
bytes: &'a [u8],
len: usize,
narrow: bool,
item: PhantomData<fn() -> T>,
}
const F32_BYTES: usize = 4;
const F64_BYTES: usize = 8;
impl<T: From<f32> + FromF64> Floats<'_, T> {
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn get(&self, i: usize) -> Option<T> {
if i >= self.len {
return None;
}
if self.narrow {
let b = self.bytes.get(i * F32_BYTES..(i + 1) * F32_BYTES)?;
Some(T::from(f32::from_le_bytes(b.try_into().ok()?)))
} else {
let b = self.bytes.get(i * F64_BYTES..(i + 1) * F64_BYTES)?;
Some(T::from_f64(f64::from_le_bytes(b.try_into().ok()?)))
}
}
pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
(0..self.len).map_while(|i| self.get(i))
}
}
pub trait FromF64 {
fn from_f64(f: f64) -> Self;
}
impl FromF64 for f64 {
fn from_f64(f: f64) -> Self {
f
}
}
impl FromF64 for f32 {
fn from_f64(f: f64) -> Self {
f as f32
}
}
macro_rules! int_views {
($($t:ty => $signed:expr),*) => {$(
impl<'a> View<'a> for $t {
type View = $t;
type ListView = Ints<'a, $t>;
fn unpack_view(u: &mut Unpacker<'a>) -> Option<$t> {
<$t as crate::Schema>::unpack(u)
}
fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Ints<'a, $t>> {
let (len, bits, bytes) = u.packed_ints()?;
Some(Ints { bytes, len, bits, signed: $signed, item: PhantomData })
}
}
)*};
}
int_views!(i8 => true, i16 => true, i32 => true, i64 => true, u8 => false, u16 => false, u32 => false, u64 => false, usize => false);
macro_rules! float_views {
($($t:ty => $wide:expr),*) => {$(
impl<'a> View<'a> for $t {
type View = $t;
type ListView = Floats<'a, $t>;
fn unpack_view(u: &mut Unpacker<'a>) -> Option<$t> {
<$t as crate::Schema>::unpack(u)
}
fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Floats<'a, $t>> {
let (len, narrow, bytes) = u.packed_floats($wide)?;
Some(Floats { bytes, len, narrow, item: PhantomData })
}
}
)*};
}
float_views!(f32 => false, f64 => true);