Skip to content

Commit 6598930

Browse files
authored
Merge pull request #40 from stepfunc/feature/constants
Feature/constants
2 parents 406f50c + 1aef5a4 commit 6598930

File tree

14 files changed

+352
-14
lines changed

14 files changed

+352
-14
lines changed

generators/c-oo-bindgen/src/lib.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,10 @@ clippy::all
4646

4747
use crate::doc::*;
4848
use crate::formatting::*;
49-
use heck::{CamelCase, SnakeCase};
49+
use heck::{CamelCase, ShoutySnakeCase, SnakeCase};
5050
use oo_bindgen::callback::*;
5151
use oo_bindgen::class::*;
52+
use oo_bindgen::constants::{ConstantSetHandle, ConstantValue, Representation};
5253
use oo_bindgen::doc::*;
5354
use oo_bindgen::formatting::*;
5455
use oo_bindgen::native_enum::*;
@@ -243,6 +244,7 @@ fn generate_c_header<P: AsRef<Path>>(lib: &Library, path: P) -> FormattingResult
243244
// Iterate through each statement and print them
244245
for statement in lib.into_iter() {
245246
match statement {
247+
Statement::Constants(handle) => write_constants_definition(f, handle, lib)?,
246248
Statement::NativeStructDeclaration(handle) => {
247249
f.writeln(&format!(
248250
"typedef struct {} {};",
@@ -269,6 +271,29 @@ fn generate_c_header<P: AsRef<Path>>(lib: &Library, path: P) -> FormattingResult
269271
})
270272
}
271273

274+
fn write_constants_definition(
275+
f: &mut dyn Printer,
276+
handle: &ConstantSetHandle,
277+
lib: &Library,
278+
) -> FormattingResult<()> {
279+
fn get_constant_value(value: ConstantValue) -> String {
280+
match value {
281+
ConstantValue::U8(value, Representation::Hex) => format!("0x{:02X?}", value),
282+
}
283+
}
284+
285+
for item in &handle.values {
286+
doxygen(f, |f| doxygen_print(f, &item.doc, lib))?;
287+
f.writeln(&format!(
288+
"#define {}_{} {}",
289+
handle.name.to_shouty_snake_case(),
290+
item.name.to_shouty_snake_case(),
291+
get_constant_value(item.value)
292+
))?;
293+
}
294+
Ok(())
295+
}
296+
272297
fn write_struct_definition(
273298
f: &mut dyn Printer,
274299
handle: &NativeStructHandle,

generators/dotnet-oo-bindgen/src/lib.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use crate::conversion::*;
4848
use crate::doc::*;
4949
use crate::formatting::*;
5050
use heck::CamelCase;
51+
use oo_bindgen::constants::*;
5152
use oo_bindgen::formatting::*;
5253
use oo_bindgen::native_enum::*;
5354
use oo_bindgen::native_function::*;
@@ -81,6 +82,7 @@ pub fn generate_dotnet_bindings(
8182

8283
generate_native_func_class(lib, config)?;
8384

85+
generate_constants(lib, config)?;
8486
generate_structs(lib, config)?;
8587
generate_enums(lib, config)?;
8688
generate_classes(lib, config)?;
@@ -170,6 +172,20 @@ fn generate_native_func_class(lib: &Library, config: &DotnetBindgenConfig) -> Fo
170172
})
171173
}
172174

175+
fn generate_constants(lib: &Library, config: &DotnetBindgenConfig) -> FormattingResult<()> {
176+
for constants in lib.constants() {
177+
// Open file
178+
let mut filename = config.output_dir.clone();
179+
filename.push(&constants.name);
180+
filename.set_extension("cs");
181+
let mut f = FilePrinter::new(filename)?;
182+
183+
generate_constant_set(&mut f, constants, lib)?;
184+
}
185+
186+
Ok(())
187+
}
188+
173189
fn generate_structs(lib: &Library, config: &DotnetBindgenConfig) -> FormattingResult<()> {
174190
for native_struct in lib.structs() {
175191
// Open file
@@ -198,6 +214,49 @@ fn generate_enums(lib: &Library, config: &DotnetBindgenConfig) -> FormattingResu
198214
Ok(())
199215
}
200216

217+
fn generate_constant_set(
218+
f: &mut impl Printer,
219+
set: &ConstantSetHandle,
220+
lib: &Library,
221+
) -> FormattingResult<()> {
222+
fn get_type_as_string(value: &ConstantValue) -> &'static str {
223+
match value {
224+
ConstantValue::U8(_, _) => "byte",
225+
}
226+
}
227+
228+
fn get_value_as_string(value: &ConstantValue) -> String {
229+
match value {
230+
ConstantValue::U8(x, Representation::Hex) => format!("0x{:02X?}", x),
231+
}
232+
}
233+
234+
print_license(f, &lib.license)?;
235+
print_imports(f)?;
236+
f.newline()?;
237+
238+
namespaced(f, &lib.name, |f| {
239+
documentation(f, |f| {
240+
// Print top-level documentation
241+
xmldoc_print(f, &set.doc, lib)
242+
})?;
243+
244+
f.writeln(&format!("public static class {}", set.name.to_camel_case()))?;
245+
blocked(f, |f| {
246+
for value in &set.values {
247+
documentation(f, |f| xmldoc_print(f, &value.doc, lib))?;
248+
f.writeln(&format!(
249+
"public const {} {} = {};",
250+
get_type_as_string(&value.value),
251+
value.name.to_camel_case(),
252+
get_value_as_string(&value.value),
253+
))?;
254+
}
255+
Ok(())
256+
})
257+
})
258+
}
259+
201260
fn generate_enum(
202261
f: &mut impl Printer,
203262
native_enum: &NativeEnumHandle,
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use super::doc::*;
2+
use super::*;
3+
use heck::{CamelCase, ShoutySnakeCase};
4+
use oo_bindgen::constants::*;
5+
6+
pub(crate) fn generate(
7+
f: &mut impl Printer,
8+
set: &ConstantSetHandle,
9+
lib: &Library,
10+
) -> FormattingResult<()> {
11+
fn get_type_as_string(value: &ConstantValue) -> &'static str {
12+
match value {
13+
ConstantValue::U8(_, _) => "UByte",
14+
}
15+
}
16+
17+
fn get_value_as_string(value: &ConstantValue) -> String {
18+
match value {
19+
ConstantValue::U8(x, Representation::Hex) => format!("UByte.valueOf(0x{:02X?})", x),
20+
}
21+
}
22+
23+
let set_name = set.name.to_camel_case();
24+
25+
// Documentation
26+
documentation(f, |f| javadoc_print(f, &set.doc, lib))?;
27+
28+
// class definition
29+
f.writeln(&format!("public class {}", set_name))?;
30+
blocked(f, |f| {
31+
f.writeln("// not constructable")?;
32+
f.writeln(&format!("private {}() {{}}", set_name))?;
33+
34+
// Write the values
35+
for constant in &set.values {
36+
documentation(f, |f| javadoc_print(f, &constant.doc, lib))?;
37+
f.writeln(&format!(
38+
"public static final {} {} = {};",
39+
get_type_as_string(&constant.value),
40+
constant.name.to_shouty_snake_case(),
41+
get_value_as_string(&constant.value)
42+
))?;
43+
}
44+
Ok(())
45+
})
46+
}

generators/java-oo-bindgen/src/java/mod.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::fs;
1010

1111
mod callback;
1212
mod class;
13+
mod constant;
1314
mod conversion;
1415
mod doc;
1516
mod enumeration;
@@ -49,6 +50,7 @@ pub fn generate_java_bindings(lib: &Library, config: &JavaBindgenConfig) -> Form
4950
generate_native_func_class(lib, config)?;
5051

5152
// Generate the user-facing stuff
53+
generate_constants(lib, config)?;
5254
generate_structs(lib, config)?;
5355
generate_enums(lib, config)?;
5456
generate_classes(lib, config)?;
@@ -187,12 +189,10 @@ fn generate_native_func_class(lib: &Library, config: &JavaBindgenConfig) -> Form
187189
}
188190
}
189191
}
190-
if let ReturnType::Type(return_type, _) = &handle.return_type {
191-
if let Type::ClassRef(class_handle) = &return_type {
192-
// We don't want to generate the `create` method of collections
193-
if lib.find_collection(&class_handle.name).is_some() {
194-
continue;
195-
}
192+
if let ReturnType::Type(Type::ClassRef(class_handle), _) = &handle.return_type {
193+
// We don't want to generate the `create` method of collections
194+
if lib.find_collection(&class_handle.name).is_some() {
195+
continue;
196196
}
197197
}
198198

@@ -218,6 +218,15 @@ fn generate_native_func_class(lib: &Library, config: &JavaBindgenConfig) -> Form
218218
})
219219
}
220220

