uniui_build 0.0.15

Builds uniui applicatins for different targets
use std::{
	cmp::Eq,
	collections::HashMap,
	hash::Hash,
};

#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct Func {
	pub name: String,
	pub export: String,
	pub result: String,
	pub params: Vec<String>,
}

#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct Config {
	pub funcs: Option<Vec<Func>>,
	pub manifest_path: String,
	pub main_function: Option<String>,
	pub java_files: Option<Vec<String>>,
}


pub fn process_manifest<T: Eq + Hash>(
	name: T,
	manifest: String,
	map: &mut HashMap<T, Option<Config>>,
) {
	map.entry(name).or_insert_with(|| get_config(manifest));
}


#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
struct Manifest {
	package: Package,
}

#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
struct Package {
	metadata: Option<Metadata>,
}

#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
struct Metadata {
	uni_android: Option<UniAndroid>,
}

#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
struct UniAndroid {
	export_func_file: Option<String>,
	main_function: Option<String>,
	java_files: Option<Vec<String>>,
}

/// There we are reading manifest file (should be located at `manifest_path`).
/// Then we read [package.metadata.uni_android] section of the manifest to fill
/// up `Config` and return it.
///
/// Returns `Some(Config)` when [package.metadata.uni_android] section found.
/// Otherwise return None. `panic` every time something went wrong. Designed to
/// be internally used inside `uniui_build` till we have better solution
pub fn get_config(manifest_path: String) -> Option<Config> {
	let content = std::fs::read(&manifest_path)
		.expect(&format!("File reading error. Path:{}", manifest_path));

	return match toml::from_slice::<Manifest>(&content) {
		Ok(manifest) => {
			let maybe_uni_android = manifest.package.metadata.and_then(|m| m.uni_android);

			match maybe_uni_android {
				None => None,
				Some(uni_android) => {
					let path_to_dir = {
						let mut p = std::path::Path::new(&manifest_path).to_path_buf();
						p.pop();
						p.to_str()
							.expect(&format!(
								"Couldn't convert path to String. Path:{}",
								p.display(),
							))
							.to_owned()
					};

					let funcs = match uni_android.export_func_file {
						None => None,
						Some(export_func_file) => {
							let path = {
								let mut p =
									std::path::Path::new(&manifest_path).to_path_buf();
								p.pop();
								p.push(export_func_file);
								p
							};

							let content = std::fs::read(&path).expect(&format!(
								"Failed to read provided export_func_file:{}",
								path.display()
							));

							let funcs = serde_json::from_slice(&content).expect(
								&format!("Couldn't parse file:{}", path.display()),
							);

							Some(funcs)
						},
					};

					Some(Config {
						funcs,
						manifest_path: path_to_dir,
						main_function: uni_android.main_function,
						java_files: uni_android.java_files,
					})
				},
			}
		},
		Err(e) => panic!("Manifest parsing error for {}. Err:{:?}", manifest_path, e),
	};
}