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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
//! This crate works with [`flapigen`] to provide an easy to use rust code with other programming languages
//!
//! [`flapigen`]: https://docs.rs/flapigen
//!
//! This crate uses procedural macros such as `#generate_interface` to locate methods and types for which interface
//! code would be generated automatically
//! Suppose you have the following Rust code:
//! ```rust
//! struct Foo {
//!     data: i32
//! }
//!
//! impl Foo {
//!     fn new(val: i32) -> Foo {
//!         Foo{data: val}
//!     }
//!
//!     fn f(&self, a: i32, b: i32) -> i32 {
//!         self.data + a + b
//!     }
//!
//!     ///Custom doc comment
//!     fn set_field(&mut self, v: i32) {
//!         self.data = v;
//!     }
//! }
//!
//! ```
//! Using [`flapigen`], you need to generate an interface file with contents:
//!
//! [`flapigen`]: https://docs.rs/flapigen
//! ```ignore
//! foreign_class!(class Foo {
//!     self_type Foo;
//!     constructor Foo::new(_: i32) -> Foo;
//!     ///Custom doc comment
//!     fn Foo::set_field(&mut self, _: i32);
//!     fn Foo::f(&self, _: i32, _: i32) -> i32;
//! });
//! ```
//!
//! Using this crate, you can simply annotate the methods using either `#[generate_interface]`, `#[generate_interface(constructor)]` or `#[generate_interface_doc]`
//!
//! First add the appropriate dependencies
//!
//! In Cargo.toml
//! ```toml
//! [dependencies]
//! rifgen = "*"
//! [build-dependencies]
//! rifgen = "*"
//! ```
//!
//! In build.rs
//!```no_run
//! //place this code before flapigen swig_expand function
//! use rifgen::{Generator, TypeCases, Language};
//! let source_folder = "/user/projects"; //use your projects folder
//! let out_file = "/user/projects/glue.in";
//! Generator::new(TypeCases::CamelCase,Language::Java,source_folder)
//! .generate_interface(out_file)
//! ```
//!
//! Using the example above, the modified code would be
//! ```
//! use rifgen::rifgen_attr::*;
//!
//! struct Foo {
//!     data: i32
//! }
//!
//! impl Foo {
//!     #[generate_interface(constructor)]
//!     fn new(val: i32) -> Foo {
//!         Foo{data: val}
//!     }
//!     #[generate_interface]
//!     fn f(&self, a: i32, b: i32) -> i32 {
//!         self.data + a + b
//!     }
//!
//!     ///Custom doc comment
//!     #[generate_interface]
//!     fn set_field(&mut self, v: i32) {
//!         self.data = v;
//!     }
//! }
//! ```
//!
//! This crate works with doc comments so all doc comments would be preserved
//! Use `#[generate_interface_doc]` on <b>structs only</b> to preserve the doc comment of the struct
//! ```
//! ///Data holder
//! # use rifgen_attr::generate_interface_doc;
//! #[generate_interface_doc]
//! struct Foo {
//!     data: i32
//! }
//! ```
//!
//! For `trait` just annotate the trait definition
//! ```
//! ///MyCallback documentation
//! # use rifgen_attr::generate_interface;
//! #[generate_interface]
//! trait MyCallback {
//!     
//!     fn on_click(&self) {
//!     }
//! }
//! ```
//! For `enum`, it's similar to `trait`
//! ```
//! # use rifgen_attr::generate_interface;
//! #[generate_interface]
//! enum MyEnum {
//!     One,
//!     Two
//! }
//! ```
mod enums;
mod generator_lib;
mod maps;
mod text_formatter;
mod traits;
mod types_structs;

pub extern crate rifgen_attr;

use crate::generator_lib::FileGenerator;
use std::path::Path;

/// The various type cases to use when generating interface files
/// i.e CamelCase or snake_case or just leave the style unchanged
#[derive(Copy, Clone)]
pub enum TypeCases {
    /// Various names of methods and variants are untouched.
    /// This is the default setting
    Default,
    /// Convert all method names to CamelCase
    CamelCase,
    /// Convert all method method names to snake_case
    SnakeCase,
}

/// The builder to use in build.rs file to generate the interface file
pub struct Generator<P: AsRef<Path>> {
    type_case: TypeCases,
    scr_folder: P,
    language: Language,
}

///Supported languages for now
pub enum Language {
    Java,
    Cpp,
}

impl<S: AsRef<Path>> Generator<S> {
    /// Creates a new generator instance
    ///
    /// `scr_folder` refers to the starting folder where it is recursively walked
    ///through to find other files
    pub fn new(type_case: TypeCases, language: Language, scr_folder: S) -> Generator<S> {
        Generator {
            type_case,
            scr_folder,
            language,
        }
    }

    ///`interface_file_path` refers to the path of the output file.
    /// If it exists, it would be overwritten
    pub fn generate_interface<I: AsRef<Path>>(self, interface_file_path: I) {
        FileGenerator::new(self.type_case, interface_file_path, self.scr_folder)
            .build(self.language);
    }
}

/*#[cfg(test)]
mod tests {
    use crate::{Generator, Language, TypeCases};

    #[test]
    fn test() {
        for i in 0..20 {
            Generator::new(TypeCases::CamelCase, Language::Java, "C:\\Users\\taimoor\\IdeaProjects\\rifgen\\test folder")
                .generate_interface(format!("C:\\Users\\taimoor\\IdeaProjects\\rifgen\\src\\TEST{}.in", i))
        }
    }
}*/