@@ -496,6 +496,7 @@ fn println_struct<W: std::io::Write>(w: &mut W, s: &syn::ItemStruct, types: &mut
496
496
and_token : syn:: Token !( & ) ( Span :: call_site ( ) ) , lifetime : None , mutability : None ,
497
497
elem : Box :: new ( field. ty . clone ( ) ) } ) ;
498
498
if types. understood_c_type ( & ref_type, Some ( & gen_types) ) {
499
+ println_docs ( w, & field. attrs , "" ) ;
499
500
write ! ( w, "#[no_mangle]\n pub extern \" C\" fn {}_get_{}(this_ptr: &{}) -> " , struct_name, ident, struct_name) . unwrap ( ) ;
500
501
types. print_c_type ( w, & ref_type, Some ( & gen_types) , true ) ;
501
502
write ! ( w, " {{\n \t " ) . unwrap ( ) ;
@@ -507,6 +508,7 @@ fn println_struct<W: std::io::Write>(w: &mut W, s: &syn::ItemStruct, types: &mut
507
508
}
508
509
509
510
if types. understood_c_type ( & field. ty , Some ( & gen_types) ) {
511
+ println_docs ( w, & field. attrs , "" ) ;
510
512
write ! ( w, "#[no_mangle]\n pub extern \" C\" fn {}_set_{}(this_ptr: &mut {}, val: " , struct_name, ident, struct_name) . unwrap ( ) ;
511
513
types. print_c_type ( w, & field. ty , Some ( & gen_types) , false ) ;
512
514
write ! ( w, ") {{\n \t " ) . unwrap ( ) ;
@@ -567,7 +569,18 @@ fn println_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &TypeRes
567
569
if trait_path. 0 . is_some ( ) { unimplemented ! ( ) ; }
568
570
if types. understood_c_path ( & trait_path. 1 ) {
569
571
eprintln ! ( "WIP: IMPL {:?} FOR {}" , trait_path. 1 , ident) ;
572
+ } else if let Some ( trait_ident) = trait_path. 1 . get_ident ( ) {
570
573
//XXX: implement for basic things like ToString and implement traits
574
+ match & format ! ( "{}" , trait_ident) as & str {
575
+ "From" => { } ,
576
+ "Default" => {
577
+ write ! ( w, "#[no_mangle]\n pub extern \" C\" fn {}_default() -> {} {{\n " , ident, ident) . unwrap ( ) ;
578
+ write ! ( w, "\t {} {{ inner: Box::into_raw(Box::new(Default::default())) }}\n " , ident) . unwrap ( ) ;
579
+ write ! ( w, "}}\n " ) . unwrap ( ) ;
580
+ } ,
581
+ "PartialEq" => { } ,
582
+ _ => { } ,
583
+ }
571
584
}
572
585
} else {
573
586
let declared_type = types. get_declared_type ( & ident) . unwrap ( ) ;
@@ -678,14 +691,15 @@ fn should_export(path: &str) -> bool {
678
691
}
679
692
}
680
693
681
- fn convert_file ( path : & str , out_path : & str , orig_crate : & str , module : & str , header_file : & mut File ) {
694
+ struct FullLibraryAST {
695
+ files : HashMap < String , syn:: File > ,
696
+ }
697
+
698
+ fn convert_file ( libast : & FullLibraryAST , crate_types : & CrateTypes , path : & str , out_path : & str , orig_crate : & str , module : & str , header_file : & mut File ) {
682
699
if !should_export ( path) { return ; }
683
700
eprintln ! ( "Converting {}..." , path) ;
684
701
685
- let mut file = File :: open ( path) . expect ( "Unable to open file" ) ;
686
- let mut src = String :: new ( ) ;
687
- file. read_to_string ( & mut src) . expect ( "Unable to read file" ) ;
688
- let syntax = syn:: parse_file ( & src) . expect ( "Unable to parse file" ) ;
702
+ let syntax = if let Some ( ast) = libast. files . get ( module) { ast } else { return } ;
689
703
690
704
assert ! ( syntax. shebang. is_none( ) ) ; // Not sure what this is, hope we dont have one
691
705
@@ -744,15 +758,17 @@ fn convert_file(path: &str, out_path: &str, orig_crate: &str, module: &str, head
744
758
if should_export ( & f_path) {
745
759
println_docs ( & mut out, & m. attrs , "" ) ;
746
760
write ! ( out, "pub mod {};\n " , m. ident) . unwrap ( ) ;
747
- convert_file ( & f_path, & format ! ( "{}/{}.rs" , ( out_path. as_ref( ) as & Path ) . parent( ) . unwrap( ) . display( ) , m. ident) ,
761
+ convert_file ( libast, crate_types, & f_path,
762
+ & format ! ( "{}/{}.rs" , ( out_path. as_ref( ) as & Path ) . parent( ) . unwrap( ) . display( ) , m. ident) ,
748
763
orig_crate, & new_mod, header_file) ;
749
764
}
750
765
} else {
751
766
let f_path = format ! ( "{}/{}/mod.rs" , ( path. as_ref( ) as & Path ) . parent( ) . unwrap( ) . display( ) , m. ident) ;
752
767
if should_export ( & f_path) {
753
768
println_docs ( & mut out, & m. attrs , "" ) ;
754
769
write ! ( out, "pub mod {};\n " , m. ident) . unwrap ( ) ;
755
- convert_file ( & f_path, & format ! ( "{}/{}/mod.rs" , ( out_path. as_ref( ) as & Path ) . parent( ) . unwrap( ) . display( ) , m. ident) ,
770
+ convert_file ( libast, crate_types, & f_path,
771
+ & format ! ( "{}/{}/mod.rs" , ( out_path. as_ref( ) as & Path ) . parent( ) . unwrap( ) . display( ) , m. ident) ,
756
772
orig_crate, & new_mod, header_file) ;
757
773
}
758
774
}
@@ -784,6 +800,115 @@ fn convert_file(path: &str, out_path: &str, orig_crate: &str, module: &str, head
784
800
out. flush ( ) . unwrap ( ) ;
785
801
}
786
802
803
+ fn load_ast ( path : & str , module : String , ast_storage : & mut FullLibraryAST ) {
804
+ if !should_export ( path) { return ; }
805
+ eprintln ! ( "Loading {}..." , path) ;
806
+
807
+ let mut file = File :: open ( path) . expect ( "Unable to open file" ) ;
808
+ let mut src = String :: new ( ) ;
809
+ file. read_to_string ( & mut src) . expect ( "Unable to read file" ) ;
810
+ let syntax = syn:: parse_file ( & src) . expect ( "Unable to parse file" ) ;
811
+
812
+ assert_eq ! ( export_status( & syntax. attrs) , ExportStatus :: Export ) ;
813
+
814
+ for item in syntax. items . iter ( ) {
815
+ match item {
816
+ syn:: Item :: Mod ( m) => {
817
+ if let syn:: Visibility :: Public ( _) = m. vis {
818
+ match export_status ( & m. attrs ) {
819
+ ExportStatus :: Export => { } ,
820
+ ExportStatus :: NoExport |ExportStatus :: TestOnly => continue ,
821
+ }
822
+
823
+ let f_path = format ! ( "{}/{}.rs" , ( path. as_ref( ) as & Path ) . parent( ) . unwrap( ) . display( ) , m. ident) ;
824
+ let new_mod = if module. is_empty ( ) { format ! ( "{}" , m. ident) } else { format ! ( "{}::{}" , module, m. ident) } ;
825
+ if let Ok ( _) = File :: open ( & f_path) {
826
+ if should_export ( & f_path) {
827
+ load_ast ( & f_path, new_mod, ast_storage) ;
828
+ }
829
+ } else {
830
+ let f_path = format ! ( "{}/{}/mod.rs" , ( path. as_ref( ) as & Path ) . parent( ) . unwrap( ) . display( ) , m. ident) ;
831
+ if should_export ( & f_path) {
832
+ load_ast ( & f_path, new_mod, ast_storage) ;
833
+ }
834
+ }
835
+ }
836
+ } ,
837
+ _ => { } ,
838
+ }
839
+ }
840
+ ast_storage. files . insert ( module, syntax) ;
841
+ }
842
+
843
+ fn walk_ast < ' a > ( path : & str , module : String , ast_storage : & ' a FullLibraryAST , crate_types : & mut CrateTypes < ' a > ) {
844
+ if !should_export ( path) { return ; }
845
+ eprintln ! ( "Walking {}..." , path) ;
846
+ let syntax = if let Some ( ast) = ast_storage. files . get ( & module) { ast } else { return } ;
847
+ assert_eq ! ( export_status( & syntax. attrs) , ExportStatus :: Export ) ;
848
+
849
+ for item in syntax. items . iter ( ) {
850
+ match item {
851
+ syn:: Item :: Mod ( m) => {
852
+ if let syn:: Visibility :: Public ( _) = m. vis {
853
+ match export_status ( & m. attrs ) {
854
+ ExportStatus :: Export => { } ,
855
+ ExportStatus :: NoExport |ExportStatus :: TestOnly => continue ,
856
+ }
857
+
858
+ let f_path = format ! ( "{}/{}.rs" , ( path. as_ref( ) as & Path ) . parent( ) . unwrap( ) . display( ) , m. ident) ;
859
+ let new_mod = if module. is_empty ( ) { format ! ( "{}" , m. ident) } else { format ! ( "{}::{}" , module, m. ident) } ;
860
+ if let Ok ( _) = File :: open ( & f_path) {
861
+ if should_export ( & f_path) {
862
+ walk_ast ( & f_path, new_mod, ast_storage, crate_types) ;
863
+ }
864
+ } else {
865
+ let f_path = format ! ( "{}/{}/mod.rs" , ( path. as_ref( ) as & Path ) . parent( ) . unwrap( ) . display( ) , m. ident) ;
866
+ if should_export ( & f_path) {
867
+ walk_ast ( & f_path, new_mod, ast_storage, crate_types) ;
868
+ }
869
+ }
870
+ }
871
+ } ,
872
+ syn:: Item :: Struct ( s) => {
873
+ if let syn:: Visibility :: Public ( _) = s. vis {
874
+ match export_status ( & s. attrs ) {
875
+ ExportStatus :: Export => { } ,
876
+ ExportStatus :: NoExport |ExportStatus :: TestOnly => continue ,
877
+ }
878
+ let struct_path = format ! ( "{}::{}" , module, s. ident) ;
879
+ crate_types. structs . insert ( struct_path, & s) ;
880
+ }
881
+ } ,
882
+ syn:: Item :: Trait ( t) => {
883
+ if let syn:: Visibility :: Public ( _) = t. vis {
884
+ match export_status ( & t. attrs ) {
885
+ ExportStatus :: Export => { } ,
886
+ ExportStatus :: NoExport |ExportStatus :: TestOnly => continue ,
887
+ }
888
+ let trait_path = format ! ( "{}::{}" , module, t. ident) ;
889
+ crate_types. traits . insert ( trait_path, & t) ;
890
+ }
891
+ } ,
892
+ syn:: Item :: Impl ( i) => {
893
+ match export_status ( & i. attrs ) {
894
+ ExportStatus :: Export => { } ,
895
+ ExportStatus :: NoExport |ExportStatus :: TestOnly => continue ,
896
+ }
897
+ if i. defaultness . is_none ( ) && i. unsafety . is_none ( ) && i. trait_ . is_some ( ) {
898
+ if let syn:: Type :: Path ( path) = & * i. self_ty {
899
+ if let Some ( ident) = single_ident_generic_path_to_ident ( & path. path ) {
900
+ if let Some ( trait_ident) = single_ident_generic_path_to_ident ( & i. trait_ . as_ref ( ) . unwrap ( ) . 1 ) {
901
+ crate_types. trait_impls . entry ( format ! ( "{}::{}" , module, ident) ) . or_insert ( Vec :: new ( ) ) . push ( trait_ident) ;
902
+ }
903
+ }
904
+ }
905
+ }
906
+ } ,
907
+ _ => { } ,
908
+ }
909
+ }
910
+ }
911
+
787
912
fn main ( ) {
788
913
let args: Vec < String > = env:: args ( ) . collect ( ) ;
789
914
if args. len ( ) != 5 {
@@ -794,7 +919,13 @@ fn main() {
794
919
let mut header_file = std:: fs:: OpenOptions :: new ( ) . write ( true ) . append ( true )
795
920
. open ( & args[ 4 ] ) . expect ( "Unable to open new header file" ) ;
796
921
797
- convert_file ( & ( args[ 1 ] . clone ( ) + "/lib.rs" ) , & ( args[ 2 ] . clone ( ) + "lib.rs" ) , & args[ 3 ] , "" , & mut header_file) ;
922
+ let mut libast = FullLibraryAST { files : HashMap :: new ( ) } ;
923
+ load_ast ( & ( args[ 1 ] . clone ( ) + "/lib.rs" ) , "" . to_string ( ) , & mut libast) ;
924
+
925
+ let mut libtypes = CrateTypes { traits : HashMap :: new ( ) , trait_impls : HashMap :: new ( ) , structs : HashMap :: new ( ) } ;
926
+ walk_ast ( & ( args[ 1 ] . clone ( ) + "/lib.rs" ) , "" . to_string ( ) , & libast, & mut libtypes) ;
927
+
928
+ convert_file ( & libast, & libtypes, & ( args[ 1 ] . clone ( ) + "/lib.rs" ) , & ( args[ 2 ] . clone ( ) + "lib.rs" ) , & args[ 3 ] , "" , & mut header_file) ;
798
929
799
930
header_file. flush ( ) . unwrap ( ) ;
800
931
}
0 commit comments