Skip to content

Commit 6b09f11

Browse files
authored
Allow for arbitrary BindingGenerator (#1991)
De-couple TargetLanguage from the `generate_external_bindings` calls. This will allow 3rd-party BindingGenerators to use the methods. The `try_format_code` boolean had to be punched through (for now) to keep the API as similar as possible. I think a follow-up action should be to move the boolean to the Config.
1 parent 0a88d94 commit 6b09f11

File tree

15 files changed

+178
-54
lines changed

15 files changed

+178
-54
lines changed

fixtures/docstring-proc-macro/tests/test_generated_bindings.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ uniffi::build_foreign_language_testcases!(
77
#[cfg(test)]
88
mod tests {
99
use uniffi_bindgen::bindings::TargetLanguage;
10+
use uniffi_bindgen::BindingGeneratorDefault;
1011
use uniffi_testing::UniFFITestHelper;
1112

1213
const DOCSTRINGS: &[&str] = &[
@@ -50,7 +51,10 @@ mod tests {
5051
uniffi_bindgen::library_mode::generate_bindings(
5152
&cdylib_path,
5253
None,
53-
&[language],
54+
&BindingGeneratorDefault {
55+
target_languages: vec![language],
56+
try_format_code: false,
57+
},
5458
None,
5559
&out_dir,
5660
false,

fixtures/docstring/tests/test_generated_bindings.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ uniffi::build_foreign_language_testcases!(
88
mod tests {
99
use camino::Utf8PathBuf;
1010
use uniffi_bindgen::bindings::TargetLanguage;
11+
use uniffi_bindgen::BindingGeneratorDefault;
1112
use uniffi_testing::UniFFITestHelper;
1213

1314
const DOCSTRINGS: &[&str] = &[
@@ -48,7 +49,10 @@ mod tests {
4849
uniffi_bindgen::generate_bindings(
4950
&Utf8PathBuf::from("src/docstring.udl"),
5051
None,
51-
vec![language],
52+
BindingGeneratorDefault {
53+
target_languages: vec![language],
54+
try_format_code: false,
55+
},
5256
Some(&out_dir),
5357
None,
5458
None,

fixtures/swift-bridging-header-compile/tests/clang.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use camino::Utf8PathBuf;
22
use std::process::Command;
3-
use uniffi::TargetLanguage;
3+
use uniffi::SwiftBindingGenerator;
44
use uniffi_testing::UniFFITestHelper;
55

66
#[test]
@@ -14,7 +14,7 @@ fn clang() -> Result<(), anyhow::Error> {
1414
uniffi::generate_bindings(
1515
&Utf8PathBuf::from("src/swift-bridging-header-compile.udl"),
1616
None,
17-
vec![TargetLanguage::Swift],
17+
SwiftBindingGenerator,
1818
Some(&out_dir),
1919
None,
2020
None,

uniffi/src/cli.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use camino::Utf8PathBuf;
66
use clap::{Parser, Subcommand};
77
use uniffi_bindgen::bindings::TargetLanguage;
8+
use uniffi_bindgen::BindingGeneratorDefault;
89

910
// Structs to help our cmdline parsing. Note that docstrings below form part
1011
// of the "help" output.
@@ -102,7 +103,10 @@ pub fn run_main() -> anyhow::Result<()> {
102103
uniffi_bindgen::library_mode::generate_bindings(
103104
&source,
104105
crate_name,
105-
&language,
106+
&BindingGeneratorDefault {
107+
target_languages: language,
108+
try_format_code: !no_format,
109+
},
106110
config.as_deref(),
107111
&out_dir,
108112
!no_format,
@@ -111,7 +115,10 @@ pub fn run_main() -> anyhow::Result<()> {
111115
uniffi_bindgen::generate_bindings(
112116
&source,
113117
config.as_deref(),
114-
language,
118+
BindingGeneratorDefault {
119+
target_languages: language,
120+
try_format_code: !no_format,
121+
},
115122
out_dir.as_deref(),
116123
lib_file.as_deref(),
117124
crate_name.as_deref(),

uniffi/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ pub use uniffi_bindgen::bindings::ruby::run_test as ruby_run_test;
1717
pub use uniffi_bindgen::bindings::swift::run_test as swift_run_test;
1818
#[cfg(feature = "bindgen")]
1919
pub use uniffi_bindgen::{
20-
bindings::TargetLanguage, generate_bindings, generate_component_scaffolding,
21-
generate_component_scaffolding_for_crate, print_repr,
20+
bindings::kotlin::gen_kotlin::KotlinBindingGenerator,
21+
bindings::python::gen_python::PythonBindingGenerator,
22+
bindings::ruby::gen_ruby::RubyBindingGenerator,
23+
bindings::swift::gen_swift::SwiftBindingGenerator, bindings::TargetLanguage, generate_bindings,
24+
generate_component_scaffolding, generate_component_scaffolding_for_crate, print_repr,
2225
};
2326
#[cfg(feature = "build")]
2427
pub use uniffi_build::{generate_scaffolding, generate_scaffolding_for_crate};

uniffi_bindgen/src/bindings/kotlin/gen_kotlin/mod.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ use std::cell::RefCell;
77
use std::collections::{BTreeSet, HashMap, HashSet};
88
use std::fmt::Debug;
99

10-
use anyhow::{Context, Result};
10+
use anyhow::{bail, Context, Result};
1111
use askama::Template;
12+
use camino::Utf8Path;
1213
use heck::{ToLowerCamelCase, ToShoutySnakeCase, ToUpperCamelCase};
1314
use serde::{Deserialize, Serialize};
1415

1516
use crate::backend::TemplateExpression;
17+
use crate::bindings::kotlin;
1618
use crate::interface::*;
17-
use crate::BindingsConfig;
19+
use crate::{BindingGenerator, BindingsConfig};
1820

1921
mod callback_interface;
2022
mod compounds;
@@ -27,6 +29,28 @@ mod primitives;
2729
mod record;
2830
mod variant;
2931

32+
pub struct KotlinBindingGenerator;
33+
impl BindingGenerator for KotlinBindingGenerator {
34+
type Config = Config;
35+
36+
fn write_bindings(
37+
&self,
38+
ci: &ComponentInterface,
39+
config: &Config,
40+
out_dir: &Utf8Path,
41+
try_format_code: bool,
42+
) -> Result<()> {
43+
kotlin::write_bindings(config, ci, out_dir, try_format_code)
44+
}
45+
46+
fn check_library_path(&self, library_path: &Utf8Path, cdylib_name: Option<&str>) -> Result<()> {
47+
if cdylib_name.is_none() {
48+
bail!("Generate bindings for Kotlin requires a cdylib, but {library_path} was given");
49+
}
50+
Ok(())
51+
}
52+
}
53+
3054
trait CodeType: Debug {
3155
/// The language specific label used to reference this type. This will be used in
3256
/// method signatures and property declarations.

uniffi_bindgen/src/bindings/kotlin/test.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5-
use crate::{
6-
bindings::{RunScriptOptions, TargetLanguage},
7-
library_mode::generate_bindings,
8-
};
5+
use crate::bindings::TargetLanguage;
6+
use crate::{bindings::RunScriptOptions, library_mode::generate_bindings, BindingGeneratorDefault};
97
use anyhow::{bail, Context, Result};
108
use camino::{Utf8Path, Utf8PathBuf};
119
use std::env;
@@ -40,7 +38,10 @@ pub fn run_script(
4038
generate_bindings(
4139
&cdylib_path,
4240
None,
43-
&[TargetLanguage::Kotlin],
41+
&BindingGeneratorDefault {
42+
target_languages: vec![TargetLanguage::Kotlin],
43+
try_format_code: false,
44+
},
4445
None,
4546
&out_dir,
4647
false,

uniffi_bindgen/src/bindings/python/gen_python/mod.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5-
use anyhow::{Context, Result};
5+
use anyhow::{bail, Context, Result};
66
use askama::Template;
7+
use camino::Utf8Path;
78
use heck::{ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase};
89
use once_cell::sync::Lazy;
910
use serde::{Deserialize, Serialize};
@@ -13,8 +14,9 @@ use std::collections::{BTreeSet, HashMap, HashSet};
1314
use std::fmt::Debug;
1415

1516
use crate::backend::TemplateExpression;
17+
use crate::bindings::python;
1618
use crate::interface::*;
17-
use crate::BindingsConfig;
19+
use crate::{BindingGenerator, BindingsConfig};
1820

1921
mod callback_interface;
2022
mod compounds;
@@ -26,6 +28,29 @@ mod object;
2628
mod primitives;
2729
mod record;
2830

31+
pub struct PythonBindingGenerator;
32+
33+
impl BindingGenerator for PythonBindingGenerator {
34+
type Config = Config;
35+
36+
fn write_bindings(
37+
&self,
38+
ci: &ComponentInterface,
39+
config: &Config,
40+
out_dir: &Utf8Path,
41+
try_format_code: bool,
42+
) -> Result<()> {
43+
python::write_bindings(config, ci, out_dir, try_format_code)
44+
}
45+
46+
fn check_library_path(&self, library_path: &Utf8Path, cdylib_name: Option<&str>) -> Result<()> {
47+
if cdylib_name.is_none() {
48+
bail!("Generate bindings for Python requires a cdylib, but {library_path} was given");
49+
}
50+
Ok(())
51+
}
52+
}
53+
2954
/// A trait tor the implementation.
3055
trait CodeType: Debug {
3156
/// The language specific label used to reference this type. This will be used in

uniffi_bindgen/src/bindings/python/test.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5-
use crate::{
6-
bindings::{RunScriptOptions, TargetLanguage},
7-
library_mode::generate_bindings,
8-
};
5+
use crate::bindings::TargetLanguage;
6+
use crate::{bindings::RunScriptOptions, library_mode::generate_bindings, BindingGeneratorDefault};
97
use anyhow::{Context, Result};
108
use camino::Utf8Path;
119
use std::env;
@@ -41,7 +39,10 @@ pub fn run_script(
4139
generate_bindings(
4240
&cdylib_path,
4341
None,
44-
&[TargetLanguage::Python],
42+
&BindingGeneratorDefault {
43+
target_languages: vec![TargetLanguage::Python],
44+
try_format_code: false,
45+
},
4546
None,
4647
&out_dir,
4748
false,

uniffi_bindgen/src/bindings/ruby/gen_ruby/mod.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,39 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5-
use anyhow::Result;
5+
use anyhow::{bail, Result};
66
use askama::Template;
7+
use camino::Utf8Path;
78
use heck::{ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase};
89
use serde::{Deserialize, Serialize};
910
use std::borrow::Borrow;
1011
use std::collections::HashMap;
1112

13+
use crate::bindings::ruby;
1214
use crate::interface::*;
13-
use crate::BindingsConfig;
15+
use crate::{BindingGenerator, BindingsConfig};
16+
17+
pub struct RubyBindingGenerator;
18+
impl BindingGenerator for RubyBindingGenerator {
19+
type Config = Config;
20+
21+
fn write_bindings(
22+
&self,
23+
ci: &ComponentInterface,
24+
config: &Config,
25+
out_dir: &Utf8Path,
26+
try_format_code: bool,
27+
) -> Result<()> {
28+
ruby::write_bindings(config, ci, out_dir, try_format_code)
29+
}
30+
31+
fn check_library_path(&self, library_path: &Utf8Path, cdylib_name: Option<&str>) -> Result<()> {
32+
if cdylib_name.is_none() {
33+
bail!("Generate bindings for Ruby requires a cdylib, but {library_path} was given");
34+
}
35+
Ok(())
36+
}
37+
}
1438

1539
const RESERVED_WORDS: &[&str] = &[
1640
"alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined?", "do", "else",

uniffi_bindgen/src/bindings/ruby/test.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ License, v. 2.0. If a copy of the MPL was not distributed with this
44

55
use crate::bindings::TargetLanguage;
66
use crate::library_mode::generate_bindings;
7+
use crate::BindingGeneratorDefault;
78
use anyhow::{bail, Context, Result};
89
use camino::Utf8Path;
910
use std::env;
@@ -37,7 +38,10 @@ pub fn test_script_command(
3738
generate_bindings(
3839
&cdylib_path,
3940
None,
40-
&[TargetLanguage::Ruby],
41+
&BindingGeneratorDefault {
42+
target_languages: vec![TargetLanguage::Ruby],
43+
try_format_code: false,
44+
},
4145
None,
4246
&out_dir,
4347
false,

uniffi_bindgen/src/bindings/swift/gen_swift/mod.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ use std::fmt::Debug;
1010

1111
use anyhow::{Context, Result};
1212
use askama::Template;
13+
use camino::Utf8Path;
1314
use heck::{ToLowerCamelCase, ToShoutySnakeCase, ToUpperCamelCase};
1415
use serde::{Deserialize, Serialize};
1516

1617
use super::Bindings;
1718
use crate::backend::TemplateExpression;
19+
use crate::bindings::swift;
1820
use crate::interface::*;
19-
use crate::BindingsConfig;
21+
use crate::{BindingGenerator, BindingsConfig};
2022

2123
mod callback_interface;
2224
mod compounds;
@@ -28,6 +30,29 @@ mod object;
2830
mod primitives;
2931
mod record;
3032

33+
pub struct SwiftBindingGenerator;
34+
impl BindingGenerator for SwiftBindingGenerator {
35+
type Config = Config;
36+
37+
fn write_bindings(
38+
&self,
39+
ci: &ComponentInterface,
40+
config: &Config,
41+
out_dir: &Utf8Path,
42+
try_format_code: bool,
43+
) -> Result<()> {
44+
swift::write_bindings(config, ci, out_dir, try_format_code)
45+
}
46+
47+
fn check_library_path(
48+
&self,
49+
_library_path: &Utf8Path,
50+
_cdylib_name: Option<&str>,
51+
) -> Result<()> {
52+
Ok(())
53+
}
54+
}
55+
3156
/// A trait tor the implementation.
3257
trait CodeType: Debug {
3358
/// The language specific label used to reference this type. This will be used in

uniffi_bindgen/src/bindings/swift/test.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5-
use crate::{
6-
bindings::{RunScriptOptions, TargetLanguage},
7-
library_mode::generate_bindings,
8-
};
5+
use crate::{bindings::RunScriptOptions, library_mode::generate_bindings, BindingGeneratorDefault};
96
use anyhow::{bail, Context, Result};
107
use camino::{Utf8Path, Utf8PathBuf};
118
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
@@ -15,6 +12,8 @@ use std::io::Write;
1512
use std::process::{Command, Stdio};
1613
use uniffi_testing::UniFFITestHelper;
1714

15+
use crate::bindings::TargetLanguage;
16+
1817
/// Run Swift tests for a UniFFI test fixture
1918
pub fn run_test(tmp_dir: &str, fixture_name: &str, script_file: &str) -> Result<()> {
2019
run_script(
@@ -129,7 +128,10 @@ impl GeneratedSources {
129128
let sources = generate_bindings(
130129
cdylib_path,
131130
None,
132-
&[TargetLanguage::Swift],
131+
&BindingGeneratorDefault {
132+
target_languages: vec![TargetLanguage::Swift],
133+
try_format_code: false,
134+
},
133135
None,
134136
out_dir,
135137
false,

0 commit comments

Comments
 (0)