#![ warn( missing_docs ) ]
mod num;
mod interval;
#[ macro_export ]
macro_rules! tree_print
{
( $src : expr ) =>
{{
let result = $crate::tree_export_str!( $src );
println!( "{}", result );
result
}};
( $( $src : expr ),+ $(,)? ) =>
{{
$( $crate::tree_print!( $src ) );+
}};
}
#[ macro_export ]
macro_rules! tree_export_str
{
( $src : expr ) =>
{{
let src2 = &$src;
format!( "{} : {} :\n{:#?}", stringify!( $src ), quote!{ #src2 }, $src )
}};
}
#[derive( Debug, PartialEq, Copy, Clone )]
pub enum ContainerKind
{
No,
Vector,
HashMap,
}
pub fn type_container_kind( ty : &syn::Type ) -> ContainerKind
{
if let syn::Type::Path( path ) = ty
{
let last = &path.path.segments.last();
if last.is_none()
{
return ContainerKind::No
}
match last.unwrap().ident.to_string().as_ref()
{
"Vec" => { return ContainerKind::Vector }
"HashMap" => { return ContainerKind::HashMap }
_ => { return ContainerKind::No }
}
}
ContainerKind::No
}
pub fn type_rightmost( ty : &syn::Type ) -> Option< String >
{
if let syn::Type::Path( path ) = ty
{
let last = &path.path.segments.last();
if last.is_none()
{
return None;
}
return Some( last.unwrap().ident.to_string() );
}
None
}
use crate::interval::Interval;
pub fn type_parameters< R >( ty : &syn::Type, range : R ) -> Vec< &syn::Type >
where
R : std::convert::Into< crate::interval::IntervalInclusive >
{
let range = range.into();
if let syn::Type::Path( syn::TypePath{ path : syn::Path { ref segments, .. }, .. } ) = ty
{
let last = &segments.last();
if last.is_none()
{
return vec![ &ty ]
}
let args = &last.unwrap().arguments;
if let syn::PathArguments::AngleBracketed( ref args2 ) = args
{
let args3 = &args2.args;
let selected : Vec< &syn::Type > = args3
.iter()
.skip_while( | e | if let syn::GenericArgument::Type( _ ) = e { false } else { true } )
.skip( range.first().try_into().unwrap() )
.take( range.len().try_into().unwrap() )
.map( | e | if let syn::GenericArgument::Type( ty ) = e { ty } else { unreachable!( "Expects Type" ) } )
.collect();
return selected;
}
}
vec![ &ty ]
}
pub use syn::spanned::Spanned;
pub trait Spanned2
{
fn span2( &self ) -> proc_macro2::Span;
}
impl Spanned2 for syn::Data
{
fn span2( &self ) -> proc_macro2::Span
{
match self
{
syn::Data::Struct( syn::DataStruct { ref fields, .. } ) => fields.span(),
syn::Data::Enum( syn::DataEnum { ref variants, .. } ) => variants.span(),
syn::Data::Union( syn::DataUnion { ref fields, .. } ) => fields.span(),
}
}
}
#[ doc( hidden ) ]
pub struct Data< 'a, T >( &'a T );
#[ doc( hidden ) ]
pub trait Span1
{
fn act( self ) -> proc_macro2::Span;
}
impl< 'a, T > Span1
for Data< 'a, T >
where T : syn::spanned::Spanned,
{
fn act( self ) -> proc_macro2::Span
{
self.0.span()
}
}
#[ doc( hidden ) ]
pub trait Span2
{
fn act( self ) -> proc_macro2::Span;
}
impl< 'a, T > Span2
for Data< 'a, T >
where T : Spanned2,
{
fn act( self ) -> proc_macro2::Span
{
self.0.span2()
}
}
#[ doc( hidden ) ]
pub fn _span_of< T : Sized >( src : &T ) -> Data< T >
{
Data( src )
}
#[ macro_export ]
macro_rules! span_of
{
( $src : expr ) =>
{
$crate::_span_of( &$src ).act()
}
}
pub fn span_of< Src : Spanned2 >( src : &Src ) -> proc_macro2::Span
{
src.span2()
}