use std::marker::PhantomData;
use std::ptr::NonNull;
use crate::quad::Quad;
use crate::term::TTerm;
mod _unsafe_quad;
pub(crate) use _unsafe_quad::*;
pub trait QuadStreamingMode {
type UnsafeQuad: UnsafeQuad;
}
#[derive(Debug)]
pub struct ByValue<Q: Quad>(PhantomData<Q>);
impl<Q: Quad> QuadStreamingMode for ByValue<Q> {
type UnsafeQuad = Q;
}
#[derive(Debug)]
pub struct ByRef<Q: Quad>(PhantomData<Q>);
impl<Q: Quad> QuadStreamingMode for ByRef<Q> {
type UnsafeQuad = NonNull<Q>;
}
#[derive(Debug)]
pub struct ByTermRefs<T: TTerm + ?Sized>(PhantomData<*const T>);
impl<T: TTerm + ?Sized> QuadStreamingMode for ByTermRefs<T> {
#[allow(clippy::type_complexity)]
type UnsafeQuad = TermRefs<([NonNull<T>; 3], Option<NonNull<T>>)>;
}
#[derive(Debug)]
pub struct StreamedQuad<'a, T: QuadStreamingMode> {
_phantom: PhantomData<&'a T::UnsafeQuad>,
wrapped: T::UnsafeQuad,
}
impl<'a, T> StreamedQuad<'a, T>
where
T: QuadStreamingMode,
{
pub unsafe fn wrap(wrapped: T::UnsafeQuad) -> Self {
StreamedQuad {
_phantom: PhantomData,
wrapped,
}
}
}
impl<'a, Q> StreamedQuad<'a, ByValue<Q>>
where
Q: Quad,
{
pub fn by_value(quad: Q) -> Self {
StreamedQuad {
_phantom: PhantomData,
wrapped: quad,
}
}
}
impl<'a, Q> StreamedQuad<'a, ByRef<Q>>
where
Q: Quad,
{
pub fn by_ref(quad: &'a Q) -> Self {
StreamedQuad {
_phantom: PhantomData,
wrapped: quad.into(),
}
}
}
impl<'a, T> StreamedQuad<'a, ByTermRefs<T>>
where
T: TTerm + ?Sized,
{
pub fn by_term_refs(s: &'a T, p: &'a T, o: &'a T, g: Option<&'a T>) -> Self {
StreamedQuad {
_phantom: PhantomData,
wrapped: TermRefs(([s.into(), p.into(), o.into()], g.map(|g| g.into()))),
}
}
}
impl<'a, T> StreamedQuad<'a, T>
where
T: ScopedQuadMode<'a>,
{
pub fn scoped(quad: T::SourceQuad) -> Self {
T::scoped(quad)
}
}
impl<'a, T> Quad for StreamedQuad<'a, T>
where
T: QuadStreamingMode,
{
type Term = <T::UnsafeQuad as UnsafeQuad>::Term;
fn s(&self) -> &Self::Term {
unsafe { self.wrapped.u_s() }
}
fn p(&self) -> &Self::Term {
unsafe { self.wrapped.u_p() }
}
fn o(&self) -> &Self::Term {
unsafe { self.wrapped.u_o() }
}
fn g(&self) -> Option<&Self::Term> {
unsafe { self.wrapped.u_g() }
}
}
#[macro_export]
macro_rules! make_scoped_quad_streaming_mode {
($(#[$attrs: meta])* $mode: ident, $qt: ident) => {
$(#[$attrs])*
#[derive(Debug)]
pub struct $mode(std::marker::PhantomData<$qt<'static>>);
impl $crate::quad::streaming_mode::QuadStreamingMode for $mode {
type UnsafeQuad = $qt<'static>;
}
impl<'a> $crate::quad::streaming_mode::ScopedQuadMode<'a> for $mode {
type SourceQuad = $qt<'a>;
fn scoped(quad: $qt<'a>) -> $crate::quad::streaming_mode::StreamedQuad<'a, $mode> {
unsafe {
$crate::quad::streaming_mode::StreamedQuad::wrap(std::mem::transmute(quad))
}
}
}
};
}
pub trait ScopedQuadMode<'a>: QuadStreamingMode + Sized {
type SourceQuad: Quad + 'a;
fn scoped(quad: Self::SourceQuad) -> StreamedQuad<'a, Self>;
}
pub(crate) use crate::triple::streaming_mode::FromTriple;
#[derive(Debug)]
pub struct FromQuad<T: QuadStreamingMode>(PhantomData<T>);
impl<T: QuadStreamingMode> crate::triple::streaming_mode::TripleStreamingMode for FromQuad<T> {
type UnsafeTriple = UnsafeTripleAdapter<T::UnsafeQuad>;
}
impl<'a, Q> crate::triple::streaming_mode::StreamedTriple<'a, FromQuad<Q>>
where
Q: QuadStreamingMode,
{
pub(crate) fn from_quad(quad: StreamedQuad<Q>) -> Self {
unsafe { Self::wrap(UnsafeTripleAdapter(quad.wrapped)) }
}
}