/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
usecrate::util::{
create_metadata_items, either_attribute_arg, ident_to_string, kw, parse_comma_separated,
UniffiAttributeArgs,
}; use proc_macro2::{Ident, TokenStream}; use quote::{quote, ToTokens}; use syn::{
braced,
parse::{Parse, ParseStream},
spanned::Spanned,
token::Brace,
Expr, ExprClosure, Pat, Token, Type,
};
impl Parse for CustomTypeArgs { fn parse(input: ParseStream<'_>) -> syn::Result<Self> { // Parse the custom / UniFFI type which are both required let custom_type = input.parse()?;
input.parse::<Token![,]>()?; let uniffi_type = input.parse()?; let options = if input.peek(Token![,]) {
input.parse::<Token![,]>()?;
if input.peek(Brace) { let content;
braced!(content in input);
content.parse()?
} else {
CustomTypeOptions::default()
}
} else {
CustomTypeOptions::default()
};
Ok(Self {
custom_type,
uniffi_type,
options,
})
}
}
/// Handle extra options for the custom type macro #[derive(Default)] pubstruct CustomTypeOptions {
lower: Option<ConvertClosure>,
try_lift: Option<ConvertClosure>,
remote: Option<kw::remote>,
}
let name = match &custom_type { Type::Path(p) => match p.path.get_ident() {
Some(i) => Ok(ident_to_string(i)),
None => Err("Custom types must only have one component"),
},
_ => Err("Custom types must be specified as simple idents"),
}
.map_err(|msg| syn::Error::new(custom_type.span(), msg))?;
let (lower_param, lower_expr) = match options.lower {
Some(convert_closure) => convert_closure.token_tuple(),
None => (
quote! { val },
quote! { <#custom_typeas Into<#uniffi_type>>::into(val) },
),
}; let (try_lift, try_lift_expr) = match options.try_lift {
Some(convert_closure) => convert_closure.token_tuple(),
None => (
quote! { val },
quote! { ::core::result::Result::Ok(<#uniffi_typeas TryInto<#custom_type>>::try_into(val)?) },
),
};
let build_context = quote::quote! {
|| { let location = ::core::panic::Location::caller();
::std::format!( "Lifting custom type `{}` from FFI type `{}` failed at {}:{}",
::core::any::type_name::<#custom_type>(),
::core::any::type_name::<#uniffi_type>(),
location.file(),
location.line()
)
}
};
// We allow needless_question_mark here because the error type of `TryInto` only needs conversion // iff it is not a `anyhow::Error` already. let try_lift_expr = quote::quote! { #[allow(clippy::needless_question_mark)]
{
::uniffi::deps::anyhow::Context::with_context(
(move || -> ::uniffi::Result<#custom_type> { #try_lift_expr })(), #build_context
)
}
};
let docstring = ""; // todo... let meta_static_var = custom_type_meta_static_var(&name, &uniffi_type, docstring)?;
Ok(quote! { #[allow(non_camel_case_types)] #impl_spec { // Note: the UniFFI type needs to implement both `Lower` and `Lift'. We use the // `Lower` trait to get the associated type `FfiType` and const `TYPE_ID_META`. These // can't differ between `Lower` and `Lift`. type FfiType = <#uniffi_typeas ::uniffi::Lower<crate::UniFfiTag>>::FfiType; fn lower(#lower_param: #custom_type ) -> Self::FfiType {
<#uniffi_typeas ::uniffi::Lower<crate::UniFfiTag>>::lower(#lower_expr)
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.