cxx_qt_gen/generator/rust/
mod.rs1pub mod constructor;
7pub mod cxxqttype;
8pub mod externcxxqt;
9pub mod fragment;
10pub mod inherit;
11pub mod method;
12pub mod property;
13pub mod qenum;
14pub mod qobject;
15pub mod signals;
16pub mod threading;
17
18use crate::generator::{rust::fragment::GeneratedRustFragment, structuring};
19use crate::parser::{parameter::ParsedFunctionParameter, Parser};
20use proc_macro2::{Ident, TokenStream};
21use quote::quote;
22use syn::{parse_quote, ItemMod, Result};
23
24pub struct GeneratedRustBlocks {
26 pub cxx_mod: ItemMod,
28 pub namespace: String,
30 pub fragments: Vec<GeneratedRustFragment>,
32}
33
34impl GeneratedRustBlocks {
35 pub fn from(parser: &Parser) -> Result<GeneratedRustBlocks> {
37 let structures = structuring::Structures::new(&parser.cxx_qt_data)?;
38
39 let mut fragments = vec![];
40 fragments.extend(
41 structures
42 .qobjects
43 .iter()
44 .map(|qobject| GeneratedRustFragment::from_qobject(qobject, &parser.type_names))
45 .collect::<Result<Vec<GeneratedRustFragment>>>()?,
46 );
47 fragments.extend(
48 parser
49 .cxx_qt_data
50 .extern_cxxqt_blocks
51 .iter()
52 .map(|extern_cxx_block| {
53 GeneratedRustFragment::from_extern_cxx_qt(extern_cxx_block, &parser.type_names)
54 })
55 .collect::<Result<Vec<GeneratedRustFragment>>>()?,
56 );
57
58 let namespace = parser.cxx_qt_data.namespace.clone().unwrap_or_default();
59 let passthrough_mod = &parser.passthrough_module;
60
61 let vis = &passthrough_mod.vis;
62 let ident = &passthrough_mod.module_ident;
63 let docs = &passthrough_mod.docs;
64 let module = passthrough_mod.items.clone().map_or(
65 quote! {
67 #vis mod #ident;
68 },
69 |items| {
70 quote! {
71 #vis mod #ident {
72 #(#items)*
73 }
74 }
75 },
76 );
77 let cxx_mod = parse_quote! {
78 #[cxx::bridge(namespace = #namespace)]
79 #[allow(unused_unsafe)]
83 #(#docs)*
84 #module
85 };
86
87 let qenums = &parser.cxx_qt_data.qenums;
88 if !qenums.is_empty() {
89 fragments.extend(qenum::generate(qenums));
90 }
91
92 Ok(GeneratedRustBlocks {
93 cxx_mod,
94 namespace,
95 fragments,
96 })
97 }
98}
99
100pub fn get_params_tokens(
102 mutable: bool,
103 parameters: &[ParsedFunctionParameter],
104 class_name: &Ident,
105) -> TokenStream {
106 let struct_sig = if mutable {
107 quote! { Pin<&mut #class_name> }
108 } else {
109 quote! { &#class_name }
110 };
111 if parameters.is_empty() {
112 quote! { self: #struct_sig }
113 } else {
114 let parameters = parameters
115 .iter()
116 .map(|parameter| {
117 let ident = ¶meter.ident;
118 let ty = ¶meter.ty;
119 quote! { #ident: #ty }
120 })
121 .collect::<Vec<TokenStream>>();
122 quote! { self: #struct_sig, #(#parameters),* }
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129 use syn::parse_quote;
130
131 #[test]
132 fn test_generated_rust_blocks() {
133 let module: ItemMod = parse_quote! {
134 #[cxx_qt::bridge]
135 mod ffi {
136 extern "RustQt" {
137 #[qobject]
138 type MyObject = super::MyObjectRust;
139 }
140 }
141 };
142 let parser = Parser::from(module).unwrap();
143
144 let rust = GeneratedRustBlocks::from(&parser).unwrap();
145 assert!(rust.cxx_mod.content.is_none());
146 assert_eq!(rust.namespace, "");
147 assert_eq!(rust.fragments.len(), 1);
148 }
149
150 #[test]
151 fn test_generated_rust_blocks_namespace() {
152 let module: ItemMod = parse_quote! {
153 #[cxx_qt::bridge(namespace = "cxx_qt")]
154 mod ffi {
155 extern "RustQt" {
156 #[qobject]
157 type MyObject = super::MyObjectRust;
158 }
159 }
160 };
161 let parser = Parser::from(module).unwrap();
162
163 let rust = GeneratedRustBlocks::from(&parser).unwrap();
164 assert!(rust.cxx_mod.content.is_none());
165 assert_eq!(rust.namespace, "cxx_qt");
166 assert_eq!(rust.fragments.len(), 1);
167 }
168
169 #[test]
170 fn test_generated_rust_blocks_foreign_qobject() {
171 let module: ItemMod = parse_quote! {
172 #[cxx_qt::bridge]
173 mod ffi {
174 extern "C++Qt" {
175 #[qobject]
176 type MyObject;
177 }
178 }
179 };
180 let parser = Parser::from(module).unwrap();
181
182 let rust = GeneratedRustBlocks::from(&parser).unwrap();
183 assert!(rust.cxx_mod.content.is_none());
184 assert_eq!(rust.namespace, "");
185 assert_eq!(rust.fragments.len(), 1);
186 }
187}