/
interface_info.rs
134 lines (120 loc) · 5.3 KB
/
interface_info.rs
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use super::*;
pub struct InterfaceInfo {
pub def: TypeDef,
pub kind: InterfaceKind,
pub is_base: bool,
pub version: (u16, u16),
}
impl InterfaceInfo {
pub fn sort(result: &mut Vec<Self>) {
result.sort_by(|a, b| {
if a.is_base != b.is_base {
return a.is_base.cmp(&b.is_base);
}
if a.version != b.version {
return a.version.cmp(&b.version);
}
if a.kind != b.kind {
return a.kind.cmp(&b.kind);
}
a.def.type_name().cmp(&b.def.type_name())
});
}
pub fn gen_methods(interfaces: &[Self], gen: &Gen) -> TokenStream {
let mut method_names = BTreeMap::<String, u32>::new();
let mut tokens = TokenStream::with_capacity();
for interface in interfaces {
if interface.is_base && gen.relative.starts_with("Windows.UI.Xaml") && !interface.def.namespace().starts_with("Windows.Foundation") {
continue;
}
for (vtable_offset, method) in interface.def.methods().enumerate() {
let name = method.rust_name();
let overload = method_names.entry(name.clone()).or_insert(0);
*overload += 1;
let info = MethodInfo {
name,
vtable_offset: vtable_offset as u32 + 6,
overload: *overload,
is_deprecated: method.is_deprecated(),
};
let signature = method.signature(&interface.def.generics);
tokens.combine(&gen_winrt_method(&signature, &info, interface, gen));
}
}
tokens
}
pub fn gen_conversion(&self, from: &TokenStream, constraints: &TokenStream, features: &BTreeSet<&'static str>, gen: &Gen) -> TokenStream {
if self.def.is_exclusive() {
return TokenStream::new();
}
let into = gen_type_name(&self.def, gen);
let mut features = features.clone();
features.insert(self.def.namespace());
let cfg = gen.gen_cfg(&features);
match self.kind {
InterfaceKind::Default => {
quote! {
#cfg
impl<#constraints> ::core::convert::From<#from> for #into {
fn from(value: #from) -> Self {
unsafe { ::core::mem::transmute(value) }
}
}
#cfg
impl<#constraints> ::core::convert::From<&#from> for #into {
fn from(value: &#from) -> Self {
::core::convert::From::from(::core::clone::Clone::clone(value))
}
}
#cfg
impl<'a, #constraints> ::windows::core::IntoParam<'a, #into> for #from {
fn into_param(self) -> ::windows::core::Param<'a, #into> {
::windows::core::Param::Owned(unsafe { ::core::mem::transmute(self) })
}
}
#cfg
impl<'a, #constraints> ::windows::core::IntoParam<'a, #into> for &#from {
fn into_param(self) -> ::windows::core::Param<'a, #into> {
::windows::core::Param::Borrowed(unsafe { ::core::mem::transmute(self) })
}
}
}
}
InterfaceKind::NonDefault => {
// Note: these implement `TryFrom` instead of `From` as they are fallible since new non-default interfaces
// may be added in subsequent versions of a class.
quote! {
#cfg
impl<#constraints> ::core::convert::TryFrom<#from> for #into {
type Error = ::windows::core::Error;
fn try_from(value: #from) -> ::windows::core::Result<Self> {
::core::convert::TryFrom::try_from(&value)
}
}
#cfg
impl<#constraints> ::core::convert::TryFrom<&#from> for #into {
type Error = ::windows::core::Error;
fn try_from(value: &#from) -> ::windows::core::Result<Self> {
::windows::core::Interface::cast(value)
}
}
#cfg
impl<'a, #constraints> ::windows::core::IntoParam<'a, #into> for #from {
fn into_param(self) -> ::windows::core::Param<'a, #into> {
::windows::core::IntoParam::into_param(&self)
}
}
#cfg
impl<'a, #constraints> ::windows::core::IntoParam<'a, #into> for &#from {
fn into_param(self) -> ::windows::core::Param<'a, #into> {
::core::convert::TryInto::<#into>::try_into(self)
.map(::windows::core::Param::Owned)
.unwrap_or(::windows::core::Param::None)
}
}
}
}
_ => TokenStream::new(),
}
}
}