Skip to content

Commit

Permalink
refactor(err): use anyhow context()
Browse files Browse the repository at this point in the history
Addresses kindelia#247.

use anyhow::Context trait to Replace calls to
map_err(|e| anyhow!("...{}", e)) with .context("...").

This does two things:
1. Makes the code and error messages more succinct and readable.
2. Preserves the original error
  • Loading branch information
dan-da committed Dec 2, 2022
1 parent e5ba140 commit 09d4558
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 93 deletions.
67 changes: 31 additions & 36 deletions kindelia/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{path::PathBuf, str::FromStr};

use crate::files::FileInput;
use anyhow::anyhow;
use anyhow::{anyhow, Context};

// ConfigSettings
// ==============
Expand Down Expand Up @@ -86,18 +86,17 @@ where
if let Some(config_values) = config_values {
let value = Self::get_prop(config_values, &prop_path);
if let Some(value) = value {
return T::arg_from(value).map(|v| Some(v)).map_err(|e| {
anyhow!(
"Could not convert value of '{}' into desired type: {}",
prop_path,
e
)
});
return T::arg_from(value).map(|v| Some(v)).context(anyhow!(
"Could not convert value of '{}' into desired type",
prop_path
));
}
}
Ok(None)
} else {
panic!("Cannot resolve from config file config without 'prop' field set")
Err(anyhow!(
"Cannot resolve from config file config without 'prop' field set"
))
}
}

Expand All @@ -108,16 +107,14 @@ where
where
T: ArgumentFrom<toml::Value>,
{
let value = Self::get_prop(config_values, prop_path).ok_or_else(|| {
anyhow!("Could not find prop '{}' in config file.", prop_path)
})?;
T::arg_from(value).map_err(|e| {
anyhow!(
"Could not convert value of '{}' into desired type: {}",
prop_path,
e
)
})
let value = Self::get_prop(config_values, prop_path).context(anyhow!(
"Could not find prop '{}' in config file.",
prop_path
))?;
T::arg_from(value).context(anyhow!(
"Could not convert value of '{}' into desired type",
prop_path,
))
}

fn get_prop(mut value: &toml::Value, prop_path: &str) -> Option<toml::Value> {
Expand Down Expand Up @@ -149,13 +146,13 @@ impl ArgumentFrom<String> for String {

impl ArgumentFrom<String> for u32 {
fn arg_from(t: String) -> anyhow::Result<Self> {
t.parse().map_err(|e| anyhow!("Invalid integer: `{}`", e))
t.parse().context(anyhow!("Invalid integer: `{}`", t))
}
}

impl ArgumentFrom<String> for u64 {
fn arg_from(t: String) -> anyhow::Result<Self> {
t.parse().map_err(|e| anyhow!("Invalid integer: `{}`", e))
t.parse().context(anyhow!("Invalid integer: `{}`", t))
}
}

Expand All @@ -166,7 +163,7 @@ impl ArgumentFrom<toml::Value> for u32 {
toml::Value::String(s) => {
let s = s.trim_start_matches("0x");
let num = u32::from_str_radix(s, 16)
.map_err(|e| anyhow!("Invalid hexadecimal '{}': {}", s, e))?;
.context(anyhow!("Invalid hexadecimal '{}'", s))?;
Ok(num)
}
_ => Err(anyhow!("Invalid integer '{}'", value)),
Expand All @@ -181,7 +178,7 @@ impl ArgumentFrom<toml::Value> for u64 {
toml::Value::String(s) => {
let s = s.trim_start_matches("0x");
let num = u64::from_str_radix(s, 16)
.map_err(|e| anyhow!("Invalid hexadecimal '{}': {}", s, e))?;
.context(anyhow!("Invalid hexadecimal '{}'", s))?;
Ok(num)
}
_ => Err(anyhow!("Invalid integer '{}'", value)),
Expand Down Expand Up @@ -210,45 +207,44 @@ impl ArgumentFrom<String> for bool {
impl ArgumentFrom<String> for PathBuf {
fn arg_from(t: String) -> anyhow::Result<Self> {
if let Some(path) = t.strip_prefix("~/") {
let home_dir = dirs::home_dir()
.ok_or_else(|| anyhow!("Could not find $HOME directory."))?;
let home_dir =
dirs::home_dir().context("Could not find $HOME directory.")?;
Ok(home_dir.join(path))
} else {
PathBuf::from_str(&t).map_err(|_| anyhow!("Invalid path: {}", t))
PathBuf::from_str(&t).context(anyhow!("Invalid path: {}", t))
}
}
}

impl ArgumentFrom<toml::Value> for PathBuf {
fn arg_from(value: toml::Value) -> anyhow::Result<Self> {
let t: String = value
.try_into()
.map_err(|_| anyhow!("Could not convert value to PathBuf"))?;
let t: String =
value.try_into().context("Could not convert value to PathBuf")?;
PathBuf::arg_from(t)
}
}

impl ArgumentFrom<toml::Value> for String {
fn arg_from(t: toml::Value) -> anyhow::Result<Self> {
t.try_into().map_err(|_| anyhow!("Could not convert value into String"))
t.try_into().context("Could not convert value into String")
}
}

impl ArgumentFrom<toml::Value> for Vec<String> {
fn arg_from(t: toml::Value) -> anyhow::Result<Self> {
t.try_into().map_err(|_| anyhow!("Could not convert value into array"))
t.try_into().context("Could not convert value into array")
}
}

impl ArgumentFrom<toml::Value> for bool {
fn arg_from(t: toml::Value) -> anyhow::Result<Self> {
t.as_bool().ok_or_else(|| anyhow!("Invalid boolean value: {}", t))
t.as_bool().context(anyhow!("Invalid boolean value: {}", t))
}
}

impl ArgumentFrom<toml::Value> for kindelia_core::config::ApiConfig {
fn arg_from(t: toml::Value) -> anyhow::Result<Self> {
t.try_into().map_err(|_| anyhow!("Could not convert value into array"))
t.try_into().context("Could not convert value into array")
}
}

Expand All @@ -258,9 +254,8 @@ pub fn arg_from_file_or_stdin<T: ArgumentFrom<String>>(
match file {
FileInput::Path { path } => {
// read from file
let content = std::fs::read_to_string(&path).map_err(|err| {
anyhow!("Cannot read from '{:?}' file: {}", path, err)
})?;
let content = std::fs::read_to_string(&path)
.context(anyhow!("Cannot read from '{:?}'", path))?;
T::arg_from(content)
}
FileInput::Stdin => {
Expand Down
6 changes: 3 additions & 3 deletions kindelia/src/files.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use anyhow::anyhow;
use anyhow::Context;
use std::fmt::{Display, Formatter};
use std::io::Read;
use std::path::PathBuf;
Expand Down Expand Up @@ -46,14 +46,14 @@ impl FileInput {
FileInput::Path { path } => {
// read from file
std::fs::read_to_string(path)
.map_err(|e| anyhow!("Cannot read from '{:?}' cause: {}", path, e))
.context(format!("Cannot read from '{:?}'", path))
}
FileInput::Stdin => {
// read from stdin
let mut buff = String::new();
std::io::stdin()
.read_to_string(&mut buff)
.map_err(|e| anyhow!("Could not read from stdin: {}", e))?;
.context("Could not read from stdin")?;
Ok(buff)
}
}
Expand Down
Loading

0 comments on commit 09d4558

Please sign in to comment.