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
mod iid;
#[allow(clippy::module_inception)]
mod interface;
mod interface_impl;
mod interfaces;
mod vptr;
pub mod vtable;
pub use interface::{Interface, InterfaceMethod};
pub use interfaces::Interfaces;
use proc_macro2::{Ident, TokenStream};
use syn::Path;
use std::collections::HashMap;
use std::iter::FromIterator;
pub fn expand_interfacess(interfaces: Interfaces) -> TokenStream {
let mut out: Vec<TokenStream> = Vec::new();
for interface in interfaces.inner {
out.push(interface.to_struct_tokens());
out.push(vtable::generate(&interface).unwrap_or_else(|e| e.to_compile_error()));
out.push(vptr::generate(&interface));
out.push(interface_impl::generate(&interface));
out.push(interface.to_iid_tokens());
}
out.extend(convert_impls(interfaces.parents));
TokenStream::from_iter(out)
}
fn convert_impls(parents: HashMap<Ident, Path>) -> Vec<TokenStream> {
let mut result = Vec::new();
let interfaces: Vec<Ident> = parents.keys().cloned().collect();
for interface in interfaces {
let name = interface;
let mut current = &name;
while let Some(p) = parents.get(current) {
result.push(quote::quote! {
impl ::core::convert::From<#name> for #p {
fn from(this: #name) -> Self {
unsafe { ::core::mem::transmute(this) }
}
}
impl <'a> ::core::convert::From<&'a #name> for &'a #p {
fn from(this: &'a #name) -> Self {
unsafe { ::core::mem::transmute(this) }
}
}
#[allow(clippy::from_over_into)]
impl <'a> ::core::convert::Into<::com::Param<'a, #p>> for #name {
fn into(self) -> ::com::Param<'a, #p> {
::com::Param::Owned(self.into())
}
}
#[allow(clippy::from_over_into)]
impl <'a> ::core::convert::Into<::com::Param<'a, #p>> for &'a #name {
fn into(self) -> ::com::Param<'a, #p> {
::com::Param::Borrowed(self.into())
}
}
});
match p.get_ident() {
Some(n) => current = n,
None => break,
}
}
}
result
}