use std::fs::read_link; use std::{collections::HashMap, fs, path::PathBuf};
use serde::Deserialize;
use toml::{self, de::Error};
#[derive(Debug, Clone, Deserialize)]
pub struct LectureConfig{
vec_file: Vec<PathBuf>,
title: String,
name: String,
vec_author: Vec<String>,
theme_path: PathBuf,
project_url: String,
documentation_url: String,
master_project: String,
contact_mail: String,
vec_parser: Vec<PathBuf>,
vec_environment: Vec<PathBuf>,
dependencies: HashMap<String, String>,
main_page_image: Option<PathBuf>,
}
impl LectureConfig{
pub fn get_vec_file(&self) -> &Vec<PathBuf>{
&self.vec_file
}
pub fn get_title(&self) -> &String{
&self.title
}
pub fn get_name(&self) -> &String{
&self.name
}
pub fn get_vec_author(&self) -> &Vec<String>{
&self.vec_author
}
pub fn get_theme_path(&self) -> &PathBuf{
&self.theme_path
}
pub fn get_project_url(&self) -> &String{
&self.project_url
}
pub fn get_documentation_url(&self) -> &String{
&self.documentation_url
}
pub fn get_master_project(&self) -> &String{
&self.master_project
}
pub fn get_contact_mail(&self) -> &String{
&self.contact_mail
}
pub fn get_vec_parser(&self) -> &Vec<PathBuf>{
&self.vec_parser
}
pub fn get_vec_environment(&self) -> &Vec<PathBuf>{
&self.vec_environment
}
pub fn get_map_dependency(&self) -> &HashMap<String, String>{
&self.dependencies
}
pub fn get_main_page_image(&self) -> &Option<PathBuf>{
&self.main_page_image
}
}
fn make_abolute_path(absolute_config_parent: &PathBuf, input_path: &PathBuf, program_prefix_share: &Option<PathBuf>) -> PathBuf {
match program_prefix_share {
Some(prefix) => { let str_input_path: String = String::from(input_path.to_str().unwrap());
if str_input_path.contains("${PREFIX_SHARE}") {
let absolute_path: PathBuf = PathBuf::from(str_input_path.replace("${PREFIX_SHARE}", prefix.to_str().unwrap()));
return absolute_path;
}else{ let absolute_path = absolute_config_parent.join(input_path);
return absolute_path;
}
},
None => {
let absolute_path = absolute_config_parent.join(input_path);
return absolute_path;
}
}
}
pub fn load_lecture_config(filename: &String) -> Result<LectureConfig, Error> {
let mut config: LectureConfig = match fs::read_to_string(filename) {
Ok(str) => match toml::from_str(&str){
Ok(value) => value,
Err(error) => panic!("load_lecture_config : cannot parse file '{}', parsing error {}", filename, error)
},
Err(err) => panic!("load_lecture_config : cannot read file '{}', error: {}", filename, err)
};
let config_path = PathBuf::from(filename);
let absolute_config = match config_path.canonicalize() {
Ok(absolute_config_path) => absolute_config_path,
Err(err) => panic!("load_lecture_config : cannot get absolute path of '{}'. Error {}", filename, err)
};
let absolute_config_parent: PathBuf = match absolute_config.parent() {
Some(abs_path) => PathBuf::from(abs_path),
None => panic!("load_lecture_config : no parent found for file {:?}", absolute_config)
};
let program_prefix_share: Option<PathBuf> = match read_link(&PathBuf::from("/proc/self/exe")) {
Ok(prefix) => Some(PathBuf::from(prefix.parent().unwrap().parent().unwrap().join("share"))),
Err(_) => None
};
let theme_path = PathBuf::from(config.get_theme_path());
if theme_path.is_relative() {
config.theme_path = make_abolute_path(&absolute_config_parent, &config.theme_path, &program_prefix_share);
}
for input_file in config.vec_file.iter_mut() {
if input_file.is_relative() {
*input_file = make_abolute_path(&absolute_config_parent, &input_file, &program_prefix_share);
}
}
for input_dir in config.vec_parser.iter_mut() {
if input_dir.is_relative() {
*input_dir = make_abolute_path(&absolute_config_parent, &input_dir, &program_prefix_share);
}
}
for input_dir in config.vec_environment.iter_mut() {
if input_dir.is_relative() {
*input_dir = make_abolute_path(&absolute_config_parent, &input_dir, &program_prefix_share);
}
}
match &mut config.main_page_image {
Some(main_page_image) => {
*main_page_image = make_abolute_path(&absolute_config_parent, &main_page_image, &program_prefix_share);
},
None => {}
}
Ok(config)
}
#[cfg(test)]
mod tests{
use super::*;
#[test]
fn test_load_lecture_config(){
let config: LectureConfig = load_lecture_config(&String::from("tests/LectureWithDependency/lecture.toml")).unwrap();
assert_eq!(config.get_vec_file().len(), 1);
assert!(config.get_vec_file().get(0).unwrap().ends_with(&String::from("index.md")));
assert_eq!(config.get_title().clone(), String::from("A great lecture"));
assert_eq!(config.get_name().clone(), String::from("TestLecture"));
assert_eq!(config.get_project_url().clone(), String::from("https://gitlab.in2p3.fr/CTA-LAPP/PHOENIX_LIBS2/static-site-generator/RustyPhoenixLecture"));
assert_eq!(config.get_documentation_url().clone(), String::from("https://cta-lapp.pages.in2p3.fr/PHOENIX_LIBS2/static-site-generator/RustyPhoenixLecture"));
assert_eq!(config.get_master_project().clone(), String::from("https://paubert.pages.in2p3.fr/Lectures/"));
assert_eq!(config.get_contact_mail().clone(), String::from("pierre.aubert@lapp.in2p3.fr"));
assert_eq!(config.get_vec_author().len(), 1);
assert_eq!(config.get_vec_author().get(0).unwrap().clone(), String::from("Pierre Aubert"));
assert!(config.get_theme_path().ends_with(&String::from("themes/book")));
assert_eq!(config.get_map_dependency().len(), 1);
assert_eq!(config.get_map_dependency().get(&String::from("performance_with_stencil")).unwrap(), &String::from("https://pages.gitlab.com/url/to/this/lecture/"));
}
}