use std::{collections::HashMap, fs::File, io::Read, path::Path};
use serde::Deserialize;
use toml::Value;
#[derive(Debug, Clone)]
pub struct ProjectDescriptor {
pub package: PackageDescriptor,
pub app: AppDescriptor,
pub settings: Option<HashMap<String, Value>>,
pub actions: Option<HashMap<String, ActionDescriptor>>,
}
#[derive(Debug, Deserialize, Clone)]
#[serde(rename(serialize = "component"))]
pub struct CargoToml {
pub package: PackageDescriptor,
}
#[derive(Debug, Deserialize, Clone)]
#[serde(rename(serialize = "component"))]
pub struct AppToml {
pub app: AppDescriptor,
pub settings: Option<HashMap<String, Value>>,
pub actions: Option<HashMap<String, ActionDescriptor>>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct PackageDescriptor {
pub name: String,
pub version: String,
pub authors: Option<Vec<String>>,
pub homepage: Option<String>,
pub license: Option<String>,
pub repository: Option<String>,
}
#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "kebab-case")]
pub struct AppDescriptor {
pub id: String,
pub name: Option<String>,
pub generic_name: Option<String>,
pub summary: String,
pub description: String,
pub categories: Vec<String>,
pub metadata_license: String,
pub screenshots: Option<Vec<Screenshot>>,
pub releases: Option<Vec<Release>>,
pub content_rating: Option<Vec<ContentRating>>,
pub requires: Vec<Recommend>,
pub recommends: Vec<Recommend>,
pub permissions: Vec<String>,
pub mimetype: Option<String>,
pub flatpak_runtime_version: Option<String>,
pub flatpak_modules: Option<Vec<String>>,
pub resources: Option<String>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct Release {
pub version: String,
pub date: String,
pub description: String,
}
#[derive(Debug, Deserialize, Clone)]
pub struct Screenshot {
#[serde(rename = "type")]
pub type_: Option<String>,
pub url: String,
}
#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "kebab-case")]
pub struct ContentRating {
pub id: String,
pub value: String,
}
#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "kebab-case")]
pub enum Recommend {
Display(String),
DisplayLength(String),
Control(String),
}
#[derive(Debug, Deserialize, Clone)]
pub struct ActionDescriptor {
pub state: Option<String>,
#[serde(rename = "type")]
pub type_: Option<String>,
pub accelerators: Option<Vec<String>>,
}
pub fn parse_project_descriptor(
cargo_toml_path: &Path,
app_toml_path: &Path,
) -> std::io::Result<ProjectDescriptor> {
let mut cargo_file = match File::open(cargo_toml_path) {
Ok(f) => f,
Err(e) => {
eprintln!("[gra] Could not read {:?}: {}", cargo_toml_path, e);
return Err(e);
}
};
let mut app_file = match File::open(app_toml_path) {
Ok(f) => f,
Err(e) => {
eprintln!("[gra] Could not read {:?}: {}", app_toml_path, e);
return Err(e);
}
};
let mut cargo_toml_content = String::new();
cargo_file.read_to_string(&mut cargo_toml_content)?;
let mut app_toml_content = String::new();
app_file.read_to_string(&mut app_toml_content)?;
match parse_project_descriptor_str(&cargo_toml_content, &app_toml_content) {
Err(e) => {
eprintln!("[gra] Error: {}.\n{}", e, cargo_toml_content);
Err(e)
}
Ok(p) => Ok(p),
}
}
pub fn parse_project_descriptor_str(
cargo_toml: &str,
app_toml: &str,
) -> std::io::Result<ProjectDescriptor> {
let cargo_toml: CargoToml = toml::from_str(cargo_toml)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, format!("{}.", e)))?;
let app_toml: AppToml = toml::from_str(app_toml)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, format!("{}.", e)))?;
Ok(ProjectDescriptor {
package: cargo_toml.package,
app: app_toml.app,
settings: app_toml.settings,
actions: app_toml.actions,
})
}