mirror of
https://github.com/hexedtech/jni-toolbox.git
synced 2024-11-22 23:44:57 +01:00
feat: handle more complex return types
This commit is contained in:
parent
1775ea2adf
commit
78713a1b4e
4 changed files with 29 additions and 24 deletions
|
@ -2,6 +2,8 @@ use proc_macro2::{Span, TokenStream};
|
||||||
use quote::TokenStreamExt;
|
use quote::TokenStreamExt;
|
||||||
use syn::Ident;
|
use syn::Ident;
|
||||||
|
|
||||||
|
use crate::ext::bare_type;
|
||||||
|
|
||||||
pub(crate) struct ArgumentOptions {
|
pub(crate) struct ArgumentOptions {
|
||||||
pub(crate) incoming: TokenStream,
|
pub(crate) incoming: TokenStream,
|
||||||
pub(crate) transforming: TokenStream,
|
pub(crate) transforming: TokenStream,
|
||||||
|
@ -22,27 +24,6 @@ fn unpack_pat(pat: syn::Pat) -> Result<TokenStream, syn::Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bare_type(ty: Box<syn::Type>) -> Option<syn::TypePath> {
|
|
||||||
match *ty {
|
|
||||||
syn::Type::Array(a) => bare_type(a.elem),
|
|
||||||
syn::Type::BareFn(_) => None,
|
|
||||||
syn::Type::ImplTrait(_) => None,
|
|
||||||
syn::Type::Infer(_) => None,
|
|
||||||
syn::Type::Macro(_) => None,
|
|
||||||
syn::Type::Never(_) => None,
|
|
||||||
syn::Type::TraitObject(_) => None,
|
|
||||||
syn::Type::Verbatim(_) => None,
|
|
||||||
syn::Type::Ptr(p) => bare_type(p.elem),
|
|
||||||
syn::Type::Slice(s) => bare_type(s.elem),
|
|
||||||
syn::Type::Tuple(t) => bare_type(Box::new(t.elems.first()?.clone())), // TODO
|
|
||||||
syn::Type::Group(g) => bare_type(g.elem),
|
|
||||||
syn::Type::Paren(p) => bare_type(p.elem),
|
|
||||||
syn::Type::Reference(r) => bare_type(r.elem),
|
|
||||||
syn::Type::Path(ty) => Some(ty),
|
|
||||||
_ => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn type_equals(ty: Box<syn::Type>, search: impl AsRef<str>) -> bool {
|
fn type_equals(ty: Box<syn::Type>, search: impl AsRef<str>) -> bool {
|
||||||
let Some(ty) = bare_type(ty) else { return false };
|
let Some(ty) = bare_type(ty) else { return false };
|
||||||
let Some(last) = ty.path.segments.last() else { return false };
|
let Some(last) = ty.path.segments.last() else { return false };
|
||||||
|
|
21
macro/src/ext.rs
Normal file
21
macro/src/ext.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
pub(crate) fn bare_type(ty: Box<syn::Type>) -> Option<syn::TypePath> {
|
||||||
|
match *ty {
|
||||||
|
syn::Type::Array(a) => bare_type(a.elem),
|
||||||
|
syn::Type::BareFn(_) => None,
|
||||||
|
syn::Type::ImplTrait(_) => None,
|
||||||
|
syn::Type::Infer(_) => None,
|
||||||
|
syn::Type::Macro(_) => None,
|
||||||
|
syn::Type::Never(_) => None,
|
||||||
|
syn::Type::TraitObject(_) => None,
|
||||||
|
syn::Type::Verbatim(_) => None,
|
||||||
|
syn::Type::Ptr(p) => bare_type(p.elem),
|
||||||
|
syn::Type::Slice(s) => bare_type(s.elem),
|
||||||
|
syn::Type::Tuple(t) => bare_type(Box::new(t.elems.first()?.clone())), // TODO
|
||||||
|
syn::Type::Group(g) => bare_type(g.elem),
|
||||||
|
syn::Type::Paren(p) => bare_type(p.elem),
|
||||||
|
syn::Type::Reference(r) => bare_type(r.elem),
|
||||||
|
syn::Type::Path(ty) => Some(ty),
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ mod attrs;
|
||||||
mod wrapper;
|
mod wrapper;
|
||||||
mod args;
|
mod args;
|
||||||
mod ret;
|
mod ret;
|
||||||
|
mod ext;
|
||||||
|
|
||||||
/// Wrap this function in in a JNI exported fn.
|
/// Wrap this function in in a JNI exported fn.
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
|
|
|
@ -2,6 +2,8 @@ use proc_macro2::{Span, TokenStream};
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use syn::{ReturnType, Type};
|
use syn::{ReturnType, Type};
|
||||||
|
|
||||||
|
use crate::ext::bare_type;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct ReturnOptions {
|
pub(crate) struct ReturnOptions {
|
||||||
pub(crate) ty: Option<Box<Type>>,
|
pub(crate) ty: Option<Box<Type>>,
|
||||||
|
@ -16,8 +18,8 @@ impl ReturnOptions {
|
||||||
pub(crate) fn parse_signature(ret: &ReturnType) -> Result<Self, syn::Error> {
|
pub(crate) fn parse_signature(ret: &ReturnType) -> Result<Self, syn::Error> {
|
||||||
match ret {
|
match ret {
|
||||||
syn::ReturnType::Default => Ok(Self { ty: None, result: false, void: true, pointer: false }),
|
syn::ReturnType::Default => Ok(Self { ty: None, result: false, void: true, pointer: false }),
|
||||||
syn::ReturnType::Type(_tok, ty) => match *ty.clone() {
|
syn::ReturnType::Type(_tok, ty) => match bare_type(ty.clone()) {
|
||||||
syn::Type::Path(path) => {
|
Some(path) => {
|
||||||
let Some(last) = path.path.segments.last() else {
|
let Some(last) = path.path.segments.last() else {
|
||||||
return Err(syn::Error::new(Span::call_site(), "empty Result type is not valid"));
|
return Err(syn::Error::new(Span::call_site(), "empty Result type is not valid"));
|
||||||
};
|
};
|
||||||
|
@ -43,7 +45,7 @@ impl ReturnOptions {
|
||||||
let pointer = !PRIMITIVE_TYPES.iter().any(|t| last.ident == t);
|
let pointer = !PRIMITIVE_TYPES.iter().any(|t| last.ident == t);
|
||||||
Ok(Self { ty: Some(Box::new(Type::Path(path.clone()))), result: false, void: false, pointer })
|
Ok(Self { ty: Some(Box::new(Type::Path(path.clone()))), result: false, void: false, pointer })
|
||||||
},
|
},
|
||||||
_ => Err(syn::Error::new(Span::call_site(), "unsupported return type")),
|
None => Err(syn::Error::new(Span::call_site(), "unsupported return type")),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue