utils/
lib.rs

1//! This is an utils crate with functions that are used in the main crate, macros, and tests
2use std::{io, path::{Path, PathBuf}, process::Command};
3
4pub static CLASS_DIR: &'static str = "./target/tmp/classes";
5
6/// Convert the first letter of a String into uppercase
7pub fn first_char_uppercase(s: &str) -> String {
8    let mut c = s.chars();
9    match c.next() {
10        Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
11        None => String::new(),
12    }
13}
14
15/// Converts a ClassPath that uses *slashes* `/` to separate components to a Class that uses *dots* `.`.
16/// 
17/// e.g. `"[Ljava/lang/String;" -> "[Ljava.lang.String;"`
18pub fn java_path_to_dot_notation(path: &str) -> String {
19    path.replace(['/', '$'], ".")
20}
21
22/// Convert the *fully-qualified* name of a *Java method* to the name that should be used in the native code.
23pub fn java_method_to_symbol(class: &str, method: &str) -> String {
24    format!("Java_{class}_{name}",
25        class = class
26            .replace('.', "_")
27            .replace('/', "_"),
28        name = method.replace('_', "_1"),
29    )
30}
31
32pub fn absolute_path(path: impl AsRef<Path>) -> PathBuf {
33    let path = path.as_ref();
34    path.canonicalize()
35        .unwrap_or_else(|err| panic!("Failed to make path \"{}\" absolute: {err}", path.display()))
36}
37pub fn run(command: &mut Command) -> io::Result<String> {
38    let command_name = command.get_program().to_string_lossy().to_string();
39    // Spawn the command, waiting for it to return.
40    let output = command.output()
41        .map_err(|err| io::Error::new(err.kind(), format!("Failed to spawn command \"{command_name}\": {err}")))?;
42    // Return the command's error stream if it returned an error
43    if !output.status.success() {
44        let error = String::from_utf8_lossy(&output.stderr);
45        return Err(io::Error::other(format!("Command \"{command_name}\" exited with error:\n{error}")))
46    }
47
48    String::from_utf8(output.stdout)
49        .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, format!("Failed to decode output of command \"{command_name}\": {err}")))
50}