1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use crate::util::{derive_all_ffi_traits, ident_to_string, mod_path, tagged_impl_header};
use proc_macro2::{Ident, TokenStream};
use quote::quote;
use syn::Path;
// Generate an FfiConverter impl based on the UniffiCustomTypeConverter
// implementation that the library supplies
pub(crate) fn expand_ffi_converter_custom_type(
ident: &Ident,
builtin: &Path,
udl_mode: bool,
) -> syn::Result<TokenStream> {
let impl_spec = tagged_impl_header("FfiConverter", ident, udl_mode);
let derive_ffi_traits = derive_all_ffi_traits(ident, udl_mode);
let name = ident_to_string(ident);
let mod_path = mod_path()?;
Ok(quote! {
#[automatically_derived]
unsafe #impl_spec {
// Note: the builtin 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 = <#builtin as ::uniffi::Lower<crate::UniFfiTag>>::FfiType;
fn lower(obj: #ident ) -> Self::FfiType {
<#builtin as ::uniffi::Lower<crate::UniFfiTag>>::lower(<#ident as crate::UniffiCustomTypeConverter>::from_custom(obj))
}
fn try_lift(v: Self::FfiType) -> uniffi::Result<#ident> {
<#ident as crate::UniffiCustomTypeConverter>::into_custom(<#builtin as ::uniffi::Lift<crate::UniFfiTag>>::try_lift(v)?)
}
fn write(obj: #ident, buf: &mut Vec<u8>) {
<#builtin as ::uniffi::Lower<crate::UniFfiTag>>::write(<#ident as crate::UniffiCustomTypeConverter>::from_custom(obj), buf);
}
fn try_read(buf: &mut &[u8]) -> uniffi::Result<#ident> {
<#ident as crate::UniffiCustomTypeConverter>::into_custom(<#builtin as ::uniffi::Lift<crate::UniFfiTag>>::try_read(buf)?)
}
const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::TYPE_CUSTOM)
.concat_str(#mod_path)
.concat_str(#name)
.concat(<#builtin as ::uniffi::Lower<crate::UniFfiTag>>::TYPE_ID_META);
}
#derive_ffi_traits
})
}
// Generate an FfiConverter impl *and* an UniffiCustomTypeConverter.
pub(crate) fn expand_ffi_converter_custom_newtype(
ident: &Ident,
builtin: &Path,
udl_mode: bool,
) -> syn::Result<TokenStream> {
let ffi_converter = expand_ffi_converter_custom_type(ident, builtin, udl_mode)?;
let type_converter = custom_ffi_type_converter(ident, builtin)?;
Ok(quote! {
#ffi_converter
#type_converter
})
}
fn custom_ffi_type_converter(ident: &Ident, builtin: &Path) -> syn::Result<TokenStream> {
Ok(quote! {
impl crate::UniffiCustomTypeConverter for #ident {
type Builtin = #builtin;
fn into_custom(val: Self::Builtin) -> uniffi::Result<Self> {
Ok(#ident(val))
}
fn from_custom(obj: Self) -> Self::Builtin {
obj.0
}
}
})
}
|