use quote::quote;
use syn::Type;
pub fn get_v8_local_inner_type(ty: &Type) -> Option<String> {
if let Type::Path(type_path) = ty {
let segments: Vec<_> = type_path.path.segments.iter().collect();
let local_segment =
if segments.len() == 2 && segments[0].ident == "v8" && segments[1].ident == "Local" {
Some(&segments[1])
} else if segments.len() == 1 && segments[0].ident == "Local" {
Some(&segments[0])
} else {
None
};
if let Some(segment) = local_segment {
if let syn::PathArguments::AngleBracketed(args) = &segment.arguments {
if let Some(syn::GenericArgument::Type(Type::Path(inner_path))) = args.args.first()
{
if let Some(last_segment) = inner_path.path.segments.last() {
return Some(last_segment.ident.to_string());
}
}
}
}
}
None
}
pub fn is_result_type(ty: &Type) -> bool {
if let Type::Path(type_path) = ty {
if let Some(segment) = type_path.path.segments.last() {
return segment.ident == "Result";
}
}
false
}
pub fn get_option_inner_type(ty: &Type) -> Option<&Type> {
if let Type::Path(type_path) = ty {
if let Some(segment) = type_path.path.segments.last() {
if segment.ident == "Option" {
if let syn::PathArguments::AngleBracketed(args) = &segment.arguments {
if let Some(syn::GenericArgument::Type(inner_ty)) = args.args.first() {
return Some(inner_ty);
}
}
}
}
}
None
}
pub fn get_rc_inner_type(ty: &Type) -> Option<&Type> {
if let Type::Path(type_path) = ty {
if let Some(segment) = type_path.path.segments.last() {
if segment.ident == "Rc" {
if let syn::PathArguments::AngleBracketed(args) = &segment.arguments {
if let Some(syn::GenericArgument::Type(inner_ty)) = args.args.first() {
return Some(inner_ty);
}
}
}
}
}
None
}
pub fn v8_local_extraction(
name: &syn::Ident,
idx: i32,
v8_type: &str,
check_method: &str,
) -> proc_macro2::TokenStream {
let v8_type_ident = syn::Ident::new(v8_type, name.span());
let check_ident = syn::Ident::new(check_method, name.span());
let error_msg = format!("argument {} must be a {}", idx, v8_type);
quote! {
let __v8g_tmp = args.get(#idx);
if !__v8g_tmp.#check_ident() {
let msg = v8::String::new(scope, #error_msg).unwrap();
let err = v8::Exception::type_error(scope, msg);
scope.throw_exception(err);
return;
}
let #name: v8::Local<v8::#v8_type_ident> = __v8g_tmp.try_into().unwrap();
}
}