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