use crate::prelude::*;
use crate::rename_col::RenameCol;
use core::ops::{Deref,DerefMut};
use core::borrow::{Borrow,BorrowMut};
use tylisp::LispId;
pub trait Col: 'static
+ Clone
+ From<<Self as Col>::Inner>
+ Into<<Self as Col>::Inner>
+ Deref<Target = <Self as Col>::Inner>
+ DerefMut
+ AsRef<<Self as Col>::Inner>
+ AsMut<<Self as Col>::Inner>
+ Borrow<<Self as Col>::Inner>
+ BorrowMut<<Self as Col>::Inner>
+ ColProxy< For=Self >
+ LispId
+ crate::record::Record<Cols=tylisp::sexpr!{Self}>
+ tylisp::engine::Eval<Result=Self>
{
type Inner;
fn wrap_ref(x: &Self::Inner)->&Self;
fn wrap_mut(x: &mut Self::Inner)->&mut Self;
fn inner_ref(&self)->&Self::Inner { self.deref() }
fn rename<New: Col<Inner=Self::Inner>>(self)->New
{ New::from(<Self as Into<Self::Inner>>::into(self) ) }
fn rename_ref<New: Col<Inner=Self::Inner>>(&self)->&New
{ New::wrap_ref(self.deref()) }
fn rename_mut<New: Col<Inner=Self::Inner>>(&mut self)->&mut New
{ New::wrap_mut(self.deref_mut()) }
}
pub trait ColProxy {
type For: Col;
fn into_col(self)->Self::For;
fn col_ref(&self)->&Self::For;
}
#[macro_export]
macro_rules! col {
($viz:vis $name:ident : $ty:ty $(; $($derive:ident),*)?) => {
#[repr(transparent)]
#[derive(Debug, Copy, Clone, Hash, Default,
Ord, PartialOrd, Eq, PartialEq
$($(, $derive)*)?)]
$viz struct $name<T=$ty>(pub T);
impl $crate::col::Col for $name {
type Inner = $ty;
fn wrap_ref(x: &Self::Inner)->&Self { x.into() }
fn wrap_mut(x: &mut Self::Inner)->&mut Self { x.into() }
}
$crate::prelude::tylisp::non_calc_literal!{$name}
impl ::core::convert::From<$ty> for $name {
fn from(x:$ty)->Self { $name(x) }
}
impl ::core::convert::Into<$ty> for $name {
fn into(self)->$ty { self.0 }
}
impl<T> ::core::borrow::Borrow<T> for $name
where $ty: ::core::borrow::Borrow<T> {
fn borrow(&self)->&T { <$ty as ::core::borrow::Borrow<T>>::borrow(&self.0) }
}
impl<T> ::core::borrow::BorrowMut<T> for $name
where $ty: ::core::borrow::BorrowMut<T> {
fn borrow_mut(&mut self)->&mut T { self.0.borrow_mut() }
}
impl ::core::ops::Deref for $name {
type Target = $ty;
fn deref(&self)->&$ty { &self.0 }
}
impl ::core::ops::DerefMut for $name {
fn deref_mut(&mut self)->&mut $ty { &mut self.0 }
}
impl ::core::convert::AsRef<$ty> for $name {
fn as_ref(&self)->&$ty { &self.0 }
}
impl ::core::convert::AsMut<$ty> for $name {
fn as_mut(&mut self)->&mut $ty { &mut self.0 }
}
impl<AAAAA:$crate::col::Col, BBBBB:$crate::col::Col<Inner=AAAAA::Inner>, Renamed>
$crate::rename_col::RenameCol<AAAAA,BBBBB> for $name
where
$crate::tylisp::sexpr!{$crate::tylisp::ops::If,
{$crate::tylisp::ops::Is, @AAAAA, @$name},
@BBBBB,
@$name
}: tylisp::engine::Eval<Result = Renamed>,
Renamed: $crate::col::Col<Inner = $ty>
{
type Renamed = Renamed;
fn rename_col(self)->Renamed { <Self as $crate::col::Col>::rename(self) }
}
impl<'a, AAAAA:$crate::col::Col, BBBBB:$crate::col::Col<Inner=AAAAA::Inner>, Renamed>
$crate::rename_col::RenameCol<AAAAA,BBBBB> for &'a $name
where
$crate::tylisp::sexpr!{$crate::tylisp::ops::If,
{$crate::tylisp::ops::Is, @AAAAA, @$name},
@BBBBB,
@$name
}: tylisp::engine::Eval<Result = Renamed>,
Renamed: $crate::col::Col<Inner = $ty>
{
type Renamed = &'a Renamed;
fn rename_col(self)->&'a Renamed { <$name as $crate::col::Col>::rename_ref(self) }
}
impl<'a> ::core::convert::From<&'a $ty> for &'a $name {
fn from(x: &'a $ty)->&'a $name {
unsafe { std::mem::transmute(x) }
}
}
impl<'a> ::core::convert::From<&'a mut $ty> for &'a mut $name {
fn from(x: &'a mut $ty)->&'a mut $name {
unsafe { std::mem::transmute(x) }
}
}
impl $crate::col::ColProxy for $name {
type For = Self;
#[inline(always)]
fn into_col(self)->Self::For { self }
#[inline(always)]
fn col_ref(&self)->&Self::For { self }
}
impl $crate::record::Record for $name {
type Cols = $crate::tylisp::sexpr!{Self};
#[inline(always)]
fn into_cols(self)->Self::Cols {
$crate::tylisp::sexpr_val!{self}
}
#[inline(always)]
fn clone_cols(&self)->Self::Cols {
$crate::tylisp::sexpr_val!{self.clone()}
}
#[inline(always)]
fn col_ref<C:$crate::col::Col>(&self)->&C { match self.col_opt() {
Some(x) => x,
None => { unreachable!() }
}
}
#[inline(always)]
fn col_opt<C:$crate::col::Col>(&self)->Option<&C> {
(self as &dyn ::core::any::Any).downcast_ref()
}
}
impl $crate::record::FromRecordImpl for $name {
type Cols = $crate::tylisp::sexpr!{Self};
fn from_rec_raw(rec: impl $crate::record::Record<Cols=Self::Cols>)->Self {
rec.into_cols().head
}
}
impl<'a> $crate::record::FromExternalRecord<'a> for $name {
type Cols = $crate::tylisp::sexpr!{Self};
fn from_ext_rec_raw(rec: impl $crate::record::ExternalRecord<'a,Cols=Self::Cols>)->Self {
rec.into_cols().head
}
}
impl<'a> $crate::record::FromExternalRecord<'a> for &'a $name {
type Cols = $crate::tylisp::sexpr!{$name};
fn from_ext_rec_raw(rec: impl $crate::record::ExternalRecord<'a,Cols=Self::Cols>)->Self {
rec.ext_col_ref()
}
}
}
}
macro_rules! proxy_impls {
(< $param:tt > $( $ptr:ty ),* $(,)?) => {$(
impl<$param:Col> ColProxy for $ptr {
type For = $param;
fn into_col(self)->Self::For { (*self).clone() }
fn col_ref(&self)->&Self::For { self.deref() }
}
)*}
}
proxy_impls!{<C>
&C,
Box<C>,
}
proxy_impls!{<C>
std::rc::Rc<C>,
std::sync::Arc<C>,
}
#[cfg(test)] mod test {
use super::*;
#[derive(Clone)]
struct MyStruct;
col!{ TestField2: MyStruct }
}