summaryrefslogtreecommitdiff
path: root/rust/crates/bridge/src/bridge.rs
blob: 52dee731acda300b8f3c3c831be7251c3445db48 (plain) (blame)
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
use proc_macro::TokenStream;
use quote::quote;
use syn::{ItemFn, parse_macro_input};

#[proc_macro_attribute]
pub fn export(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let function = parse_macro_input!(item as ItemFn);
    let js_name = snake_to_camel(&function.sig.ident.to_string());

    quote! {
        #[cfg_attr(feature = "wasm", ::wasm_bindgen::prelude::wasm_bindgen(js_name = #js_name))]
        #function
    }
    .into()
}

fn snake_to_camel(name: &str) -> String {
    let mut camel = String::with_capacity(name.len());
    let mut should_uppercase_next = false;

    for character in name.chars() {
        if character == '_' {
            should_uppercase_next = true;
            continue;
        }

        if should_uppercase_next {
            camel.push(character.to_ascii_uppercase());
            should_uppercase_next = false;
            continue;
        }

        camel.push(character);
    }

    camel
}

#[cfg(test)]
mod tests {
    use super::snake_to_camel;

    #[test]
    fn converts_snake_case_to_camel_case() {
        assert_eq!(snake_to_camel("do_something"), "doSomething");
        assert_eq!(snake_to_camel("a_b_c"), "aBC");
        assert_eq!(snake_to_camel("already"), "already");
    }
}