From 204f511075fd2f538ef0d44decf8406df0f5b5a6 Mon Sep 17 00:00:00 2001 From: Avril Date: Wed, 3 Mar 2021 16:59:49 +0000 Subject: [PATCH] allow multiple inputs to -s and -u --- shuffle3rs/Cargo.lock | 7 ++++ shuffle3rs/Cargo.toml | 3 +- shuffle3rs/src/arg.rs | 84 ++++++++++++++++++++++++++++++++++++++++++ shuffle3rs/src/ext.rs | 2 + shuffle3rs/src/main.rs | 17 ++++++++- 5 files changed, 111 insertions(+), 2 deletions(-) diff --git a/shuffle3rs/Cargo.lock b/shuffle3rs/Cargo.lock index ff05771..05206a0 100644 --- a/shuffle3rs/Cargo.lock +++ b/shuffle3rs/Cargo.lock @@ -85,8 +85,15 @@ dependencies = [ "lazy_static", "rand", "rand_chacha", + "smallvec", ] +[[package]] +name = "smallvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/shuffle3rs/Cargo.toml b/shuffle3rs/Cargo.toml index 42101a2..749db1d 100644 --- a/shuffle3rs/Cargo.toml +++ b/shuffle3rs/Cargo.toml @@ -27,6 +27,7 @@ deferred-drop = [] cfg-if = "1.0.0" lazy_static = "1.4.0" rand = "0.8.3" +smallvec = "1.6.1" [dev-dependencies] -rand_chacha = "0.3.0" \ No newline at end of file +rand_chacha = "0.3.0" diff --git a/shuffle3rs/src/arg.rs b/shuffle3rs/src/arg.rs index 82dd328..0d5f5c7 100644 --- a/shuffle3rs/src/arg.rs +++ b/shuffle3rs/src/arg.rs @@ -1,4 +1,7 @@ +use super::*; +use std::{fmt, error}; +use std::path::PathBuf; /// The executable program name pub fn program_name() -> &'static str @@ -36,3 +39,84 @@ pub fn usage() std::process::exit(2) } + +pub enum Mode +{ + Help, + ShuffleInPlace(MaybeVec), + UnshuffleInPlace(MaybeVec), +} + +/// Parse the `argv` of this process. +#[inline] pub fn parse_args() -> Result +{ + parse(std::env::args().skip(1)) +} + +fn parse>(args: I) -> Result +{ + #[inline] fn validate_file(p: impl Into) -> Result + { + let p = p.into(); + if p.is_file() + { + Ok(p) + } else { + Err(Error::FileNotFound(p)) + } + } + + let mut args = args.into_iter(); + + let farg = args.next(); + match farg + { + Some(yes) => { + match yes.trim() + { + "-h" => Ok(Mode::Help), + "-s" => { + Ok(Mode::ShuffleInPlace( + args + .map(|file| validate_file(file)).collect::, Error>>() + .and_then(|v| if v.len() == 0 { Err(Error::InvalidUseArg("-s"))} else {Ok(v)})?)) + }, + "-u" => { + Ok(Mode::UnshuffleInPlace( + args + .map(|file| validate_file(file)).collect::, Error>>() + .and_then(|v| if v.len() == 0 { Err(Error::InvalidUseArg("-u"))} else {Ok(v)})?)) + + }, + _ => Err(Error::UnknownOpt(yes)) + } + } + None => Err(Error::NoOpt), + } +} + +/// Arg parsing error +#[derive(Debug)] +#[non_exhaustive] +pub enum Error +{ + InvalidUseArg(&'static str), + NoOpt, + + UnknownOpt(String), + FileNotFound(PathBuf), +} + +impl error::Error for Error{} +impl fmt::Display for Error +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + { + match self { + Self::NoOpt => write!(f, "No options specified"), + Self::UnknownOpt(opt) => write!(f, "Unknown option {:?}", opt), + Self::FileNotFound(file) => write!(f, "File {:?} not found", file), + Self::InvalidUseArg(string) => write!(f, "Argument {:?} expects a parameter", string), + } + } +} diff --git a/shuffle3rs/src/ext.rs b/shuffle3rs/src/ext.rs index 43204db..5a2031f 100644 --- a/shuffle3rs/src/ext.rs +++ b/shuffle3rs/src/ext.rs @@ -4,6 +4,8 @@ use std::iter::{FusedIterator, DoubleEndedIterator}; use rand::Rng; use crate::shuffle; +pub type MaybeVec = smallvec::SmallVec<[T; 1]>; + pub trait SliceElementExt { fn random_element(&self, rng: &mut R) -> &T; diff --git a/shuffle3rs/src/main.rs b/shuffle3rs/src/main.rs index 6fba483..0c5da7c 100644 --- a/shuffle3rs/src/main.rs +++ b/shuffle3rs/src/main.rs @@ -10,9 +10,24 @@ mod shuffle; mod arg; +use arg::Mode; fn main() { - arg::help(); + match arg::parse_args() + { + Ok(Mode::Help) => arg::usage(), + Ok(Mode::ShuffleInPlace(file)) => { + todo!() + }, + Ok(Mode::UnshuffleInPlace(file)) => { + todo!() + }, + Err(err) => { + eprintln!("Error: {}", err); + eprintln!("\nTry passing `-h`"); + std::process::exit(1) + } + } } #[cfg(test)] mod test;