use serde::Deserialize;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
use super::util::options_json_path;
use crate::error::{Error, Result};
#[derive(Debug, Clone, PartialEq)]
pub struct RekordboxOptions {
pub db_path: PathBuf,
pub analysis_root: PathBuf,
pub settings_root: PathBuf,
}
impl RekordboxOptions {
pub fn new<P: AsRef<Path> + AsRef<OsStr>>(
db_path: P,
analysis_root: P,
settings_root: P,
) -> Result<Self> {
Ok(Self {
db_path: Path::new(&db_path).to_path_buf(),
analysis_root: Path::new(&analysis_root).to_path_buf(),
settings_root: Path::new(&settings_root).to_path_buf(),
})
}
pub fn load<P: AsRef<Path> + AsRef<OsStr>>(path: P) -> Result<Self> {
#[derive(Debug, Deserialize)]
struct OptionsRaw {
options: Vec<Vec<String>>,
}
let file = std::fs::File::open(&path).map_err(|e| Error::FileNotFound(e.to_string()))?;
let reader = std::io::BufReader::new(file);
let raw: OptionsRaw = serde_json::from_reader(reader)?;
let mut db_path: Option<String> = None;
let mut analysis_root_path: Option<String> = None;
let mut settings_root_path: Option<String> = None;
for opt in raw.options {
if opt.len() < 2 {
continue; }
match opt[0].as_str() {
"db-path" => db_path = Some(opt[1].clone()),
"analysis-data-root-path" => analysis_root_path = Some(opt[1].clone()),
"settings-root-path" => settings_root_path = Some(opt[1].clone()),
_ => {}
}
}
if db_path.is_none() {
return Err(Error::OptionError(
"Database path not found in options".to_string(),
));
}
if analysis_root_path.is_none() {
return Err(Error::OptionError(
"Analysis root path not found in options".to_string(),
));
}
if settings_root_path.is_none() {
return Err(Error::OptionError(
"Settings root path not found in options".to_string(),
));
}
Self::new(
db_path.unwrap(),
analysis_root_path.unwrap(),
settings_root_path.unwrap(),
)
}
pub fn open() -> Result<Self> {
let file = options_json_path()?;
Self::load(&file)
}
pub fn get_db_dir(&self) -> PathBuf {
let path = self
.db_path
.parent()
.expect("Failed to get database directory");
path.to_path_buf()
}
}