use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens};
use syn::{Ident, Type};
fn suffixed(name: impl ToTokens, suffix: &str) -> Ident {
Ident::new(
&format!("{}{}", name.to_token_stream(), suffix),
Span::call_site(),
)
}
macro_rules! generated_names {
($($(#[$doc:meta])* $func:ident => $suffix:literal,)*) => {
$(
$(#[$doc])*
pub fn $func(name: impl ToTokens) -> Ident {
suffixed(name, $suffix)
}
)*
};
}
generated_names! {
vec_name => "Vec",
slice_name => "Slice",
slice_mut_name => "SliceMut",
ref_name => "Ref",
ref_mut_name => "RefMut",
iter_name => "Iter",
iter_mut_name => "IterMut",
ptr_name => "Ptr",
ptr_mut_name => "PtrMut",
drain_name => "Drain",
chunks_name => "Chunks",
chunks_mut_name => "ChunksMut",
chunks_exact_name => "ChunksExact",
chunks_exact_mut_name => "ChunksExactMut",
}
macro_rules! nested_types {
($($(#[$doc:meta])* $func:ident => ($compact:ident, $plain:ident $(, $lt:lifetime)?),)*) => {
$(
$(#[$doc])*
pub fn $func(
field_type: &Type,
compact: Option<&Type>,
) -> TokenStream {
match compact {
Some(inner) => {
quote! { ::layout::$compact<$($lt,)? #inner> }
}
None => {
let id = $plain(field_type);
quote! { #id $(<$lt>)? }
}
}
}
)*
};
}
nested_types! {
nested_vec_ty => (CompactVec, vec_name),
nested_slice_ty => (CompactSlice, slice_name, 'a),
nested_slice_mut_ty => (CompactSliceMut, slice_mut_name, 'a),
nested_ref_mut_ty => (CompactRefMut, ref_mut_name, 'a),
nested_ptr_ty => (CompactPtr, ptr_name),
nested_ptr_mut_ty => (CompactPtrMut, ptr_mut_name),
nested_drain_ty => (CompactDrain, drain_name, 'a),
}