You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
5.3 KiB
260 lines
5.3 KiB
//! Arg parsing
|
|
#![allow(unused_macros)]
|
|
use super::*;
|
|
use tokio::{
|
|
sync::{
|
|
mpsc,
|
|
},
|
|
};
|
|
use std::{
|
|
iter,
|
|
};
|
|
use eyre::eyre;
|
|
use config::op::{self, Password};
|
|
use error::ParseErrorKind;
|
|
|
|
mod normal;
|
|
mod generate;
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
|
enum IsSigning
|
|
{
|
|
No,
|
|
Yes,
|
|
Only,
|
|
}
|
|
|
|
impl Default for IsSigning
|
|
{
|
|
#[inline]
|
|
fn default() -> Self
|
|
{
|
|
Self::No
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
|
enum KeyKind
|
|
{
|
|
Autodetect(IsSigning),
|
|
RsaPublic(IsSigning),
|
|
RsaPrivate(IsSigning), // is signing key?
|
|
Aes,
|
|
}
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
|
enum TranslationMode {
|
|
Autodetect,
|
|
Encrypt,
|
|
Decrypt,
|
|
}
|
|
|
|
impl Default for TranslationMode
|
|
{
|
|
#[inline]
|
|
fn default() -> Self
|
|
{
|
|
Self::Autodetect
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
|
enum KeyFormat
|
|
{
|
|
Bin,
|
|
Text,
|
|
PEM,
|
|
}
|
|
|
|
impl Default for KeyFormat
|
|
{
|
|
#[inline]
|
|
fn default() -> Self
|
|
{
|
|
Self::Bin
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
|
enum GenerateKeyKind
|
|
{
|
|
Rsa,
|
|
Aes,
|
|
}
|
|
|
|
impl GenerateKeyKind
|
|
{
|
|
#[inline(always)]
|
|
pub fn is_rsa(&self) -> bool
|
|
{
|
|
if let Self::Rsa = self {
|
|
true
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
|
enum GenerateAtom
|
|
{
|
|
Type(GenerateKeyKind),
|
|
Input(String),
|
|
InputPassword(Password),
|
|
Password(Password),
|
|
Format(KeyFormat),
|
|
Output(String),
|
|
PublicOutput(String),
|
|
}
|
|
|
|
impl GenerateAtom
|
|
{
|
|
pub fn hash_into(&self, map: &mut smallmap::Map<u64, ()>) -> bool
|
|
{
|
|
use std::hash::{Hash,Hasher,};
|
|
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
|
self.hash(&mut hasher);
|
|
let vl = hasher.finish();
|
|
if map.contains_key(&vl) {
|
|
true
|
|
} else {
|
|
map.insert(hasher.finish(),());
|
|
false
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
|
enum Atom
|
|
{
|
|
Key(KeyKind, String, Password),
|
|
NonSpecific,
|
|
FileAuto(String),
|
|
FileSpecific(String, String, TranslationMode),
|
|
SetMode(config::op::Mode),
|
|
|
|
Generate(GenerateAtom),
|
|
}
|
|
|
|
impl Atom
|
|
{
|
|
pub fn hash_into(&self, map: &mut smallmap::Map<u64, ()>) -> bool
|
|
{
|
|
use std::hash::{Hash,Hasher,};
|
|
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
|
self.hash(&mut hasher);
|
|
let vl = hasher.finish();
|
|
if map.contains_key(&vl) {
|
|
true
|
|
} else {
|
|
map.insert(hasher.finish(),());
|
|
false
|
|
}
|
|
}
|
|
}
|
|
|
|
#[instrument(level="debug", err, skip(args))]
|
|
pub async fn parse<I: IntoIterator<Item=String> + std::fmt::Debug>(args: I) -> Result<config::Operation, eyre::Report>
|
|
{
|
|
let (tx, rx) = mpsc::channel(1);
|
|
|
|
macro_rules! unwrap_handler {
|
|
($handler:expr) => ($handler.await
|
|
.wrap_err_with(|| eyre!("Atom parser panicked")
|
|
.with_warning(|| "This usually indicates a bug in the program, not invalid input.")));
|
|
}
|
|
|
|
let mut args = args.into_iter();
|
|
let handler = if let Some(arg) = args.next()
|
|
{
|
|
match arg.to_lowercase().trim() {
|
|
"--generate" => {
|
|
let handler = tokio::spawn(generate::handle(rx));
|
|
match generate::parse(args.map(Into::into), tx).await
|
|
{
|
|
// The `handler` has dropped `rx` and returned an error, let unwrap_handler down there handle this.
|
|
Err(error::Error::AtomInternal) => Ok(()),
|
|
other => other,
|
|
}
|
|
.with_note(|| "In parsing of generate operation spec")?;
|
|
|
|
handler
|
|
},
|
|
"--help" => return Ok(config::Operation::Help),
|
|
"--stat" => todo!(),
|
|
_ => {
|
|
let handler = tokio::spawn(normal::handle(rx));
|
|
match normal::parse(std::iter::once(arg)
|
|
.chain(args.map(Into::into)), tx).await
|
|
{
|
|
// The `handler` has dropped `rx` and returned an error, let unwrap_handler down there handle this.
|
|
Err(error::Error::AtomInternal) => Ok(()),
|
|
other => other,
|
|
}
|
|
.with_note(|| "In parsing of normal operation spec")?;
|
|
|
|
handler
|
|
},
|
|
}
|
|
} else {
|
|
return Err(eyre!("No arguments specified"));
|
|
};
|
|
|
|
match unwrap_handler!(handler)? {
|
|
Err(d @ error::ConstructError::Dropped) => {
|
|
unreachable!("{}", d);
|
|
},
|
|
Err(error) => {
|
|
return Err(error)
|
|
.wrap_err_with(|| eyre!("Failed to construct operation from arguments"))
|
|
.with_note(|| "In constructing of operation from spec");
|
|
},
|
|
Ok(operation) => {
|
|
//TODO: Validate operation here?
|
|
Ok(operation)
|
|
},
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
#[instrument]
|
|
pub fn parse<T: Into<String>, I: IntoIterator<Item = T> + std::fmt::Debug>(args: I) -> Result<Spec, eyre::Report>
|
|
{
|
|
let mut args = args.into_iter();
|
|
if let Some(arg) = args.next()
|
|
{
|
|
let arg =arg.into();
|
|
match arg.to_lowercase().trim() {
|
|
"--generate" => Ok(Spec::Concrete(config::Operation::GenerateKey(parse_keygen(args.map(Into::into))
|
|
.with_note(|| "Mode was `--generate`")?))),
|
|
"--help" => Ok(Spec::Concrete(config::Operation::Help)),
|
|
"--stat" => Ok(Spec::Concrete(config::Operation::KeyInfo(parse_stat(args.map(Into::into))
|
|
.with_note(|| "Mode was `--stat")?))),
|
|
_ => Ok(parse_normal(std::iter::once(arg)
|
|
.chain(args.map(Into::into)))
|
|
.with_note(|| "Mode was crypt")?.into()),
|
|
}
|
|
} else {
|
|
Err(eyre!("No arguments specified"))
|
|
}
|
|
}
|
|
|
|
fn parse_normal<I: IntoIterator<Item = String>>(args: I) -> Result<OperationSpec, eyre::Report>
|
|
{
|
|
todo!()
|
|
}
|
|
|
|
|
|
fn parse_keygen<I: IntoIterator<Item = String>>(args: I) -> Result<config::op::GenerateKey, eyre::Report>
|
|
{
|
|
todo!()
|
|
}
|
|
|
|
|
|
fn parse_stat<I: IntoIterator<Item = String>>(args: I) -> Result<Vec<(String, config::op::Password)>, eyre::Report>
|
|
{
|
|
todo!()
|
|
}
|
|
*/
|