extern crate alloc;
use alloc::string::String;
use alloc::vec::Vec;
use crate::{ErrorKind, OrtResult, PromptOpts, cli::Env, common::utils, ort_error};
const DEFAULT_SAVE_TO_FILE: bool = true;
pub fn load_config(env: &Env, filename: &'static str) -> OrtResult<ConfigFile> {
let mut config_file = [0u8; 64];
let mut end = xdg_dir(
env.XDG_CONFIG_HOME.unwrap_or_default(),
env.HOME.unwrap_or_default(),
".config",
&mut config_file,
)?;
config_file[end] = b'/';
end += 1;
let start = end;
end += filename.len();
config_file[start..end].copy_from_slice(filename.as_bytes());
let config_file = unsafe { str::from_utf8_unchecked(&config_file[..end]) };
match utils::filename_read_to_string(config_file) {
Ok(cfg_str) => {
ConfigFile::from_json(&cfg_str).map_err(|_| ort_error(ErrorKind::ConfigParseFailed, ""))
}
Err("NOT FOUND") => Ok(ConfigFile::default()),
Err(_e) => Err(ort_error(ErrorKind::ConfigReadFailed, "")),
}
}
#[derive(Default)]
pub struct ConfigFile {
pub settings: Option<Settings>,
pub keys: Vec<ApiKey>,
pub prompt_opts: Option<PromptOpts>,
}
impl ConfigFile {
pub fn get_api_key(&self) -> Option<String> {
self.keys.first().as_ref().map(|k| k.value.clone())
}
pub fn _save_to_file(&self) -> bool {
self.settings
.as_ref()
.map(|s| s.save_to_file)
.unwrap_or(DEFAULT_SAVE_TO_FILE)
}
}
#[derive(Debug)]
pub struct Settings {
pub save_to_file: bool,
pub dns: Vec<String>,
}
impl Default for Settings {
fn default() -> Self {
Settings {
save_to_file: DEFAULT_SAVE_TO_FILE,
dns: Vec::new(),
}
}
}
#[derive(Debug, PartialEq)]
pub struct ApiKey {
name: String,
value: String,
}
impl ApiKey {
pub fn new(name: String, value: String) -> Self {
ApiKey { name, value }
}
}
pub fn cache_dir(env: &Env, cache_dir: &mut [u8]) -> OrtResult<usize> {
let mut end = xdg_dir(
env.XDG_CACHE_HOME.unwrap_or_default(),
env.HOME.unwrap_or_default(),
".cache",
cache_dir,
)?;
cache_dir[end] = b'/';
end += 1;
let start = end;
end += 3;
cache_dir[start..end].copy_from_slice("ort".as_bytes());
let cache_string = String::from_utf8_lossy(&cache_dir[..end]).into_owned();
utils::ensure_dir_exists(&cache_string);
Ok(end)
}
pub fn xdg_dir(
xdg_var_value: &str,
home_dir: &str,
default: &'static str,
target: &mut [u8],
) -> OrtResult<usize> {
if !xdg_var_value.is_empty() {
let dir_len = xdg_var_value.len();
target[..dir_len + 1].copy_from_slice(xdg_var_value.as_bytes());
return Ok(dir_len + 1);
}
if !home_dir.is_empty() {
let mut start = 0;
let mut end = home_dir.len();
target[start..end].copy_from_slice(home_dir.as_bytes());
target[end] = b'/';
end += 1;
start = end;
end += default.len();
target[start..end].copy_from_slice(default.as_bytes());
Ok(end)
} else {
Err(ort_error(
ErrorKind::MissingHomeDir,
"Could not get home dir. Is $HOME set?",
))
}
}