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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#![allow(dead_code)] // FIXME Remove this later.
/// Utility enum for representing JVM method types.
/// TODO Move this somewhere better so that it's more descriptive.
pub enum JvmType {
Boolean,
Byte,
Char,
Short,
Int,
Long,
Float,
Double,
/// On the left is the package componenets, on the right is the class name itself.
Class(Vec<String>, String),
/// Makes it an array of the type.
Array(Box<JvmType>) // Boxed because sizing is silly.
}
// TODO: `Into<String>` or `ToString`?
impl Into<String> for JvmType {
fn into(self) -> String {
use self::JvmType::*;
match self {
Boolean => "Z".into(),
Byte => "B".into(),
Char => "C".into(),
Short => "S".into(),
Int => "I".into(),
Long => "J".into(),
Float => "F".into(),
Double => "D".into(),
Class(pkg, cls) => {
let mut pp = String::new();
for n in pkg {
pp.push_str(n.as_str());
pp.push('/');
}
format!("L{}{};", pp, cls)
},
Array(at) => {
let jt: JvmType = *at; // It's yelling at me about type annotations.
let s: String = jt.into();
format!("[{}", s)
}
}
}
}
/// Computes the JVM name for the method type specified by the arguments.
pub fn compute_jvm_method_signature(ret: Option<JvmType>, args: Vec<JvmType>) -> String {
let mut a = String::new();
for arg in args {
let rep: String = arg.into(); // Still complaining about type annotations.
a.push_str(rep.as_str());
}
let rrep: String = ret.map_or("".into(), |t| t.into());
format!("({}){}", a, rrep)
}
// TODO Write a macro that wraps the call to compute_jvm_method_signature, because it's still ugly.
#[cfg(test)]
mod tests {
use super::JvmType;
use super::compute_jvm_method_signature;
#[test]
fn jvm_method_test_1() {
// void foo();
assert_eq!(compute_jvm_method_signature(None, vec![]), String::from("()"))
}
#[test]
fn jvm_method_test_2() {
// long f (int n, String s, int[] arr); // (from the JNI docs)
assert_eq!(
compute_jvm_method_signature(
Some(JvmType::Long),
vec![
JvmType::Int,
JvmType::Class(vec!["java".into(), "lang".into()], "String".into()),
JvmType::Array(Box::new(JvmType::Int))]),
String::from("(ILjava/lang/String;[I)J"))
}
}