Skip to content

Commit

Permalink
bindgen: Overhaul the bindgen utility
Browse files Browse the repository at this point in the history
It now generates the target language directly instead of generating a c header which then needs to be separately converted to the target language. It also supports generating multiple languages in the future.
  • Loading branch information
madadam committed Sep 25, 2023
1 parent 335a357 commit efbee80
Show file tree
Hide file tree
Showing 15 changed files with 400 additions and 91 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ async-trait = "0.1.67"
btdht = { git = "https://github.com/equalitie/btdht.git", rev = "4b8dc478e3e5f011a45b8f50c424519019f7b70d" }
bytes = "1.4.0"
camino = "1.0.9"
clap = { version = "4.1.8", features = ["derive"] }
futures-util = { version = "0.3.27", default-features = false }
num_enum = { version = "0.5.11", default-features = false }
once_cell = "1.12.0"
Expand Down
7 changes: 5 additions & 2 deletions bindgen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[package]
name = "ouisync-bindgen"
description = "Bindings generator for the ouisync library"
publish = false
authors.workspace = true
edition.workspace = true
Expand All @@ -13,5 +14,7 @@ name = "bindgen"
path = "src/main.rs"

[dependencies]
cbindgen = "0.20.0"
env_logger = { version = "0.10.0", optional = true }
clap = { workspace = true }
heck = "0.4.1"
syn = { version = "2.0.33", default-features = false, features = ["parsing", "full", "extra-traits"] }
thiserror = { workspace = true }
67 changes: 67 additions & 0 deletions bindgen/src/dart.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use crate::parse::{Enum, Source};
use heck::AsLowerCamelCase;
use std::io::{self, Write};

pub(crate) fn generate(source: &Source, out: &mut dyn Write) -> io::Result<()> {
for (name, value) in &source.enums {
generate_enum(name, value, out)?;
}

Ok(())
}

fn generate_enum(name: &str, value: &Enum, out: &mut dyn Write) -> io::Result<()> {
writeln!(out, "enum {name} {{")?;

for variant in &value.variants {
writeln!(out, " {},", AsLowerCamelCase(&variant.name))?;
}

writeln!(out, " ;")?;
writeln!(out)?;

// decode
writeln!(out, " static {} decode(int n) {{", name)?;
writeln!(out, " switch (n) {{")?;

for variant in &value.variants {
writeln!(
out,
" case {}: return {}.{};",
variant.value,
name,
AsLowerCamelCase(&variant.name)
)?;
}

writeln!(
out,
" default: throw ArgumentError('invalid value: $n');"
)?;
writeln!(out, " }}")?;
writeln!(out, " }}")?;
writeln!(out)?;

// encode
writeln!(out, " int encode() {{")?;
writeln!(out, " switch (this) {{")?;

for variant in &value.variants {
writeln!(
out,
" case {}.{}: return {};",
name,
AsLowerCamelCase(&variant.name),
variant.value
)?;
}

writeln!(out, " }}")?;
writeln!(out, " }}")?;
writeln!(out)?;

writeln!(out, "}}")?;
writeln!(out)?;

Ok(())
}
60 changes: 38 additions & 22 deletions bindgen/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,43 @@
use cbindgen::{Builder, EnumConfig, Language, RenameRule};
use std::path::Path;
mod dart;
mod parse;

use clap::{Parser, ValueEnum};
use parse::{parse_file, Source};
use std::io;

fn main() -> Result<(), Box<dyn std::error::Error>> {
// Generate the C bindings header

#[cfg(feature = "env_logger")]
env_logger::init();

let output_path = Path::new("target").join("bindings.h");

Builder::new()
.with_config(cbindgen::Config {
language: Language::C,
enumeration: EnumConfig {
rename_variants: RenameRule::CamelCase,
..Default::default()
},
..Default::default()
})
.with_src(Path::new("ffi").join("src").join("lib.rs"))
.with_src(Path::new("bridge").join("src").join("constants.rs"))
.generate()?
.write_to_file(output_path);
let options = Options::parse();

let source_files = [
"bridge/src/protocol/mod.rs",
"ffi/src/lib.rs",
"lib/src/access_control/access_mode.rs",
"lib/src/directory/entry_type.rs",
];
let mut source = Source::new();

for source_file in source_files {
parse_file(source_file, &mut source)?;
}

match options.language {
Language::Dart => dart::generate(&source, &mut io::stdout())?,
Language::Kotlin => todo!(),
}

Ok(())
}

#[derive(Parser, Debug)]
#[command(about)]
struct Options {
/// Language to generate the bindings for
#[arg(short, long)]
language: Language,
}

#[derive(Clone, Copy, Debug, ValueEnum)]
enum Language {
Dart,
Kotlin,
}
Loading

0 comments on commit efbee80

Please sign in to comment.