2025-12-17 13:17:58 -07:00
|
|
|
mod blob;
|
|
|
|
|
|
2025-12-17 10:20:50 -07:00
|
|
|
use std::{
|
|
|
|
|
collections::HashMap,
|
|
|
|
|
error::Error,
|
|
|
|
|
fs,
|
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
|
};
|
2025-12-16 22:23:54 -07:00
|
|
|
|
2025-12-17 10:38:37 -07:00
|
|
|
use unshell_lib::{debug, info};
|
2025-12-17 10:20:50 -07:00
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
|
2025-12-17 10:38:37 -07:00
|
|
|
struct ComponentMetadata {
|
2025-12-17 10:20:50 -07:00
|
|
|
name: String,
|
|
|
|
|
description: Option<String>,
|
|
|
|
|
version: Option<String>,
|
|
|
|
|
authors: Option<Vec<String>>,
|
|
|
|
|
|
|
|
|
|
// Struct to contain build information
|
2025-12-17 10:38:37 -07:00
|
|
|
#[serde(default)]
|
2025-12-17 10:20:50 -07:00
|
|
|
build_config: BuildConfig,
|
|
|
|
|
|
|
|
|
|
// Other components that can be pointed to by this component
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
child_components: Vec<PathBuf>,
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-17 10:38:37 -07:00
|
|
|
#[derive(Default, Debug, Clone, serde::Deserialize, serde::Serialize)]
|
2025-12-17 10:20:50 -07:00
|
|
|
struct BuildConfig {
|
|
|
|
|
// Cargo feature list of a component
|
|
|
|
|
// (Name, Description)
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
features: HashMap<String, String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
|
2025-12-17 16:40:34 -07:00
|
|
|
pub enum ConfigStructField {
|
2025-12-17 10:20:50 -07:00
|
|
|
Header(String),
|
|
|
|
|
Text(String),
|
|
|
|
|
String {
|
|
|
|
|
// Default value of string edit in struct
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
default: String,
|
|
|
|
|
max_length: Option<usize>,
|
|
|
|
|
// Display string edit as password
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
protected: Option<bool>,
|
|
|
|
|
},
|
|
|
|
|
Integer {
|
|
|
|
|
// Default value of integer in struct
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
default: i32,
|
|
|
|
|
min: Option<i32>,
|
|
|
|
|
max: Option<i32>,
|
|
|
|
|
},
|
|
|
|
|
// Checkbox
|
|
|
|
|
// Dropdown
|
|
|
|
|
// Collapsing header
|
|
|
|
|
// Slider
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-17 10:38:37 -07:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct ComponentState {
|
|
|
|
|
metadata: ComponentMetadata,
|
|
|
|
|
path: PathBuf,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn load_config(path: &PathBuf) -> Result<Vec<ComponentState>, Box<dyn Error>> {
|
2025-12-17 10:20:50 -07:00
|
|
|
let path_absolute = fs::canonicalize(path.clone())?;
|
2025-12-17 13:17:58 -07:00
|
|
|
debug!("Loading data from path: `{:?}`", path_absolute);
|
2025-12-17 10:20:50 -07:00
|
|
|
|
|
|
|
|
// Read string as path
|
|
|
|
|
let config_str = fs::read_to_string(path.clone())?;
|
|
|
|
|
|
|
|
|
|
// Load config from String
|
|
|
|
|
let config = toml::from_str::<ComponentMetadata>(&config_str)?;
|
|
|
|
|
|
2025-12-17 10:38:37 -07:00
|
|
|
info!("Loaded component `{}`", config.name);
|
|
|
|
|
|
|
|
|
|
let parent_path = path_absolute.parent().expect("Path must have parent");
|
|
|
|
|
|
2025-12-17 10:20:50 -07:00
|
|
|
if config.child_components.is_empty() {
|
2025-12-17 10:38:37 -07:00
|
|
|
Ok(vec![ComponentState {
|
|
|
|
|
metadata: config,
|
|
|
|
|
path: PathBuf::from(parent_path),
|
|
|
|
|
}])
|
2025-12-17 10:20:50 -07:00
|
|
|
} else {
|
|
|
|
|
let mut config_vec = vec![];
|
|
|
|
|
|
|
|
|
|
// Load each child component
|
|
|
|
|
for component_path in &config.child_components {
|
|
|
|
|
let path = Path::join(parent_path, component_path);
|
|
|
|
|
let mut config = load_config(&path)?;
|
|
|
|
|
config_vec.append(&mut config);
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-17 10:38:37 -07:00
|
|
|
config_vec.insert(
|
|
|
|
|
0,
|
|
|
|
|
ComponentState {
|
|
|
|
|
metadata: config,
|
|
|
|
|
path: PathBuf::from(parent_path),
|
|
|
|
|
},
|
|
|
|
|
);
|
2025-12-17 10:20:50 -07:00
|
|
|
|
|
|
|
|
Ok(config_vec)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// pub fn parse_toml() -> ComponentMetadata {
|
|
|
|
|
// let data = include_str!("../../test.toml");
|
|
|
|
|
|
|
|
|
|
// let config = toml::from_str(data).unwrap();
|
|
|
|
|
|
|
|
|
|
// config
|
|
|
|
|
// }
|