parent
192a7a6ed6
commit
dca0c79c4a
@ -0,0 +1,96 @@
|
||||
//! Parsing args
|
||||
use super::*;
|
||||
use ext::*;
|
||||
use std::iter;
|
||||
|
||||
/// Arg state
|
||||
#[derive(Debug, Default)]
|
||||
struct State
|
||||
{
|
||||
is_server: bool,
|
||||
is_sending: bool,
|
||||
|
||||
enc: Option<bool>,
|
||||
comp: Option<bool>,
|
||||
bufsz: Option<usize>,
|
||||
arc: Option<bool>,
|
||||
contin: Option<bool>,
|
||||
oneshot: Option<bool>,
|
||||
|
||||
inter: Option<bool>,
|
||||
|
||||
files: Vec<String>,
|
||||
}
|
||||
|
||||
impl State
|
||||
{
|
||||
fn mode(&self) -> impl fmt::Display + 'static
|
||||
{
|
||||
let send = r#if!(self.is_sending, "send", "recv");
|
||||
let serve = r#if!(self.is_server, "server", "client");
|
||||
lazy_format!("{} ({})", send, serve)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_schain<I>(state: &mut State, single: I) -> eyre::Result<()>
|
||||
where I: IntoIterator<Item=char>
|
||||
{
|
||||
for ch in single.into_iter().map(char::to_lowercase).flatten()
|
||||
{
|
||||
match ch {
|
||||
'e' => state.enc = Some(true),
|
||||
'c' => state.comp = Some(true),
|
||||
'a' => state.arc = Some(true),
|
||||
'k' => state.contin = Some(true),
|
||||
'1' if state.is_server => state.oneshot = Some(true),
|
||||
'i' if !state.is_sending => state.inter = Some(true),
|
||||
x => return Err(eyre!("Unknown option for mode {}", state.mode()))
|
||||
.with_section(move || x.header("Option was"))
|
||||
.with_note(move || "Some options are only valid for certain modes"),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Try to parse an iterator of strings (usually the command-line arguments) into an `Op`.
|
||||
pub fn parse_iter<I>(args: &mut I) -> eyre::Result<Op>
|
||||
where I: Iterator<Item= String> + ?Sized
|
||||
{
|
||||
let state = parse_iter_raw(args)
|
||||
.wrap_err(eyre!("Invalid arguments"))
|
||||
.with_suggestion(|| "Try passing `--help`")?; // Send help message here, since it's unlikely to be helpful when returning from state's validation compared to here.
|
||||
|
||||
todo!("TODO: `impl TryFrom<State> for Op`, etc")
|
||||
}
|
||||
fn parse_iter_raw<I>(args: &mut I) -> eyre::Result<State>
|
||||
where I: Iterator<Item= String> + ?Sized
|
||||
{
|
||||
let mut state = State::default();
|
||||
//TODO: Parse modes before this.
|
||||
while let Some(arg) = args.next()
|
||||
{
|
||||
let mut chars = arg.chars();
|
||||
match (&mut chars).take(2).collect_array::<2>() {
|
||||
['-', '-'] => {
|
||||
// Long option
|
||||
let opt = &arg[2..];
|
||||
match opt {
|
||||
"--" => break,
|
||||
//TODO: Long options, pulling option param from `args` if needed, etc.
|
||||
unknown => return Err(eyre!("Unknown option for mode {}", state.mode()))
|
||||
.with_section(|| format!("--{}", unknown).header("Option was"))
|
||||
.with_note(|| "Some options are only valid for certain modes"),
|
||||
}
|
||||
},
|
||||
['-', n] => {
|
||||
// Small option
|
||||
parse_schain(&mut state, iter::once(n).chain(chars))?;
|
||||
},
|
||||
_ => {
|
||||
// Not an option
|
||||
state.files.push(arg);
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(state)
|
||||
}
|
Loading…
Reference in new issue