cxx_qt_gen/syntax/
qtitem.rs1use crate::syntax::path::path_compare_str;
7use proc_macro2::TokenStream;
8use quote::ToTokens;
9use syn::parse::{Parse, ParseStream};
10use syn::{Attribute, Item, ItemMod, Result, Token, Visibility};
11
12#[derive(Clone, PartialEq, Eq)]
13pub enum CxxQtItem {
15 Item(Item),
17 Cxx(ItemMod),
19 CxxQt(ItemMod),
21}
22
23impl std::fmt::Debug for CxxQtItem {
24 fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
25 match self {
26 CxxQtItem::Item(v0) => {
27 let mut formatter = formatter.debug_tuple("Item");
28 formatter.field(v0);
29 formatter.finish()
30 }
31 CxxQtItem::Cxx(v0) => {
32 let mut formatter = formatter.debug_tuple("Cxx");
33 formatter.field(v0);
34 formatter.finish()
35 }
36 CxxQtItem::CxxQt(v0) => {
37 let mut formatter = formatter.debug_tuple("CxxQt");
38 formatter.field(v0);
39 formatter.finish()
40 }
41 }
42 }
43}
44
45impl Parse for CxxQtItem {
46 fn parse(input: ParseStream) -> Result<Self> {
47 let ahead = input.fork();
49 let attributes = ahead.call(Attribute::parse_outer)?;
50
51 ahead.parse::<Visibility>()?;
53 ahead.parse::<Option<Token![unsafe]>>()?;
54
55 if ahead.peek(Token![mod]) {
56 for attribute in &attributes {
57 if path_compare_str(attribute.meta.path(), &["cxx", "bridge"]) {
58 return input.parse().map(CxxQtItem::Cxx);
59 } else if path_compare_str(attribute.meta.path(), &["cxx_qt", "bridge"]) {
60 return input.parse().map(CxxQtItem::CxxQt);
61 }
62 }
63 }
64
65 input.parse().map(CxxQtItem::Item)
67 }
68}
69
70impl ToTokens for CxxQtItem {
71 fn to_tokens(&self, tokens: &mut TokenStream) {
72 match self {
73 CxxQtItem::Item(item) => {
74 item.to_tokens(tokens);
75 }
76 CxxQtItem::Cxx(module) => {
77 module.to_tokens(tokens);
78 }
79 CxxQtItem::CxxQt(module) => {
80 module.to_tokens(tokens);
81 }
82 }
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use syn::parse_quote;
90 #[test]
91 fn test_format_cxx() {
92 let cxx: CxxQtItem = parse_quote! {
93 #[cxx::bridge]
94 mod ffi {}
95 };
96 let debug_formatted = format!("{:?}", cxx);
97 assert!(debug_formatted.starts_with("Cxx(ItemMod"))
98 }
99
100 #[test]
101 fn test_format_cxx_qt() {
102 let cxx_qt: CxxQtItem = parse_quote! {
103 #[cxx_qt::bridge]
104 mod ffi {}
105 };
106 let debug_formatted = format!("{:?}", cxx_qt);
107 assert!(debug_formatted.starts_with("CxxQt(ItemMod"))
108 }
109
110 #[test]
111 fn test_format_non_cxx() {
112 let cxx: CxxQtItem = parse_quote! {
113 #[attr]
114 mod ffi {}
115 };
116 let debug_formatted = format!("{:?}", cxx);
117 assert!(debug_formatted.starts_with("Item(Item::Mod"))
118 }
119
120 #[test]
121 fn test_format_rust_item() {
122 let rust: CxxQtItem = parse_quote! {
123 struct MyStruct {
124 name: &str
125 }
126 };
127 let debug_formatted = format!("{:?}", rust);
128 assert!(debug_formatted.starts_with("Item(Item::Struct"))
129 }
130}