#![forbid(unsafe_code)]
#![deny(missing_debug_implementations)]
#![warn(rust_2018_idioms)]
#![warn(clippy::cargo, clippy::nursery, clippy::pedantic)]
#![allow(clippy::multiple_crate_versions)]
mod cli;
mod core;
mod input;
mod output;
mod params;
mod password;
mod utils;
use std::{
io,
process::{self, Termination},
};
use scryptenc::Error as ScryptencError;
#[derive(Debug)]
enum ExitCode {
Success,
Failure,
InvalidFormat,
UnknownVersion,
LackOfMemory,
LackOfCpuTime,
InvalidPassword,
InvalidParams,
LackOfResources,
Other(sysexits::ExitCode),
}
impl From<sysexits::ExitCode> for ExitCode {
fn from(code: sysexits::ExitCode) -> Self {
Self::Other(code)
}
}
impl Termination for ExitCode {
fn report(self) -> process::ExitCode {
match self {
Self::Success => process::ExitCode::SUCCESS,
Self::Failure => process::ExitCode::FAILURE,
Self::InvalidFormat => process::ExitCode::from(7),
Self::UnknownVersion => process::ExitCode::from(8),
Self::LackOfMemory => process::ExitCode::from(9),
Self::LackOfCpuTime => process::ExitCode::from(10),
Self::InvalidPassword => process::ExitCode::from(11),
Self::InvalidParams => process::ExitCode::from(14),
Self::LackOfResources => process::ExitCode::from(15),
Self::Other(code) => process::ExitCode::from(code),
}
}
}
fn main() -> ExitCode {
match core::run() {
Ok(()) => ExitCode::Success,
Err(err) => {
eprintln!("Error: {err:?}");
#[allow(clippy::option_if_let_else)]
if let Some(e) = err.downcast_ref::<io::Error>() {
sysexits::ExitCode::try_from(e.kind()).map_or(ExitCode::Failure, ExitCode::from)
} else if let Some(e) = err.downcast_ref::<ScryptencError>() {
match e {
ScryptencError::InvalidLength
| ScryptencError::InvalidMagicNumber
| ScryptencError::InvalidChecksum => ExitCode::InvalidFormat,
ScryptencError::UnknownVersion(_) => ExitCode::UnknownVersion,
ScryptencError::InvalidParams(_) => ExitCode::InvalidParams,
ScryptencError::InvalidSignature(_) => ExitCode::InvalidPassword,
}
} else if let Some(e) = err.downcast_ref::<params::Error>() {
match e {
params::Error::Memory => ExitCode::LackOfMemory,
params::Error::CpuTime => ExitCode::LackOfCpuTime,
params::Error::Resources => ExitCode::LackOfResources,
}
} else {
ExitCode::Failure
}
}
}
}