Skip to content

Commit

Permalink
Add Node.js Bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
CryZe committed Apr 2, 2017
1 parent ffc717e commit 2d649f9
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 93 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "livesplit-core"
version = "0.1.3"
version = "0.1.4"
authors = ["Christopher Serr <[email protected]>"]
documentation = "https://docs.rs/livesplit-core/"
repository = "https://github.com/CryZe/livesplit-core"
Expand Down
2 changes: 1 addition & 1 deletion capi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "livesplit-core-capi"
version = "0.1.3"
version = "0.1.4"
authors = ["Christopher Serr <[email protected]>"]

[dependencies]
Expand Down
3 changes: 2 additions & 1 deletion capi/bind_gen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[package]
authors = ["Christopher Serr <[email protected]>"]
name = "bindings"
version = "0.1.0"
authors = ["Christopher Serr <[email protected]>"]

[dependencies]
heck = "0.1.0"
syntex_syntax = "0.58.0"
21 changes: 3 additions & 18 deletions capi/bind_gen/src/csharp.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,6 @@
use std::io::{Write, Result};
use {Function, Type, TypeKind};

fn to_camel_case(snake_case: &str, cap_first_letter: bool) -> String {
let mut camel_case = String::new();

for (u, split) in snake_case.split('_').enumerate() {
for (i, c) in split.char_indices() {
if (cap_first_letter || u != 0) && i == 0 {
camel_case.extend(c.to_uppercase());
} else {
camel_case.push(c);
}
}
}

camel_case
}
use heck::{CamelCase, MixedCase};

