use std::collections::btree_map::BTreeMap;
use std::env;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::path::PathBuf;
use toml;
#[derive(Debug, Clone, Serialize, Deserialize)]
struct TomlPackage {
name: String,
metadata: Option<TomlMetadata>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct TomlMetadata {
android: Option<TomlAndroid>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct TomlAndroid {
package_name: Option<String>,
label: Option<String>,
icon: Option<String>,
assets: Option<String>,
res: Option<String>,
android_version: Option<u32>,
fullscreen: Option<bool>,
application_attributes: Option<BTreeMap<String, String>>,
activity_attributes: Option<BTreeMap<String, String>>,
build_targets: Option<Vec<String>>,
opengles_version_major: Option<u8>,
opengles_version_minor: Option<u8>,
}
pub struct Config {
pub ndk_path: PathBuf,
pub android_api: String,
pub project_path: PathBuf,
pub toolchain_target_dir: String,
pub package_name: String,
pub package_name_sanitized: String,
pub project_name: String,
pub package_label: String,
pub package_icon: Option<String>,
pub enable_arm: bool,
pub enable_arm64: bool,
pub enable_x86: bool,
pub enable_x86_64: bool,
pub enable_mips: bool,
pub enable_mips_64: bool,
pub build_targets: Vec<String>,
pub android_version: u32,
pub assets_path: Option<PathBuf>,
pub res_path: Option<PathBuf>,
pub release: bool,
pub fullscreen: bool,
pub application_attributes: Option<String>,
pub activity_attributes: Option<String>,
pub target: Option<String>,
pub opengles_version_major: u8,
pub opengles_version_minor: u8,
}
impl Config {
pub fn project_path_str(&self) -> &str {
self.project_path.to_str().unwrap()
}
}
pub fn load(manifest_path: &Path) -> Config {
let (package_name, manifest_content) = {
let content = {
let mut file = File::open(manifest_path).unwrap();
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
content
};
let toml = content.parse::<toml::Value>().unwrap();
let decoded: TomlPackage = toml["package"].clone().try_into::<TomlPackage>().unwrap();
let package_name = decoded.name.clone();
(package_name, decoded.metadata.and_then(|m| m.android))
};
let ndk_path = env::var("NDK_HOME").expect(
"Please set the path to the Android NDK with the \
$NDK_HOME environment variable.",
);
let manifest_parent = str::replace(&manifest_path.to_str().unwrap()[..], "/Cargo.toml", "");
let project_path = Path::new(&manifest_parent[..]).to_owned();
let n = &package_name.clone()[..];
let package_name_sanitized = str::replace(&str::replace(n, "-", "_")[..], "rust.", "");
Config {
ndk_path: Path::new(&ndk_path).to_owned(),
android_api: "24".to_owned(),
toolchain_target_dir: format!("{}/target", project_path.to_str().unwrap()),
project_path: project_path,
package_name: manifest_content
.as_ref()
.and_then(|a| a.package_name.clone())
.unwrap_or_else(|| format!("rust.{}", package_name)),
project_name: package_name.clone(),
package_name_sanitized: package_name_sanitized.clone(),
package_label: manifest_content
.as_ref()
.and_then(|a| a.label.clone())
.unwrap_or_else(|| package_name.clone()),
package_icon: manifest_content.as_ref().and_then(|a| a.icon.clone()),
enable_arm: false,
enable_arm64: false,
enable_x86: false,
enable_x86_64: false,
enable_mips: false,
enable_mips_64: false,
build_targets: manifest_content
.as_ref()
.and_then(|a| a.build_targets.clone())
.unwrap_or(vec!["arm-linux-androideabi".to_owned()]),
android_version: manifest_content
.as_ref()
.and_then(|a| a.android_version)
.unwrap_or(18),
assets_path: manifest_content
.as_ref()
.and_then(|a| a.assets.as_ref())
.map(|p| manifest_path.parent().unwrap().join(p)),
res_path: manifest_content.as_ref().and_then(|a| a.res.as_ref()).map(
|p| {
manifest_path.parent().unwrap().join(p)
},
),
release: false,
fullscreen: manifest_content
.as_ref()
.and_then(|a| a.fullscreen.clone())
.unwrap_or(false),
application_attributes: manifest_content.as_ref().and_then(|a| {
map_to_string(a.application_attributes.clone())
}),
activity_attributes: manifest_content.as_ref().and_then(|a| {
map_to_string(a.activity_attributes.clone())
}),
target: None,
opengles_version_major: manifest_content
.as_ref()
.and_then(|a| a.opengles_version_major)
.unwrap_or(2),
opengles_version_minor: manifest_content
.as_ref()
.and_then(|a| a.opengles_version_minor)
.unwrap_or(0),
}
}
fn map_to_string(input_map: Option<BTreeMap<String, String>>) -> Option<String> {
if let Some(map) = input_map {
let mut result = String::new();
for (key, val) in map {
result.push_str(&format!("\n{}=\"{}\"", key, val))
}
Some(result)
} else {
None
}
}