use crate::{
follow::{Follow, FollowBuf},
primitives::*,
vtable::VTable,
Error,
};
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Table<B> {
pub buf: B,
pub loc: usize,
}
impl<B> Table<B> {
#[inline]
pub fn new(buf: B, loc: usize) -> Self {
Table { buf, loc }
}
}
impl<B> Table<B>
where
B: std::convert::AsRef<[u8]>,
{
pub fn get_root(buf: B) -> Result<Self, Error> {
Ok(<ForwardsUOffset<Self>>::follow_buf(buf, 0)?)
}
pub fn get_size_prefixed_root(buf: B) -> Result<Self, Error> {
Ok(<SkipSizePrefix<ForwardsUOffset<Self>>>::follow_buf(buf, 0)?)
}
pub fn vtable<'a>(&'a self) -> Result<VTable<'a>, Error> {
<BackwardsSOffset<VTable<'a>>>::follow(self.buf.as_ref(), self.loc)
}
#[inline]
pub fn get<'a, T: Follow<'a> + 'a>(
&'a self,
slot_byte_loc: VOffsetT,
default: Option<T::Inner>,
) -> Result<Option<T::Inner>, Error> {
let v_offset = self.vtable()?.get(slot_byte_loc)?;
if let Some(v_offset) = v_offset {
let offset = v_offset as usize;
if offset == 0 {
return Ok(default);
}
<T>::follow(self.buf.as_ref(), self.loc + offset).map(Some)
} else {
Ok(default)
}
}
}
impl<B> FollowBuf for Table<B>
where
B: std::convert::AsRef<[u8]>,
{
type Buf = B;
type Inner = Table<B>;
#[inline]
fn follow_buf(buf: Self::Buf, loc: usize) -> Result<Self::Inner, Error> {
Ok(Table::new(buf, loc))
}
}
#[inline]
pub fn get_root<T, B>(data: B) -> Result<T::Inner, Error>
where
T: FollowBuf<Buf = B>,
B: std::convert::AsRef<[u8]>,
{
<ForwardsUOffset<T>>::follow_buf(data, 0)
}
#[inline]
pub fn get_size_prefixed_root<T, B>(data: B) -> Result<T::Inner, Error>
where
T: FollowBuf<Buf = B>,
B: std::convert::AsRef<[u8]>,
{
<SkipSizePrefix<ForwardsUOffset<T>>>::follow_buf(data, 0)
}
#[inline]
pub fn buffer_has_identifier(data: &[u8], ident: &str, size_prefixed: bool) -> Result<bool, Error> {
assert_eq!(ident.len(), FILE_IDENTIFIER_LENGTH);
let got = if size_prefixed {
<SkipSizePrefix<SkipRootOffset<FileIdentifier>>>::follow(data, 0)?
} else {
<SkipRootOffset<FileIdentifier>>::follow(data, 0)?
};
Ok(ident.as_bytes() == got)
}