use crate::tokens::{Tokenize, TokenizeContext};
use proc_macro2::{Span, TokenStream};
use proc_macro_crate::{crate_name, FoundCrate};
use quote::quote;
use std::collections::HashMap;
use syn::{parse_quote, Ident, Path};
#[inline]
pub fn root_crate() -> Path {
get_crate("vimwiki")
.or_else(|_| get_crate("vimwiki-core"))
.expect("vimwiki crate exists")
}
fn get_crate(cname: &str) -> syn::Result<Path> {
crate_name(cname)
.map(|found_crate| match found_crate {
FoundCrate::Itself => {
parse_quote!(::vimwiki)
}
FoundCrate::Name(name) => {
let crate_ident = Ident::new(&name, Span::mixed_site());
parse_quote!(::#crate_ident)
}
})
.map_err(|msg| syn::Error::new(Span::mixed_site(), msg))
}
#[inline]
pub fn vendor_path() -> TokenStream {
let root = root_crate();
quote! { #root::vendor }
}
#[inline]
pub fn tokenize_cow_str_type() -> TokenStream {
quote! { ::std::borrow::Cow<'_, str >}
}
pub fn tokenize_hashmap<K: Tokenize, V: Tokenize>(
m: &HashMap<K, V>,
kty: TokenStream,
vty: TokenStream,
fk: impl Fn(&K) -> TokenStream,
fv: impl Fn(&V) -> TokenStream,
) -> TokenStream {
let pairs = m.iter().map(|(k, v)| {
let tk = fk(k);
let tv = fv(v);
quote! { (#tk, #tv) }
});
quote! {
::std::iter::Iterator::collect::<::std::collections::HashMap<#kty,#vty>>(
::std::vec![#(#pairs),*].drain(..),
)
}
}
pub fn tokenize_option<T: Tokenize>(
ctx: &TokenizeContext,
o: &Option<T>,
f: impl Fn(&TokenizeContext, &T) -> TokenStream,
) -> TokenStream {
if let Some(x) = o {
let t = f(ctx, x);
quote! { ::std::option::Option::Some(#t) }
} else {
quote! { ::std::option::Option::None }
}
}