@@ -24,38 +24,81 @@ struct Input {
24
24
pub ( super ) struct Opt {
25
25
/// Any additional headers to #include
26
26
pub include : Vec < String > ,
27
+ /// Whether to set __attribute__((visibility("default")))
28
+ /// or similar annotations on function implementations.
29
+ pub cxx_impl_annotations : Option < String > ,
27
30
}
28
31
29
32
pub ( super ) fn do_generate_bridge ( path : & Path , opt : Opt ) -> Vec < u8 > {
30
33
let header = false ;
31
- generate ( path, opt, header)
34
+ generate_from_path ( path, opt, header)
32
35
}
33
36
34
37
pub ( super ) fn do_generate_header ( path : & Path , opt : Opt ) -> Vec < u8 > {
35
38
let header = true ;
36
- generate ( path, opt, header)
39
+ generate_from_path ( path, opt, header)
37
40
}
38
41
39
- fn generate ( path : & Path , opt : Opt , header : bool ) -> Vec < u8 > {
42
+ fn generate_from_path ( path : & Path , opt : Opt , header : bool ) -> Vec < u8 > {
40
43
let source = match fs:: read_to_string ( path) {
41
44
Ok ( source) => source,
42
45
Err ( err) => format_err ( path, "" , Error :: Io ( err) ) ,
43
46
} ;
44
- match ( || -> Result < _ > {
45
- proc_macro2:: fallback:: force ( ) ;
46
- let ref mut errors = Errors :: new ( ) ;
47
- let syntax = syn:: parse_file ( & source) ?;
48
- let bridge = find:: find_bridge_mod ( syntax) ?;
49
- let ref namespace = bridge. namespace ;
50
- let ref apis = syntax:: parse_items ( errors, bridge. module ) ;
51
- let ref types = Types :: collect ( errors, apis) ;
52
- errors. propagate ( ) ?;
53
- check:: typecheck ( errors, namespace, apis, types) ;
54
- errors. propagate ( ) ?;
55
- let out = write:: gen ( namespace, apis, types, opt, header) ;
56
- Ok ( out)
57
- } ) ( ) {
58
- Ok ( out) => out. content ( ) ,
47
+ match generate ( & source, opt, header) {
48
+ Ok ( out) => out,
59
49
Err ( err) => format_err ( path, & source, err) ,
60
50
}
61
51
}
52
+
53
+ fn generate ( source : & str , opt : Opt , header : bool ) -> Result < Vec < u8 > > {
54
+ proc_macro2:: fallback:: force ( ) ;
55
+ let ref mut errors = Errors :: new ( ) ;
56
+ let syntax = syn:: parse_file ( & source) ?;
57
+ let bridge = find:: find_bridge_mod ( syntax) ?;
58
+ let ref namespace = bridge. namespace ;
59
+ let ref apis = syntax:: parse_items ( errors, bridge. module ) ;
60
+ let ref types = Types :: collect ( errors, apis) ;
61
+ errors. propagate ( ) ?;
62
+ check:: typecheck ( errors, namespace, apis, types) ;
63
+ errors. propagate ( ) ?;
64
+ let out = write:: gen ( namespace, apis, types, opt, header) ;
65
+ Ok ( out. content ( ) )
66
+ }
67
+
68
+ #[ cfg( test) ]
69
+ mod tests {
70
+ use crate :: gen:: { generate, Opt } ;
71
+
72
+ const CPP_EXAMPLE : & ' static str = r#"
73
+ #[cxx::bridge]
74
+ mod ffi {
75
+ extern "C" {
76
+ pub fn do_cpp_thing(foo: &str);
77
+ }
78
+ }
79
+ "# ;
80
+
81
+ #[ test]
82
+ fn test_cpp ( ) {
83
+ let opts = Opt {
84
+ include : Vec :: new ( ) ,
85
+ cxx_impl_annotations : None ,
86
+ } ;
87
+ let output = generate ( CPP_EXAMPLE , opts, false ) . unwrap ( ) ;
88
+ let output = std:: str:: from_utf8 ( & output) . unwrap ( ) ;
89
+ // To avoid continual breakage we won't test every byte.
90
+ // Let's look for the major features.
91
+ assert ! ( output. contains( "void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)" ) ) ;
92
+ }
93
+
94
+ #[ test]
95
+ fn test_annotation ( ) {
96
+ let opts = Opt {
97
+ include : Vec :: new ( ) ,
98
+ cxx_impl_annotations : Some ( "ANNOTATION" . to_string ( ) ) ,
99
+ } ;
100
+ let output = generate ( CPP_EXAMPLE , opts, false ) . unwrap ( ) ;
101
+ let output = std:: str:: from_utf8 ( & output) . unwrap ( ) ;
102
+ assert ! ( output. contains( "ANNOTATION void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)" ) ) ;
103
+ }
104
+ }
0 commit comments