use std::marker::PhantomData;
use std::ptr::NonNull;
use crate::term::TTerm;
use crate::triple::Triple;
mod _unsafe_triple;
pub(crate) use _unsafe_triple::*;
pub trait TripleStreamingMode {
type UnsafeTriple: UnsafeTriple;
}
#[derive(Debug)]
pub struct ByValue<T: Triple>(PhantomData<T>);
impl<T: Triple> TripleStreamingMode for ByValue<T> {
type UnsafeTriple = T;
}
#[derive(Debug)]
pub struct ByRef<T: Triple>(PhantomData<T>);
impl<T: Triple> TripleStreamingMode for ByRef<T> {
type UnsafeTriple = NonNull<T>;
}
#[derive(Debug)]
pub struct ByTermRefs<T: TTerm + ?Sized>(PhantomData<*const T>);
impl<T: TTerm + ?Sized> TripleStreamingMode for ByTermRefs<T> {
type UnsafeTriple = TermRefs<[NonNull<T>; 3]>;
}
#[derive(Debug)]
pub struct StreamedTriple<'a, T: TripleStreamingMode> {
_phantom: PhantomData<&'a T::UnsafeTriple>,
wrapped: T::UnsafeTriple,
}
impl<'a, T> StreamedTriple<'a, T>
where
T: TripleStreamingMode,
{
pub unsafe fn wrap(wrapped: T::UnsafeTriple) -> Self {
StreamedTriple {
_phantom: PhantomData,
wrapped,
}
}
}
impl<'a, T> StreamedTriple<'a, ByValue<T>>
where
T: Triple,
{
pub fn by_value(triple: T) -> Self {
StreamedTriple {
_phantom: PhantomData,
wrapped: triple,
}
}
}
impl<'a, T> StreamedTriple<'a, ByRef<T>>
where
T: Triple,
{
pub fn by_ref(triple: &'a T) -> Self {
StreamedTriple {
_phantom: PhantomData,
wrapped: triple.into(),
}
}
}
impl<'a, T> StreamedTriple<'a, ByTermRefs<T>>
where
T: TTerm + ?Sized,
{
pub fn by_term_refs(s: &'a T, p: &'a T, o: &'a T) -> Self {
StreamedTriple {
_phantom: PhantomData,
wrapped: TermRefs([s.into(), p.into(), o.into()]),
}
}
}
impl<'a, T> StreamedTriple<'a, T>
where
T: ScopedTripleMode<'a>,
{
pub fn scoped(triple: T::SourceTriple) -> Self {
T::scoped(triple)
}
}
impl<'a, T> Triple for StreamedTriple<'a, T>
where
T: TripleStreamingMode,
{
type Term = <T::UnsafeTriple as UnsafeTriple>::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() }
}
}
#[macro_export]
macro_rules! make_scoped_triple_streaming_mode {
($(#[$attrs: meta])* $mode: ident, $tt: ident) => {
$(#[$attrs])*
#[derive(Debug)]
pub struct $mode(std::marker::PhantomData<$tt<'static>>);
impl $crate::triple::streaming_mode::TripleStreamingMode for $mode {
type UnsafeTriple = $tt<'static>;
}
impl<'a> $crate::triple::streaming_mode::ScopedTripleMode<'a> for $mode {
type SourceTriple = $tt<'a>;
fn scoped(
triple: $tt<'a>,
) -> $crate::triple::streaming_mode::StreamedTriple<'a, $mode> {
unsafe {
$crate::triple::streaming_mode::StreamedTriple::wrap(std::mem::transmute(
triple,
))
}
}
}
};
}
pub trait ScopedTripleMode<'a>: TripleStreamingMode + Sized {
type SourceTriple: Triple + 'a;
fn scoped(triple: Self::SourceTriple) -> StreamedTriple<'a, Self>;
}
pub(crate) use crate::quad::streaming_mode::FromQuad;
#[derive(Debug)]
pub struct FromTriple<T: TripleStreamingMode>(PhantomData<T>);
impl<T: TripleStreamingMode> crate::quad::streaming_mode::QuadStreamingMode for FromTriple<T> {
type UnsafeQuad = UnsafeQuadAdapter<T::UnsafeTriple>;
}
impl<'a, T> crate::quad::streaming_mode::StreamedQuad<'a, FromTriple<T>>
where
T: TripleStreamingMode,
{
pub(crate) fn from_triple(triple: StreamedTriple<T>) -> Self {
unsafe { Self::wrap(UnsafeQuadAdapter(triple.wrapped)) }
}
}