fn get_type(ty: &Type, output: bool) -> &str {
match (ty.kind, ty.name.as_str()) {
Expand Down Expand Up @@ -87,7 +72,7 @@ namespace LiveSplitCore
public static extern {} {}("#,
&function.name,
get_type(&function.output, true),
to_camel_case(&postfix, true))?;
postfix.to_camel_case())?;

for (i, &(ref name, ref typ)) in function.inputs.iter().enumerate() {
if i != 0 {
Expand All @@ -99,7 +84,7 @@ namespace LiveSplitCore
if name == "this" {
String::from("self")
} else {
to_camel_case(name, false)
name.to_mixed_case()
})?;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::io::{Write, Result};
use {Function, Type, TypeKind};
use heck::MixedCase;

fn get_type(ty: &Type) -> &str {
match (ty.kind, ty.name.as_str()) {
Expand All @@ -14,16 +15,20 @@ pub fn write<W: Write>(mut writer: W, functions: &[Function]) -> Result<()> {

for function in functions {
let name = function.name.to_string();
let new_prefix = name.split('_').next().unwrap();
let mut splits = name.splitn(2, '_');
let new_prefix = splits.next().unwrap();
let postfix = splits.next().unwrap();
if !prefix.is_empty() && new_prefix != prefix {
writeln!(writer, "")?;
}
prefix = new_prefix.to_string();

write!(writer,
"var {0} = ls.cwrap('{0}', {1}, [",
"var {2}_{3} = ls.cwrap('{0}', {1}, [",
&function.name,
get_type(&function.output))?;
get_type(&function.output),
prefix,
postfix.to_mixed_case())?;

for (i, &(_, ref typ)) in function.inputs.iter().enumerate() {
if i != 0 {
Expand Down
21 changes: 3 additions & 18 deletions capi/bind_gen/src/java.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,6 @@
use std::io::{Write, Result};
use {Function, Type, TypeKind};

fn to_camel_case(snake_case: &str) -> String {
let mut camel_case = String::new();

for (u, split) in snake_case.split('_').enumerate() {
for (i, c) in split.char_indices() {
if u != 0 && i == 0 {
camel_case.extend(c.to_uppercase());
} else {
camel_case.push(c);
}
}
}

camel_case
}
use heck::MixedCase;

fn get_type(ty: &Type) -> &str {
match (ty.kind, ty.name.as_str()) {
Expand Down Expand Up @@ -101,7 +86,7 @@ public interface LiveSplitCore extends Library {
{} {}_{}("#,
get_type(&function.output),
prefix,
to_camel_case(postfix))?;
postfix.to_mixed_case())?;

for (i, &(ref name, ref typ)) in function.inputs.iter().enumerate() {
if i != 0 {
Expand All @@ -113,7 +98,7 @@ public interface LiveSplitCore extends Library {
if name == "this" {
String::from("self")
} else {
to_camel_case(name)
name.to_mixed_case()
})?;
}

Expand Down
56 changes: 25 additions & 31 deletions capi/bind_gen/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
extern crate syntex_syntax;
extern crate heck;

mod c;
mod csharp;
mod emscripten;
mod java;
mod javascript;
mod node;
mod python;
mod ruby;

Expand Down Expand Up @@ -128,41 +130,33 @@ fn write_files(functions: &[Function]) -> Result<()> {

fs::create_dir_all(&path)?;

{
let mut path = path.clone();
path.push("livesplit_core.js");
javascript::write(BufWriter::new(File::create(&path)?), functions)?;
}
path.push("livesplit_core_emscripten.js");
emscripten::write(BufWriter::new(File::create(&path)?), functions)?;
path.pop();

{
let mut path = path.clone();
path.push("LiveSplitCoreNative.cs");
csharp::write(BufWriter::new(File::create(&path)?), functions)?;
}
path.push("livesplit_core_node.js");
node::write(BufWriter::new(File::create(&path)?), functions)?;
path.pop();

{
let mut path = path.clone();
path.push("LiveSplitCore.java");
java::write(BufWriter::new(File::create(&path)?), functions)?;
}
path.push("LiveSplitCoreNative.cs");
csharp::write(BufWriter::new(File::create(&path)?), functions)?;
path.pop();

{
let mut path = path.clone();
path.push("LiveSplitCore.rb");
ruby::write(BufWriter::new(File::create(&path)?), functions)?;
}
path.push("LiveSplitCore.java");
java::write(BufWriter::new(File::create(&path)?), functions)?;
path.pop();

{
let mut path = path.clone();
path.push("livesplit_core.h");
c::write(BufWriter::new(File::create(&path)?), functions)?;
}
path.push("LiveSplitCore.rb");
ruby::write(BufWriter::new(File::create(&path)?), functions)?;
path.pop();

{
let mut path = path.clone();
path.push("livesplit_core.py");
python::write(BufWriter::new(File::create(&path)?), functions)?;
}
path.push("livesplit_core.h");
c::write(BufWriter::new(File::create(&path)?), functions)?;
path.pop();

path.push("livesplit_core.py");
python::write(BufWriter::new(File::create(&path)?), functions)?;
path.pop();

Ok(())
}
128 changes: 128 additions & 0 deletions capi/bind_gen/src/node.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
use std::io::{Write, Result};
use {Function, Type, TypeKind};
use heck::MixedCase;

fn get_type(ty: &Type) -> &str {
match (ty.kind, ty.name.as_str()) {
(TypeKind::Ref, "c_char") => "'CString'",
(TypeKind::Ref, _) |
(TypeKind::RefMut, _) => "'pointer'",
(_, t) if !ty.is_custom => {
match t {
"i8" => "'int8'",
"i16" => "'int16'",
"i32" => "'int32'",
"i64" => "'int64'",
"u8" => "'uint8'",
"u16" => "'uint16'",
"u32" => "'uint32'",
"u64" => "'uint64'",
"usize" => "'size_t'",
"f32" => "'float'",
"f64" => "'double'",
"bool" => "'bool'",
"()" => "'void'",
"c_char" => "'char'",
x => x,
}
}
_ => "'pointer'",
}
}

pub fn write<W: Write>(mut writer: W, functions: &[Function]) -> Result<()> {
let mut prefix = String::from("");

write!(writer,
"{}",
r#"var ffi = require('ffi');
var ls = ffi.Library('livesplit_core', {"#)?;

for function in functions {
let name = function.name.to_string();
let mut splits = name.splitn(2, '_');
let new_prefix = splits.next().unwrap();
if !prefix.is_empty() && new_prefix != prefix {
writeln!(writer, "")?;
}
prefix = new_prefix.to_string();

write!(writer,
r#"
'{}': [{}, ["#,
name,
get_type(&function.output))?;

for (i, &(_, ref typ)) in function.inputs.iter().enumerate() {
if i != 0 {
write!(writer, ", ")?;
}
write!(writer, "{}", get_type(typ))?;
}

write!(writer, "]],")?;
}

writeln!(writer,
"{}",
r#"
});"#)?;

for function in functions {
let name = function.name.to_string();
let mut splits = name.splitn(2, '_');
let new_prefix = splits.next().unwrap();
let postfix = splits.next().unwrap();

write!(writer,
r#"
exports.{}_{} = function("#,
new_prefix,
postfix.to_mixed_case())?;

for (i, &(ref name, _)) in function.inputs.iter().enumerate() {
if i != 0 {
write!(writer, ", ")?;
}
write!(writer,
"{}",
if name == "this" {
String::from("self")
} else {
name.to_mixed_case()
})?;
}

write!(writer,
"{}",
r#") {
"#)?;

if get_type(&function.output) != "'void'" {
write!(writer, "return ")?;
}

write!(writer, r#"ls.{}("#, name)?;

for (i, &(ref name, _)) in function.inputs.iter().enumerate() {
if i != 0 {
write!(writer, ", ")?;
}
write!(writer,
"{}",
if name == "this" {
String::from("self")
} else {
name.to_mixed_case()
})?;
}

writeln!(writer,
"{}",
r#");
};"#)?;
}

Ok(())
}
Loading

0 comments on commit 2d649f9

Please sign in to comment.