use std::{
fmt,
fs::{self, File},
io::{self, BufRead, BufReader, BufWriter, Write},
path::{Path, PathBuf},
};
use koibumi_node_sync::Config;
use crate::{
constant::{BOOTSTRAPS, LOCAL_SERVER, ONION_SEED, TOR_SOCKS},
param::Params,
};
#[derive(Debug)]
pub enum Error {
IoError(io::Error),
DeError(toml::de::Error),
SerError(toml::ser::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::IoError(err) => err.fmt(f),
Self::DeError(err) => err.fmt(f),
Self::SerError(err) => err.fmt(f),
}
}
}
impl std::error::Error for Error {}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
Self::IoError(err)
}
}
impl From<toml::de::Error> for Error {
fn from(err: toml::de::Error) -> Self {
Self::DeError(err)
}
}
impl From<toml::ser::Error> for Error {
fn from(err: toml::ser::Error) -> Self {
Self::SerError(err)
}
}
fn load_config_string(path: &Path) -> Result<String, Error> {
let f = File::open(path)?;
let reader = BufReader::new(f);
let lines = reader.lines().collect::<io::Result<Vec<String>>>()?;
Ok(lines.join("\n"))
}
fn default_config() -> Config {
Config::builder()
.server(Some(LOCAL_SERVER.parse().unwrap()))
.socks(Some(TOR_SOCKS.parse().unwrap()))
.connect_to_onion(true)
.connect_to_ip(true)
.seeds(vec![ONION_SEED.parse().unwrap()])
.bootstraps(vec![
BOOTSTRAPS[0].parse().unwrap(),
BOOTSTRAPS[1].parse().unwrap(),
])
.build()
}
pub fn load(params: &Params) -> Result<Config, Error> {
let mut path = params.data_dir().to_path_buf();
path.push("node.toml");
if !path.exists() {
return Ok(default_config());
}
let string = load_config_string(&path)?;
Ok(toml::from_str(&string)?)
}
pub(crate) fn create_data_dir(params: &Params) -> Result<PathBuf, io::Error> {
let path = params.data_dir();
if !path.exists() {
fs::create_dir_all(&path)?;
}
Ok(path.to_path_buf())
}
pub fn save(params: &Params, config: &Config) -> Result<(), Error> {
let string = toml::to_string(&config)?;
let path = params.data_dir();
if !path.exists() {
fs::create_dir_all(&path)?;
}
let mut new_path = path.to_path_buf();
new_path.push("node-new.toml");
let f = File::create(new_path.clone())?;
let mut writer = BufWriter::new(f);
writer.write_all(string.as_bytes())?;
writer.flush()?;
let mut to_path = path.to_path_buf();
to_path.push("node.toml");
fs::rename(new_path, to_path)?;
Ok(())
}