aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-03-06 13:18:29 -0500
committerJesse Luehrs <doy@tozt.net>2021-03-06 13:18:29 -0500
commit9e77724efff281f0fe6d05440ad65c5ab561f380 (patch)
treeee5983d46b9f040a9c9880df9eb02b8d36956628
parentabc01f5a3865da5bd962402a8f7d9fd95c149622 (diff)
downloadrbw-9e77724efff281f0fe6d05440ad65c5ab561f380.tar.gz
rbw-9e77724efff281f0fe6d05440ad65c5ab561f380.zip
switch to thiserror
-rw-r--r--Cargo.lock49
-rw-r--r--Cargo.toml2
-rw-r--r--src/actions.rs4
-rw-r--r--src/api.rs20
-rw-r--r--src/cipherstring.rs37
-rw-r--r--src/config.rs52
-rw-r--r--src/db.rs67
-rw-r--r--src/dirs.rs30
-rw-r--r--src/error.rs99
-rw-r--r--src/identity.rs2
-rw-r--r--src/json.rs17
-rw-r--r--src/pinentry.rs19
-rw-r--r--src/prelude.rs1
13 files changed, 227 insertions, 172 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c5877bb..171687d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -394,12 +394,6 @@ dependencies = [
]
[[package]]
-name = "doc-comment"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
-
-[[package]]
name = "encoding_rs"
version = "0.8.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1187,11 +1181,11 @@ dependencies = [
"serde_json",
"serde_path_to_error",
"serde_repr",
- "snafu",
"structopt",
"tempfile",
"term_size",
"textwrap 0.13.4",
+ "thiserror",
"tokio",
"url",
"uuid",
@@ -1499,27 +1493,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
[[package]]
-name = "snafu"
-version = "0.6.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eab12d3c261b2308b0d80c26fffb58d17eba81a4be97890101f416b478c79ca7"
-dependencies = [
- "doc-comment",
- "snafu-derive",
-]
-
-[[package]]
-name = "snafu-derive"
-version = "0.6.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
name = "socket2"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1650,6 +1623,26 @@ dependencies = [
]
[[package]]
+name = "thiserror"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "thread_local"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index c447cc5..c731b7c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -39,11 +39,11 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_path_to_error = "0.1"
serde_repr = "0.1"
-snafu = "0.6"
structopt = { version = "0.3", features = ["paw", "wrap_help"] }
tempfile = "3.2"
term_size = "0.3"
textwrap = "0.13"
+thiserror = "1.0"
tokio = { version = "1.2", features = ["full"] }
url = "2.2"
uuid = { version = "0.8", features = ["v4"] }
diff --git a/src/actions.rs b/src/actions.rs
index bda8670..0d8c88d 100644
--- a/src/actions.rs
+++ b/src/actions.rs
@@ -259,7 +259,7 @@ where
{
match f(access_token) {
Ok(t) => Ok((None, t)),
- Err(crate::error::Error::RequestUnauthorized) => {
+ Err(Error::RequestUnauthorized) => {
let access_token = exchange_refresh_token(refresh_token)?;
let t = f(&access_token)?;
Ok((Some(access_token), t))
@@ -284,7 +284,7 @@ where
{
match f(access_token).await {
Ok(t) => Ok((None, t)),
- Err(crate::error::Error::RequestUnauthorized) => {
+ Err(Error::RequestUnauthorized) => {
let access_token =
exchange_refresh_token_async(refresh_token).await?;
let t = f(&access_token).await?;
diff --git a/src/api.rs b/src/api.rs
index 40fe422..99e12fd 100644
--- a/src/api.rs
+++ b/src/api.rs
@@ -563,7 +563,7 @@ impl Client {
.json(&prelogin)
.send()
.await
- .context(crate::error::Reqwest)?;
+ .map_err(|source| Error::Reqwest { source })?;
let prelogin_res: PreloginRes = res.json_with_path().await?;
Ok(prelogin_res.kdf_iterations)
}
@@ -597,7 +597,7 @@ impl Client {
.form(&connect_req)
.send()
.await
- .context(crate::error::Reqwest)?;
+ .map_err(|source| Error::Reqwest { source })?;
if let reqwest::StatusCode::OK = res.status() {
let connect_res: ConnectPasswordRes =
res.json_with_path().await?;
@@ -627,7 +627,7 @@ impl Client {
.header("Authorization", format!("Bearer {}", access_token))
.send()
.await
- .context(crate::error::Reqwest)?;
+ .map_err(|source| Error::Reqwest { source })?;
match res.status() {
reqwest::StatusCode::OK => {
let sync_res: SyncRes = res.json_with_path().await?;
@@ -769,7 +769,7 @@ impl Client {
.header("Authorization", format!("Bearer {}", access_token))
.json(&req)
.send()
- .context(crate::error::Reqwest)?;
+ .map_err(|source| Error::Reqwest { source })?;
match res.status() {
reqwest::StatusCode::OK => Ok(()),
reqwest::StatusCode::UNAUTHORIZED => {
@@ -902,7 +902,7 @@ impl Client {
.header("Authorization", format!("Bearer {}", access_token))
.json(&req)
.send()
- .context(crate::error::Reqwest)?;
+ .map_err(|source| Error::Reqwest { source })?;
match res.status() {
reqwest::StatusCode::OK => Ok(()),
reqwest::StatusCode::UNAUTHORIZED => {
@@ -920,7 +920,7 @@ impl Client {
.delete(&self.api_url(&format!("/ciphers/{}", id)))
.header("Authorization", format!("Bearer {}", access_token))
.send()
- .context(crate::error::Reqwest)?;
+ .map_err(|source| Error::Reqwest { source })?;
match res.status() {
reqwest::StatusCode::OK => Ok(()),
reqwest::StatusCode::UNAUTHORIZED => {
@@ -941,7 +941,7 @@ impl Client {
.get(&self.api_url("/folders"))
.header("Authorization", format!("Bearer {}", access_token))
.send()
- .context(crate::error::Reqwest)?;
+ .map_err(|source| Error::Reqwest { source })?;
match res.status() {
reqwest::StatusCode::OK => {
let folders_res: FoldersRes = res.json_with_path()?;
@@ -974,7 +974,7 @@ impl Client {
.header("Authorization", format!("Bearer {}", access_token))
.json(&req)
.send()
- .context(crate::error::Reqwest)?;
+ .map_err(|source| Error::Reqwest { source })?;
match res.status() {
reqwest::StatusCode::OK => {
let folders_res: FoldersResData = res.json_with_path()?;
@@ -1003,7 +1003,7 @@ impl Client {
.post(&self.identity_url("/connect/token"))
.form(&connect_req)
.send()
- .context(crate::error::Reqwest)?;
+ .map_err(|source| Error::Reqwest { source })?;
let connect_res: ConnectRefreshTokenRes = res.json_with_path()?;
Ok(connect_res.access_token)
}
@@ -1023,7 +1023,7 @@ impl Client {
.form(&connect_req)
.send()
.await
- .context(crate::error::Reqwest)?;
+ .map_err(|source| Error::Reqwest { source })?;
let connect_res: ConnectRefreshTokenRes =
res.json_with_path().await?;
Ok(connect_res.access_token)
diff --git a/src/cipherstring.rs b/src/cipherstring.rs
index c1bd80d..f213cf7 100644
--- a/src/cipherstring.rs
+++ b/src/cipherstring.rs
@@ -48,17 +48,17 @@ impl CipherString {
}
let iv = base64::decode(parts[0])
- .context(crate::error::InvalidBase64)?;
+ .map_err(|source| Error::InvalidBase64 { source })?;
let ciphertext = base64::decode(parts[1])
- .context(crate::error::InvalidBase64)?;
- let mac = if parts.len() > 2 {
- Some(
- base64::decode(parts[2])
- .context(crate::error::InvalidBase64)?,
- )
- } else {
- None
- };
+ .map_err(|source| Error::InvalidBase64 { source })?;
+ let mac =
+ if parts.len() > 2 {
+ Some(base64::decode(parts[2]).map_err(|source| {
+ Error::InvalidBase64 { source }
+ })?)
+ } else {
+ None
+ };
Ok(Self::Symmetric {
iv,
@@ -73,7 +73,7 @@ impl CipherString {
// format is: <cipher_text_b64>|<hmac_sig>
let contents = contents.split('|').next().unwrap();
let ciphertext = base64::decode(contents)
- .context(crate::error::InvalidBase64)?;
+ .map_err(|source| Error::InvalidBase64 { source })?;
Ok(Self::Asymmetric { ciphertext })
}
_ => {
@@ -100,7 +100,7 @@ impl CipherString {
aes::Aes256,
block_modes::block_padding::Pkcs7,
>::new_var(keys.enc_key(), &iv)
- .context(crate::error::CreateBlockMode)?;
+ .map_err(|source| Error::CreateBlockMode { source })?;
let ciphertext = cipher.encrypt_vec(plaintext);
let mut digest = ring::hmac::Context::with_key(
@@ -135,7 +135,7 @@ impl CipherString {
)?;
cipher
.decrypt_vec(ciphertext)
- .context(crate::error::Decrypt)
+ .map_err(|source| Error::Decrypt { source })
}
_ => Err(Error::InvalidCipherString {
reason:
@@ -165,7 +165,7 @@ impl CipherString {
)?;
cipher
.decrypt(res.data_mut())
- .context(crate::error::Decrypt)?;
+ .map_err(|source| Error::Decrypt { source })?;
Ok(res)
}
_ => Err(Error::InvalidCipherString {
@@ -188,8 +188,9 @@ impl CipherString {
let pkey = openssl::pkey::PKey::private_key_from_pkcs8(
private_key.private_key(),
)
- .context(crate::error::OpenSSL)?;
- let rsa = pkey.rsa().context(crate::error::OpenSSL)?;
+ .map_err(|source| Error::OpenSSL { source })?;
+ let rsa =
+ pkey.rsa().map_err(|source| Error::OpenSSL { source })?;
let mut res = crate::locked::Vec::new();
res.extend(std::iter::repeat(0).take(rsa.size() as usize));
@@ -200,7 +201,7 @@ impl CipherString {
res.data_mut(),
openssl::rsa::Padding::PKCS1_OAEP,
)
- .context(crate::error::OpenSSL)?;
+ .map_err(|source| Error::OpenSSL { source })?;
res.truncate(bytes);
Ok(res)
@@ -241,7 +242,7 @@ fn decrypt_common_symmetric(
aes::Aes256,
block_modes::block_padding::Pkcs7,
>::new_var(keys.enc_key(), iv)
- .context(crate::error::CreateBlockMode)?)
+ .map_err(|source| Error::CreateBlockMode { source })?)
}
impl std::fmt::Display for CipherString {
diff --git a/src/config.rs b/src/config.rs
index 9bb4696..dbdf759 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -41,15 +41,20 @@ impl Config {
pub fn load() -> Result<Self> {
let file = crate::dirs::config_file();
- let mut fh = std::fs::File::open(&file).with_context(|| {
- crate::error::LoadConfig { file: file.clone() }
+ let mut fh = std::fs::File::open(&file).map_err(|source| {
+ Error::LoadConfig {
+ source,
+ file: file.clone(),
+ }
})?;
let mut json = String::new();
- fh.read_to_string(&mut json).with_context(|| {
- crate::error::LoadConfig { file: file.clone() }
- })?;
+ fh.read_to_string(&mut json)
+ .map_err(|source| Error::LoadConfig {
+ source,
+ file: file.clone(),
+ })?;
let mut slf: Self = serde_json::from_str(&json)
- .context(crate::error::LoadConfigJson { file })?;
+ .map_err(|source| Error::LoadConfigJson { source, file })?;
if slf.lock_timeout == 0 {
log::warn!("lock_timeout must be greater than 0");
slf.lock_timeout = default_lock_timeout();
@@ -60,15 +65,21 @@ impl Config {
pub async fn load_async() -> Result<Self> {
let file = crate::dirs::config_file();
let mut fh =
- tokio::fs::File::open(&file).await.with_context(|| {
- crate::error::LoadConfigAsync { file: file.clone() }
+ tokio::fs::File::open(&file).await.map_err(|source| {
+ Error::LoadConfigAsync {
+ source,
+ file: file.clone(),
+ }
})?;
let mut json = String::new();
- fh.read_to_string(&mut json).await.with_context(|| {
- crate::error::LoadConfigAsync { file: file.clone() }
+ fh.read_to_string(&mut json).await.map_err(|source| {
+ Error::LoadConfigAsync {
+ source,
+ file: file.clone(),
+ }
})?;
let mut slf: Self = serde_json::from_str(&json)
- .context(crate::error::LoadConfigJson { file })?;
+ .map_err(|source| Error::LoadConfigJson { source, file })?;
if slf.lock_timeout == 0 {
log::warn!("lock_timeout must be greater than 0");
slf.lock_timeout = default_lock_timeout();
@@ -80,20 +91,27 @@ impl Config {
let file = crate::dirs::config_file();
// unwrap is safe here because Self::filename is explicitly
// constructed as a filename in a directory
- std::fs::create_dir_all(file.parent().unwrap()).with_context(
- || crate::error::SaveConfig { file: file.clone() },
+ std::fs::create_dir_all(file.parent().unwrap()).map_err(
+ |source| Error::SaveConfig {
+ source,
+ file: file.clone(),
+ },
)?;
- let mut fh = std::fs::File::create(&file).with_context(|| {
- crate::error::SaveConfig { file: file.clone() }
+ let mut fh = std::fs::File::create(&file).map_err(|source| {
+ Error::SaveConfig {
+ source,
+ file: file.clone(),
+ }
})?;
fh.write_all(
serde_json::to_string(self)
- .with_context(|| crate::error::SaveConfigJson {
+ .map_err(|source| Error::SaveConfigJson {
+ source,
file: file.clone(),
})?
.as_bytes(),
)
- .context(crate::error::SaveConfig { file })?;
+ .map_err(|source| Error::SaveConfig { source, file })?;
Ok(())
}
diff --git a/src/db.rs b/src/db.rs
index 067f36f..5359321 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -179,28 +179,40 @@ impl Db {
pub fn load(server: &str, email: &str) -> Result<Self> {
let file = crate::dirs::db_file(server, email);
- let mut fh = std::fs::File::open(&file)
- .with_context(|| crate::error::LoadDb { file: file.clone() })?;
+ let mut fh =
+ std::fs::File::open(&file).map_err(|source| Error::LoadDb {
+ source,
+ file: file.clone(),
+ })?;
let mut json = String::new();
fh.read_to_string(&mut json)
- .with_context(|| crate::error::LoadDb { file: file.clone() })?;
+ .map_err(|source| Error::LoadDb {
+ source,
+ file: file.clone(),
+ })?;
let slf: Self = serde_json::from_str(&json)
- .context(crate::error::LoadDbJson { file })?;
+ .map_err(|source| Error::LoadDbJson { source, file })?;
Ok(slf)
}
pub async fn load_async(server: &str, email: &str) -> Result<Self> {
let file = crate::dirs::db_file(server, email);
let mut fh =
- tokio::fs::File::open(&file).await.with_context(|| {
- crate::error::LoadDbAsync { file: file.clone() }
+ tokio::fs::File::open(&file).await.map_err(|source| {
+ Error::LoadDbAsync {
+ source,
+ file: file.clone(),
+ }
})?;
let mut json = String::new();
- fh.read_to_string(&mut json).await.with_context(|| {
- crate::error::LoadDbAsync { file: file.clone() }
+ fh.read_to_string(&mut json).await.map_err(|source| {
+ Error::LoadDbAsync {
+ source,
+ file: file.clone(),
+ }
})?;
let slf: Self = serde_json::from_str(&json)
- .context(crate::error::LoadDbJson { file })?;
+ .map_err(|source| Error::LoadDbJson { source, file })?;
Ok(slf)
}
@@ -209,18 +221,26 @@ impl Db {
let file = crate::dirs::db_file(server, email);
// unwrap is safe here because Self::filename is explicitly
// constructed as a filename in a directory
- std::fs::create_dir_all(file.parent().unwrap())
- .with_context(|| crate::error::SaveDb { file: file.clone() })?;
- let mut fh = std::fs::File::create(&file)
- .with_context(|| crate::error::SaveDb { file: file.clone() })?;
+ std::fs::create_dir_all(file.parent().unwrap()).map_err(
+ |source| Error::SaveDb {
+ source,
+ file: file.clone(),
+ },
+ )?;
+ let mut fh =
+ std::fs::File::create(&file).map_err(|source| Error::SaveDb {
+ source,
+ file: file.clone(),
+ })?;
fh.write_all(
serde_json::to_string(self)
- .with_context(|| crate::error::SaveDbJson {
+ .map_err(|source| Error::SaveDbJson {
+ source,
file: file.clone(),
})?
.as_bytes(),
)
- .context(crate::error::SaveDb { file })?;
+ .map_err(|source| Error::SaveDb { source, file })?;
Ok(())
}
@@ -231,22 +251,27 @@ impl Db {
// constructed as a filename in a directory
tokio::fs::create_dir_all(file.parent().unwrap())
.await
- .with_context(|| crate::error::SaveDbAsync {
+ .map_err(|source| Error::SaveDbAsync {
+ source,
file: file.clone(),
})?;
let mut fh =
- tokio::fs::File::create(&file).await.with_context(|| {
- crate::error::SaveDbAsync { file: file.clone() }
+ tokio::fs::File::create(&file).await.map_err(|source| {
+ Error::SaveDbAsync {
+ source,
+ file: file.clone(),
+ }
})?;
fh.write_all(
serde_json::to_string(self)
- .with_context(|| crate::error::SaveDbJson {
+ .map_err(|source| Error::SaveDbJson {
+ source,
file: file.clone(),
})?
.as_bytes(),
)
.await
- .context(crate::error::SaveDbAsync { file })?;
+ .map_err(|source| Error::SaveDbAsync { source, file })?;
Ok(())
}
@@ -258,7 +283,7 @@ impl Db {
return Ok(());
}
}
- res.context(crate::error::RemoveDb { file })?;
+ res.map_err(|source| Error::RemoveDb { source, file })?;
Ok(())
}
diff --git a/src/dirs.rs b/src/dirs.rs
index cde00e3..285a0d5 100644
--- a/src/dirs.rs
+++ b/src/dirs.rs
@@ -3,24 +3,36 @@ use std::os::unix::fs::PermissionsExt as _;
pub fn make_all() -> Result<()> {
let cache_dir = cache_dir();
- std::fs::create_dir_all(&cache_dir)
- .context(crate::error::CreateDirectory { file: cache_dir })?;
+ std::fs::create_dir_all(&cache_dir).map_err(|source| {
+ Error::CreateDirectory {
+ source,
+ file: cache_dir,
+ }
+ })?;
let runtime_dir = runtime_dir();
- std::fs::create_dir_all(&runtime_dir).context(
- crate::error::CreateDirectory {
+ std::fs::create_dir_all(&runtime_dir).map_err(|source| {
+ Error::CreateDirectory {
+ source,
file: runtime_dir.clone(),
- },
- )?;
+ }
+ })?;
std::fs::set_permissions(
&runtime_dir,
std::fs::Permissions::from_mode(0o700),
)
- .context(crate::error::CreateDirectory { file: runtime_dir })?;
+ .map_err(|source| Error::CreateDirectory {
+ source,
+ file: runtime_dir,
+ })?;
let data_dir = data_dir();
- std::fs::create_dir_all(&data_dir)
- .context(crate::error::CreateDirectory { file: data_dir })?;
+ std::fs::create_dir_all(&data_dir).map_err(|source| {
+ Error::CreateDirectory {
+ source,
+ file: data_dir,
+ }
+ })?;
Ok(())
}
diff --git a/src/error.rs b/src/error.rs
index cd85c02..3576aa1 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,186 +1,183 @@
-#[derive(Debug, snafu::Snafu)]
-#[snafu(visibility = "pub")]
+#[derive(thiserror::Error, Debug)]
pub enum Error {
- #[snafu(display("email address not set"))]
+ #[error("email address not set")]
ConfigMissingEmail,
- #[snafu(display("failed to create block mode decryptor"))]
+ #[error("failed to create block mode decryptor")]
CreateBlockMode {
source: block_modes::InvalidKeyIvLength,
},
- #[snafu(display("failed to create directory at {}", file.display()))]
+ #[error("failed to create directory at {}", .file.display())]
CreateDirectory {
source: std::io::Error,
file: std::path::PathBuf,
},
- #[snafu(display("failed to decrypt"))]
+ #[error("failed to decrypt")]
Decrypt { source: block_modes::BlockModeError },
- #[snafu(display("failed to parse pinentry output ({:?})", out))]
+ #[error("failed to parse pinentry output ({out:?})")]
FailedToParsePinentry { out: String },
- #[snafu(display(
- "failed to run editor {}: {:?}",
- editor.to_string_lossy(),
- res
- ))]
+ #[error(
+ "failed to run editor {}: {res:?}",
+ .editor.to_string_lossy(),
+ )]
FailedToRunEditor {
editor: std::path::PathBuf,
res: std::process::ExitStatus,
},
- #[snafu(display("failed to expand with hkdf"))]
+ #[error("failed to expand with hkdf")]
HkdfExpand,
- #[snafu(display("{}", message))]
+ #[error("{message}")]
IncorrectPassword { message: String },
- #[snafu(display("invalid base64"))]
+ #[error("invalid base64")]
InvalidBase64 { source: base64::DecodeError },
- #[snafu(display("invalid cipherstring: {}", reason))]
+ #[error("invalid cipherstring: {reason}")]
InvalidCipherString { reason: String },
- #[snafu(display(
- "invalid value for ${}: {}",
- var,
- editor.to_string_lossy()
- ))]
+ #[error(
+ "invalid value for ${var}: {}",
+ .editor.to_string_lossy()
+ )]
InvalidEditor {
var: String,
editor: std::ffi::OsString,
},
- #[snafu(display("invalid mac"))]
+ #[error("invalid mac")]
InvalidMac,
- #[snafu(display("invalid two factor provider type: {}", ty))]
+ #[error("invalid two factor provider type: {ty}")]
InvalidTwoFactorProvider { ty: String },
- #[snafu(display("failed to parse JSON"))]
+ #[error("failed to parse JSON")]
JSON {
source: serde_path_to_error::Error<serde_json::Error>,
},
- #[snafu(display("failed to load config from {}", file.display()))]
+ #[error("failed to load config from {}", .file.display())]
LoadConfig {
source: std::io::Error,
file: std::path::PathBuf,
},
- #[snafu(display("failed to load config from {}", file.display()))]
+ #[error("failed to load config from {}", .file.display())]
LoadConfigAsync {
source: tokio::io::Error,
file: std::path::PathBuf,
},
- #[snafu(display("failed to load config from {}", file.display()))]
+ #[error("failed to load config from {}", .file.display())]
LoadConfigJson {
source: serde_json::Error,
file: std::path::PathBuf,
},
- #[snafu(display("failed to load db from {}", file.display()))]
+ #[error("failed to load db from {}", .file.display())]
LoadDb {
source: std::io::Error,
file: std::path::PathBuf,
},
- #[snafu(display("failed to load db from {}", file.display()))]
+ #[error("failed to load db from {}", .file.display())]
LoadDbAsync {
source: tokio::io::Error,
file: std::path::PathBuf,
},
- #[snafu(display("failed to load db from {}", file.display()))]
+ #[error("failed to load db from {}", .file.display())]
LoadDbJson {
source: serde_json::Error,
file: std::path::PathBuf,
},
- #[snafu(display("openssl error"))]
+ #[error("openssl error")]
OpenSSL { source: openssl::error::ErrorStack },
- #[snafu(display("failed to parse match type {}", s))]
+ #[error("failed to parse match type {s}")]
ParseMatchType { s: String },
- #[snafu(display("pbkdf2 requires at least 1 iteration (got 0)"))]
+ #[error("pbkdf2 requires at least 1 iteration (got 0)")]
Pbkdf2ZeroIterations,
- #[snafu(display("pinentry cancelled"))]
+ #[error("pinentry cancelled")]
PinentryCancelled,
- #[snafu(display("pinentry error: {}", error))]
+ #[error("pinentry error: {error}")]
PinentryErrorMessage { error: String },
- #[snafu(display("error reading pinentry output"))]
+ #[error("error reading pinentry output")]
PinentryReadOutput { source: tokio::io::Error },
- #[snafu(display("error waiting for pinentry to exit"))]
+ #[error("error waiting for pinentry to exit")]
PinentryWait { source: tokio::io::Error },
- #[snafu(display("failed to remove db at {}", file.display()))]
+ #[error("failed to remove db at {}", .file.display())]
RemoveDb {
source: std::io::Error,
file: std::path::PathBuf,
},
- #[snafu(display("api request returned error: {}", status))]
+ #[error("api request returned error: {status}")]
RequestFailed { status: u16 },
- #[snafu(display("api request unauthorized"))]
+ #[error("api request unauthorized")]
RequestUnauthorized,
- #[snafu(display("error making api request"))]
+ #[error("error making api request")]
Reqwest { source: reqwest::Error },
- #[snafu(display("failed to save config to {}", file.display()))]
+ #[error("failed to save config to {}", .file.display())]
SaveConfig {
source: std::io::Error,
file: std::path::PathBuf,
},
- #[snafu(display("failed to save config to {}", file.display()))]
+ #[error("failed to save config to {}", .file.display())]
SaveConfigJson {
source: serde_json::Error,
file: std::path::PathBuf,
},
- #[snafu(display("failed to save db to {}", file.display()))]
+ #[error("failed to save db to {}", .file.display())]
SaveDb {
source: std::io::Error,
file: std::path::PathBuf,
},
- #[snafu(display("failed to save db to {}", file.display()))]
+ #[error("failed to save db to {}", .file.display())]
SaveDbAsync {
source: tokio::io::Error,
file: std::path::PathBuf,
},
- #[snafu(display("failed to save db to {}", file.display()))]
+ #[error("failed to save db to {}", .file.display())]
SaveDbJson {
source: serde_json::Error,
file: std::path::PathBuf,
},
- #[snafu(display("error spawning pinentry"))]
+ #[error("error spawning pinentry")]
Spawn { source: tokio::io::Error },
- #[snafu(display("cipherstring type {} too old\n\nPlease rotate your account encryption key (https://bitwarden.com/help/article/account-encryption-key/) and try again.", ty))]
+ #[error("cipherstring type {ty} too old\n\nPlease rotate your account encryption key (https://bitwarden.com/help/article/account-encryption-key/) and try again.")]
TooOldCipherStringType { ty: String },
- #[snafu(display("two factor required"))]
+ #[error("two factor required")]
TwoFactorRequired {
providers: Vec<crate::api::TwoFactorProviderType>,
},
- #[snafu(display("unimplemented cipherstring type: {}", ty))]
+ #[error("unimplemented cipherstring type: {ty}")]
UnimplementedCipherStringType { ty: String },
- #[snafu(display("error writing to pinentry stdin"))]
+ #[error("error writing to pinentry stdin")]
WriteStdin { source: tokio::io::Error },
}
diff --git a/src/identity.rs b/src/identity.rs
index 8415765..602940f 100644
--- a/src/identity.rs
+++ b/src/identity.rs
@@ -13,7 +13,7 @@ impl Identity {
iterations: u32,
) -> Result<Self> {
let iterations = std::num::NonZeroU32::new(iterations)
- .context(crate::error::Pbkdf2ZeroIterations)?;
+ .ok_or(Error::Pbkdf2ZeroIterations)?;
let mut keys = crate::locked::Vec::new();
keys.extend(std::iter::repeat(0).take(64));
diff --git a/src/json.rs b/src/json.rs
index 2816a1f..d6c5328 100644
--- a/src/json.rs
+++ b/src/json.rs
@@ -7,15 +7,18 @@ pub trait DeserializeJsonWithPath {
impl DeserializeJsonWithPath for String {
fn json_with_path<T: serde::de::DeserializeOwned>(self) -> Result<T> {
let jd = &mut serde_json::Deserializer::from_str(&self);
- serde_path_to_error::deserialize(jd).context(crate::error::JSON)
+ serde_path_to_error::deserialize(jd)
+ .map_err(|source| Error::JSON { source })
}
}
impl DeserializeJsonWithPath for reqwest::blocking::Response {
fn json_with_path<T: serde::de::DeserializeOwned>(self) -> Result<T> {
- let bytes = self.bytes().context(crate::error::Reqwest)?;
+ let bytes =
+ self.bytes().map_err(|source| Error::Reqwest { source })?;
let jd = &mut serde_json::Deserializer::from_slice(&bytes);
- serde_path_to_error::deserialize(jd).context(crate::error::JSON)
+ serde_path_to_error::deserialize(jd)
+ .map_err(|source| Error::JSON { source })
}
}
@@ -31,8 +34,12 @@ impl DeserializeJsonWithPathAsync for reqwest::Response {
async fn json_with_path<T: serde::de::DeserializeOwned>(
self,
) -> Result<T> {
- let bytes = self.bytes().await.context(crate::error::Reqwest)?;
+ let bytes = self
+ .bytes()
+ .await
+ .map_err(|source| Error::Reqwest { source })?;
let jd = &mut serde_json::Deserializer::from_slice(&bytes);
- serde_path_to_error::deserialize(jd).context(crate::error::JSON)
+ serde_path_to_error::deserialize(jd)
+ .map_err(|source| Error::JSON { source })
}
}
diff --git a/src/pinentry.rs b/src/pinentry.rs
index 683a880..b055b77 100644
--- a/src/pinentry.rs
+++ b/src/pinentry.rs
@@ -17,7 +17,7 @@ pub async fn getpin(
} else {
opts.args(&["-o", "0"]);
}
- let mut child = opts.spawn().context(crate::error::Spawn)?;
+ let mut child = opts.spawn().map_err(|source| Error::Spawn { source })?;
// unwrap is safe because we specified stdin as piped in the command opts
// above
let mut stdin = child.stdin.take().unwrap();
@@ -26,29 +26,29 @@ pub async fn getpin(
stdin
.write_all(b"SETTITLE rbw\n")
.await
- .context(crate::error::WriteStdin)?;
+ .map_err(|source| Error::WriteStdin { source })?;
ncommands += 1;
stdin
.write_all(format!("SETPROMPT {}\n", prompt).as_bytes())
.await
- .context(crate::error::WriteStdin)?;
+ .map_err(|source| Error::WriteStdin { source })?;
ncommands += 1;
stdin
.write_all(format!("SETDESC {}\n", desc).as_bytes())
.await
- .context(crate::error::WriteStdin)?;
+ .map_err(|source| Error::WriteStdin { source })?;
ncommands += 1;
if let Some(err) = err {
stdin
.write_all(format!("SETERROR {}\n", err).as_bytes())
.await
- .context(crate::error::WriteStdin)?;
+ .map_err(|source| Error::WriteStdin { source })?;
ncommands += 1;
}
stdin
.write_all(b"GETPIN\n")
.await
- .context(crate::error::WriteStdin)?;
+ .map_err(|source| Error::WriteStdin { source })?;
ncommands += 1;
drop(stdin);
@@ -64,7 +64,10 @@ pub async fn getpin(
.await?;
buf.truncate(len);
- child.wait().await.context(crate::error::PinentryWait)?;
+ child
+ .wait()
+ .await
+ .map_err(|source| Error::PinentryWait { source })?;
Ok(crate::locked::Password::new(buf))
}
@@ -130,7 +133,7 @@ where
let bytes = r
.read(&mut data[len..])
.await
- .context(crate::error::PinentryReadOutput)?;
+ .map_err(|source| Error::PinentryReadOutput { source })?;
len += bytes;
}
}
diff --git a/src/prelude.rs b/src/prelude.rs
index af8bbd7..af4fb59 100644
--- a/src/prelude.rs
+++ b/src/prelude.rs
@@ -1,2 +1 @@
pub use crate::error::{Error, Result};
-pub use snafu::{OptionExt as _, ResultExt as _};