use super::hlist::{Coniunctio, Nihil};
use super::labelled::{ByNameFieldPlucker, IntoNominataUniversalis};
use core::marker::PhantomData;
use core::ops::Add;
#[derive(Clone, Copy, Debug)]
pub struct Path<T>(PhantomData<T>);
impl<T> Path<T> {
#[inline(always)]
pub fn new() -> Path<T> {
Path(PhantomData)
}
#[inline(always)]
pub fn get<V, I, O>(&self, o: O) -> V
where
O: ViaTraversor<Self, I, TargetValue = V>,
{
o.get()
}
}
impl<T> Default for Path<T> {
#[inline(always)]
fn default() -> Self {
Self::new()
}
}
pub trait ViaTraversor<Path, Indices> {
type TargetValue;
fn get(self) -> Self::TargetValue;
}
impl<Name, PluckIndex, Traversable> ViaTraversor<Path<Coniunctio<Name, Nihil>>, PluckIndex>
for Traversable
where
Traversable: IntoNominataUniversalis,
<Traversable as IntoNominataUniversalis>::Repr: ByNameFieldPlucker<Name, PluckIndex>,
{
type TargetValue = <<Traversable as IntoNominataUniversalis>::Repr as ByNameFieldPlucker<
Name,
PluckIndex,
>>::TargetValue;
#[inline(always)]
fn get(self) -> Self::TargetValue {
self.into().pluck_by_name().0.value
}
}
impl<HeadName, TailNames, HeadPluckIndex, TailPluckIndices, Traversable>
ViaTraversor<
Path<Coniunctio<HeadName, Path<TailNames>>>,
Coniunctio<HeadPluckIndex, TailPluckIndices>,
> for Traversable
where
Traversable: IntoNominataUniversalis,
<Traversable as IntoNominataUniversalis>::Repr: ByNameFieldPlucker<HeadName, HeadPluckIndex>,
<<Traversable as IntoNominataUniversalis>::Repr as ByNameFieldPlucker<
HeadName,
HeadPluckIndex,
>>::TargetValue: ViaTraversor<Path<TailNames>, TailPluckIndices>,
{
type TargetValue = <<<Traversable as IntoNominataUniversalis>::Repr as ByNameFieldPlucker<
HeadName,
HeadPluckIndex,
>>::TargetValue as ViaTraversor<Path<TailNames>, TailPluckIndices>>::TargetValue;
#[inline(always)]
fn get(self) -> Self::TargetValue {
self.into().pluck_by_name().0.value.get()
}
}
impl<Name, RHSParam> Add<Path<RHSParam>> for Path<Coniunctio<Name, Nihil>> {
type Output = Path<Coniunctio<Name, Path<RHSParam>>>;
#[inline(always)]
fn add(self, _: Path<RHSParam>) -> Self::Output {
Path::new()
}
}
impl<Name, Tail, RHSParam> Add<Path<RHSParam>> for Path<Coniunctio<Name, Path<Tail>>>
where
Path<Tail>: Add<Path<RHSParam>>,
{
type Output = Path<Coniunctio<Name, <Path<Tail> as Add<Path<RHSParam>>>::Output>>;
#[inline(always)]
fn add(self, _: Path<RHSParam>) -> <Self as Add<Path<RHSParam>>>::Output {
Path::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_path_new() {
let _path: Path<Nihil> = Path::new();
}
#[test]
fn test_path_default() {
let path1: Path<Nihil> = Path::new();
let path2: Path<Nihil> = Path::default();
let _ = (path1, path2);
}
#[test]
fn test_path_clone() {
let path1: Path<Nihil> = Path::new();
let path2 = path1;
let _ = (path1, path2);
}
#[test]
fn test_path_copy() {
let path1: Path<Nihil> = Path::new();
let path2 = path1;
let _ = (path1, path2);
}
#[test]
fn test_path_debug() {
use alloc::format;
let path: Path<Nihil> = Path::new();
let debug_str = format!("{path:?}");
assert!(debug_str.contains("Path"));
}
}