in uniffi_macros/src/enum_.rs [161:267]
fn enum_or_error_ffi_converter_impl(
item: &EnumItem,
options: &DeriveOptions,
metadata_type_code: TokenStream,
) -> TokenStream {
let name = item.name();
let ident = item.ident();
let impl_spec = options.ffi_impl_header("FfiConverter", ident);
let derive_ffi_traits = options.derive_all_ffi_traits(ident);
let mod_path = match mod_path() {
Ok(p) => p,
Err(e) => return e.into_compile_error(),
};
let mut write_match_arms: Vec<_> = item
.enum_()
.variants
.iter()
.enumerate()
.map(|(i, v)| {
let v_ident = &v.ident;
let field_idents = v
.fields
.iter()
.enumerate()
.map(|(i, f)| {
f.ident
.clone()
.unwrap_or_else(|| Ident::new(&format!("e{i}"), f.span()))
})
.collect::<Vec<Ident>>();
let idx = Index::from(i + 1);
let write_fields =
std::iter::zip(v.fields.iter(), field_idents.iter()).map(|(f, ident)| {
let write = ffiops::write(&f.ty);
quote! { #write(#ident, buf); }
});
let is_tuple = v.fields.iter().any(|f| f.ident.is_none());
let fields = if is_tuple {
quote! { ( #(#field_idents),* ) }
} else {
quote! { { #(#field_idents),* } }
};
quote! {
Self::#v_ident #fields => {
::uniffi::deps::bytes::BufMut::put_i32(buf, #idx);
#(#write_fields)*
}
}
})
.collect();
if item.is_non_exhaustive() {
write_match_arms.push(quote! {
_ => ::std::panic!("Unexpected variant in non-exhaustive enum"),
})
}
let write_impl = quote! {
match obj { #(#write_match_arms)* }
};
let try_read_match_arms = item.enum_().variants.iter().enumerate().map(|(i, v)| {
let idx = Index::from(i + 1);
let v_ident = &v.ident;
let is_tuple = v.fields.iter().any(|f| f.ident.is_none());
let try_read_fields = v.fields.iter().map(try_read_field);
if is_tuple {
quote! {
#idx => Self::#v_ident ( #(#try_read_fields)* ),
}
} else {
quote! {
#idx => Self::#v_ident { #(#try_read_fields)* },
}
}
});
let error_format_string = format!("Invalid {name} enum value: {{}}");
let try_read_impl = quote! {
::uniffi::check_remaining(buf, 4)?;
::std::result::Result::Ok(match ::uniffi::deps::bytes::Buf::get_i32(buf) {
#(#try_read_match_arms)*
v => ::uniffi::deps::anyhow::bail!(#error_format_string, v),
})
};
quote! {
#[automatically_derived]
unsafe #impl_spec {
::uniffi::ffi_converter_rust_buffer_lift_and_lower!(crate::UniFfiTag);
fn write(obj: Self, buf: &mut ::std::vec::Vec<u8>) {
#write_impl
}
fn try_read(buf: &mut &[::std::primitive::u8]) -> ::uniffi::deps::anyhow::Result<Self> {
#try_read_impl
}
const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(#metadata_type_code)
.concat_str(#mod_path)
.concat_str(#name);
}
#derive_ffi_traits
}
}