diff options
author | Sam Tay <sam.chong.tay@gmail.com> | 2020-06-08 23:16:05 -0700 |
---|---|---|
committer | Sam Tay <sam.chong.tay@gmail.com> | 2020-06-08 23:16:05 -0700 |
commit | 0056c5a93feabf96f432c5a50bd492742483acbd (patch) | |
tree | 2bf23190da8964c2a62f97ca05198c36cd491abc | |
parent | 546fc51006e2bcb9acf301a8c06a49a1d982bce1 (diff) |
Clean up reading/writing to files
-rw-r--r-- | src/config.rs | 19 | ||||
-rw-r--r-- | src/error.rs | 6 | ||||
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/stackexchange.rs | 25 | ||||
-rw-r--r-- | src/utils.rs | 24 |
5 files changed, 50 insertions, 25 deletions
diff --git a/src/config.rs b/src/config.rs index 1d854b9..af51de3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,10 +1,10 @@ use directories::ProjectDirs; use serde::{Deserialize, Serialize}; use std::fs; -use std::fs::File; use std::path::PathBuf; -use crate::error::{Error, PermissionType, Result}; +use crate::error::{Error, Result}; +use crate::utils; #[derive(Deserialize, Serialize, Debug)] pub struct Config { @@ -27,25 +27,22 @@ impl Default for Config { pub fn user_config() -> Result<Config> { let project = project_dir()?; let dir = project.config_dir(); - fs::create_dir_all(&dir) - .map_err(|_| Error::Permissions(PermissionType::Create, dir.to_path_buf()))?; + fs::create_dir_all(&dir)?; let filename = config_file_name()?; - match File::open(&filename) { - Err(_) => { + match utils::open_file(&filename)? { + None => { let def = Config::default(); write_config(&def)?; Ok(def) } - Ok(file) => serde_yaml::from_reader(file).map_err(|_| Error::MalformedFile(filename)), + Some(file) => serde_yaml::from_reader(file).map_err(|_| Error::MalformedFile(filename)), } } fn write_config(config: &Config) -> Result<()> { let filename = config_file_name()?; - let file = File::create(&filename) - .map_err(|_| Error::Permissions(PermissionType::Create, filename.clone()))?; - serde_yaml::to_writer(file, config) - .map_err(|_| Error::Permissions(PermissionType::Write, filename.clone())) + let file = utils::create_file(&filename)?; + Ok(serde_yaml::to_writer(file, config)?) } fn config_file_name() -> Result<PathBuf> { diff --git a/src/error.rs b/src/error.rs index d125fb2..86fb55f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -10,6 +10,10 @@ pub enum Error { Crossterm(#[from] crossterm::ErrorKind), #[error("Reqwest error: {0}")] Reqwest(#[from] reqwest::Error), + #[error("SerdeJson error: {0}")] + SerdeJson(#[from] serde_json::Error), + #[error("SerdeYaml error: {0}")] + SerdeYaml(#[from] serde_yaml::Error), #[error("IO error: {0}")] IO(#[from] std::io::Error), #[error("File `{}` is malformed; try removing it", .0.display())] @@ -28,6 +32,6 @@ pub enum Error { #[derive(Debug)] pub enum PermissionType { - Create, + Read, Write, } diff --git a/src/main.rs b/src/main.rs index 70ab6f4..7d1dd26 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod config; mod error; mod stackexchange; mod term; +mod utils; use crossterm::style::Color; use error::Error; diff --git a/src/stackexchange.rs b/src/stackexchange.rs index dce05de..cf03399 100644 --- a/src/stackexchange.rs +++ b/src/stackexchange.rs @@ -4,11 +4,11 @@ use reqwest::Url; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fs; -use std::fs::File; use std::path::PathBuf; use crate::config::{project_dir, Config}; -use crate::error::{Error, PermissionType, Result}; +use crate::error::{Error, Result}; +use crate::utils; /// StackExchange API v2.2 URL const SE_API_URL: &str = "http://api.stackexchange.com"; @@ -131,8 +131,7 @@ impl LocalStorage { pub fn new() -> Result<Self> { let project = project_dir()?; let dir = project.cache_dir(); - fs::create_dir_all(&dir) - .map_err(|_| Error::Permissions(PermissionType::Create, dir.to_path_buf()))?; + fs::create_dir_all(&dir)?; Ok(LocalStorage { sites: None, filename: dir.join("sites.json"), @@ -164,12 +163,14 @@ impl LocalStorage { } fn fetch_local_sites(&mut self) -> Result<bool> { - if let Ok(file) = File::open(&self.filename) { - self.sites = serde_json::from_reader(file) - .map_err(|_| Error::MalformedFile(self.filename.clone()))?; - return Ok(true); + match utils::open_file(&self.filename)? { + Some(file) => { + self.sites = serde_json::from_reader(file) + .map_err(|_| Error::MalformedFile(self.filename.clone()))?; + Ok(true) + } + None => Ok(false), } - Ok(false) } // TODO decide whether or not I should give LocalStorage an api key.. @@ -195,10 +196,8 @@ impl LocalStorage { } fn store_local_sites(&self) -> Result<()> { - let file = File::create(&self.filename) - .map_err(|_| Error::Permissions(PermissionType::Create, self.filename.clone()))?; - serde_json::to_writer(file, &self.sites) - .map_err(|_| Error::Permissions(PermissionType::Write, self.filename.clone())) + let file = utils::create_file(&self.filename)?; + Ok(serde_json::to_writer(file, &self.sites)?) } } diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..d1ffed8 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,24 @@ +use crate::error::{Error, PermissionType, Result}; +use std::fs::File; +use std::io::ErrorKind; +use std::path::PathBuf; + +pub fn open_file(filename: &PathBuf) -> Result<Option<File>> { + File::open(filename).map(Some).or_else(|e| match e { + e if e.kind() == ErrorKind::NotFound => Ok(None), + e if e.kind() == ErrorKind::PermissionDenied => { + Err(Error::Permissions(PermissionType::Read, filename.clone())) + } + e => Err(Error::from(e)), + }) +} + +pub fn create_file(filename: &PathBuf) -> Result<File> { + File::create(filename).map_err(|e| { + if e.kind() == ErrorKind::PermissionDenied { + Error::Permissions(PermissionType::Write, filename.clone()) + } else { + Error::from(e) + } + }) +} |