use crate::{
protocol::{Wire, value::decode},
schema,
};
use std::marker;
mod cursor;
mod sealed;
pub use cursor::Cursor;
pub(crate) use sealed::Sealed;
pub trait Fields: schema::Row + Sealed {
fn read<'row>(cursor: &mut Cursor<'row>) -> Self::View<'row>;
}
pub(crate) struct Row<'row, T: Fields> {
bytes: &'row [u8],
fields: marker::PhantomData<T>,
}
impl<'row, T: Fields> Row<'row, T> {
pub(crate) fn validate(bytes: Wire<'row>, columns: u16) -> Result<(), crate::Error> {
let mut reader = decode::RowReader::new(bytes, columns)?;
T::decode(&mut reader)?;
reader.finish()
}
pub(crate) unsafe fn new(bytes: &'row [u8]) -> Self {
Self {
bytes,
fields: marker::PhantomData,
}
}
pub(crate) fn read(self) -> T::View<'row> {
let bytes = unsafe { self.bytes.get_unchecked(2..) };
T::read(&mut Cursor { bytes })
}
}
const _: () = {
assert!(size_of::<Row<'static, (i64, (String, ()))>>() == size_of::<&[u8]>());
assert!(size_of::<Cursor<'static>>() == size_of::<&[u8]>());
};
impl<A: Fields> Fields for (A, ()) {
fn read<'row>(cursor: &mut Cursor<'row>) -> Self::View<'row> {
(A::read(cursor), ())
}
}
impl<A: Fields, B: Fields> Fields for (A, B) {
fn read<'row>(cursor: &mut Cursor<'row>) -> Self::View<'row> {
(A::read(cursor), B::read(cursor))
}
}
impl Fields for bool {
fn read<'row>(cursor: &mut Cursor<'row>) -> bool {
let [value] = unsafe { cursor.fixed() };
value != 0
}
}
impl Fields for i32 {
fn read<'row>(cursor: &mut Cursor<'row>) -> i32 {
i32::from_be_bytes(unsafe { cursor.fixed() })
}
}
impl Fields for i64 {
fn read<'row>(cursor: &mut Cursor<'row>) -> i64 {
i64::from_be_bytes(unsafe { cursor.fixed() })
}
}
impl Fields for String {
fn read<'row>(cursor: &mut Cursor<'row>) -> &'row str {
unsafe { cursor.text::<0>() }
}
}
impl Fields for crate::Jsonb {
fn read<'row>(cursor: &mut Cursor<'row>) -> &'row str {
unsafe { cursor.text::<1>() }
}
}