221+
fn generate_constants(lib: &Library, config: &JavaBindgenConfig) -> FormattingResult<()> {
222+
for set in lib.constants() {
223+
let mut f = create_file(&set.name.to_camel_case(), config, lib)?;
224+
constant::generate(&mut f, set, lib)?;
225+
}
226+
227+
Ok(())
228+
}
229+
221230
fn generate_structs(lib: &Library, config: &JavaBindgenConfig) -> FormattingResult<()> {
222231
for native_struct in lib.structs() {
223232
let mut f = create_file(&native_struct.name().to_camel_case(), config, lib)?;

generators/java-oo-bindgen/src/rust/mod.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,11 @@ fn generate_functions(
201201
}
202202
}
203203
}
204-
if let ReturnType::Type(return_type, _) = &handle.return_type {
205-
if let Type::ClassRef(class_handle) = &return_type {
206-
// We don't want to generate the `create` method of collections
207-
if lib.find_collection(&class_handle.name).is_some() {
208-
continue;
209-
}
204+
205+
if let ReturnType::Type(Type::ClassRef(class_handle), _) = &handle.return_type {
206+
// We don't want to generate the `create` method of collections
207+
if lib.find_collection(&class_handle.name).is_some() {
208+
continue;
210209
}
211210
}
212211

oo-bindgen/src/constants.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
use crate::doc::Doc;
2+
use crate::*;
3+
4+
/// How to render a numeric constant
5+
#[derive(Copy, Clone, Debug)]
6+
pub enum Representation {
7+
Hex,
8+
}
9+
10+
/// Types of constants available
11+
#[derive(Copy, Clone, Debug)]
12+
pub enum ConstantValue {
13+
U8(u8, Representation),
14+
}
15+
16+
/// Constant belonging to a set of constants
17+
#[derive(Debug)]
18+
pub struct Constant {
19+
pub name: String,
20+
pub value: ConstantValue,
21+
pub doc: Doc,
22+
}
23+
24+
/// Set of constants
25+
#[derive(Debug)]
26+
pub struct ConstantSet {
27+
/// Name of the set
28+
pub name: String,
29+
/// values
30+
pub values: Vec<Constant>,
31+
/// documentation
32+
pub doc: Doc,
33+
}
34+
35+
pub type ConstantSetHandle = Handle<ConstantSet>;
36+
37+
pub struct ConstantSetBuilder<'a> {
38+
lib: &'a mut LibraryBuilder,
39+
name: String,
40+
names: HashSet<String>,
41+
values: Vec<Constant>,
42+
doc: Option<Doc>,
43+
}
44+
45+
impl<'a> ConstantSetBuilder<'a> {
46+
pub fn new(lib: &'a mut LibraryBuilder, name: String) -> Self {
47+
Self {
48+
lib,
49+
name,
50+
names: HashSet::new(),
51+
values: Vec::new(),
52+
doc: None,
53+
}
54+
}
55+
56+
pub fn doc<D: Into<Doc>>(mut self, doc: D) -> Result<Self> {
57+
match self.doc {
58+
None => {
59+
self.doc = Some(doc.into());
60+
Ok(self)
61+
}
62+
Some(_) => Err(BindingError::DocAlreadyDefined {
63+
symbol_name: self.name,
64+
}),
65+
}
66+
}
67+
68+
pub fn add<T: Into<String>, D: Into<Doc>>(
69+
mut self,
70+
name: T,
71+
value: ConstantValue,
72+
doc: D,
73+
) -> Result<Self> {
74+
let name = name.into();
75+
if self.names.contains(&name) {
76+
return Err(BindingError::ConstantNameAlreadyUsed {
77+
set_name: self.name,
78+
constant_name: name,
79+
});
80+
}
81+
self.values.push(Constant {
82+
name,
83+
value,
84+
doc: doc.into(),
85+
});
86+
Ok(self)
87+
}
88+
89+
pub fn build(self) -> Result<()> {
90+
let doc = match self.doc {
91+
Some(doc) => doc,
92+
None => {
93+
return Err(BindingError::DocNotDefined {
94+
symbol_name: self.name,
95+
})
96+
}
97+
};
98+
99+
let handle = ConstantSetHandle::new(ConstantSet {
100+
name: self.name,
101+
values: self.values,
102+
doc,
103+
});
104+
105+
self.lib.statements.push(Statement::Constants(handle));
106+
107+
Ok(())
108+
}
109+
}

0 commit comments

Comments
 (0)