use std::{fs, path::PathBuf};
pub struct Settings {
path: PathBuf,
consent: Status,
persistence: Persistence,
cpu_fraction: f32,
threads: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Status {
Granted,
Denied,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Persistence {
Save,
Ask,
}
const DEFAULT_CPU_FRACTION: f32 = 0.25;
const DEFAULT_THREADS: usize = 1;
impl Settings {
pub fn new(application_name: &str) -> Self {
let path = dirs_path(application_name);
let mut settings = Self {
path,
consent: Status::Denied,
persistence: Persistence::Ask,
cpu_fraction: DEFAULT_CPU_FRACTION,
threads: DEFAULT_THREADS,
};
settings.load();
settings
}
fn load(&mut self) {
let Ok(content) = fs::read_to_string(&self.path) else {
return;
};
for line in content.lines() {
let Some((key, value)) = line.split_once(char::is_whitespace) else {
continue;
};
let value = value.trim();
match key {
"consent" => {
self.consent = match value {
"granted" => Status::Granted,
_ => Status::Denied,
};
}
"persistence" => {
self.persistence = match value {
"save" => Persistence::Save,
_ => Persistence::Ask,
};
}
"cpu_fraction" => {
if let Ok(parsed) = value.parse() {
self.cpu_fraction = parsed;
}
}
"threads" => {
if let Ok(parsed) = value.parse() {
self.threads = parsed;
}
}
_ => {}
}
}
}
pub fn save(&self) -> Result<(), std::io::Error> {
if self.persistence == Persistence::Ask {
let _ = fs::remove_file(&self.path);
return Ok(());
}
if let Some(parent) = self.path.parent() {
fs::create_dir_all(parent)?;
}
let consent = match self.consent {
Status::Granted => "granted",
Status::Denied => "denied",
};
let content = format!(
"consent {consent}\npersistence save\ncpu_fraction {}\nthreads {}\n",
self.cpu_fraction, self.threads,
);
fs::write(&self.path, content)
}
pub(crate) fn has_stored(&self) -> bool {
self.path.exists()
}
pub fn consent(&self) -> Status {
self.consent
}
pub fn set_consent(&mut self, consent: Status) {
self.consent = consent;
let _ = self.save();
}
pub fn persistence(&self) -> Persistence {
self.persistence
}
pub fn set_persistence(&mut self, persistence: Persistence) {
self.persistence = persistence;
if persistence == Persistence::Ask {
self.cpu_fraction = DEFAULT_CPU_FRACTION;
self.threads = DEFAULT_THREADS;
}
let _ = self.save();
}
pub fn cpu_fraction(&self) -> f32 {
self.cpu_fraction
}
pub fn set_cpu_fraction(&mut self, fraction: f32) {
self.cpu_fraction = fraction;
let _ = self.save();
}
pub fn threads(&self) -> usize {
self.threads
}
pub fn set_threads(&mut self, threads: usize) {
self.threads = threads;
let _ = self.save();
}
}
fn dirs_path(application_name: &str) -> PathBuf {
let base = dirs::config_dir().unwrap_or_else(|| PathBuf::from("."));
base.join(application_name).join("mining-settings")
}
pub struct Reply {
pub consent: Status,
pub persistence: Persistence,
}