Selaa lähdekoodia

Throw error immediately on lookup

Every time looking up an argument fails, it returns an error. We might as well just move this into the lookup function.
Benjamin Sago 8 vuotta sitten
vanhempi
sitoutus
9bbe2d9816
1 muutettua tiedostoa jossa 40 lisäystä ja 51 poistoa
  1. 40 51
      src/options/parser.rs

+ 40 - 51
src/options/parser.rs

@@ -36,12 +36,18 @@ pub struct Arg {
 pub struct Args(&'static [Arg]);
 pub struct Args(&'static [Arg]);
 
 
 impl Args {
 impl Args {
-    fn lookup_short(&self, short: ShortArg) -> Option<&Arg> {
-        self.0.into_iter().find(|arg| arg.short == Some(short))
+    fn lookup_short<'a>(&self, short: ShortArg) -> Result<&Arg, ParseError<'a>> {
+        match self.0.into_iter().find(|arg| arg.short == Some(short)) {
+            Some(arg)  => Ok(arg),
+            None       => Err(ParseError::UnknownShortArgument { attempt: short })
+        }
     }
     }
 
 
-    fn lookup_long(&self, long: &OsStr) -> Option<&Arg> {
-        self.0.into_iter().find(|arg| arg.long == long)
+    fn lookup_long<'a>(&self, long: &'a OsStr) -> Result<&Arg, ParseError<'a>> {
+        match self.0.into_iter().find(|arg| arg.long == long) {
+            Some(arg)  => Ok(arg),
+            None       => Err(ParseError::UnknownArgument { attempt: long })
+        }
     }
     }
 }
 }
 
 
@@ -89,73 +95,57 @@ fn parse<'a>(args: Args, inputs: &'a [OsString]) -> Result<Matches<'a>, ParseErr
             let long_arg = OsStr::from_bytes(&bytes[2..]);
             let long_arg = OsStr::from_bytes(&bytes[2..]);
 
 
             if let Some((before, after)) = split_on_equals(long_arg) {
             if let Some((before, after)) = split_on_equals(long_arg) {
-                if let Some(&Arg { short: _, long: long_arg_name, takes_value }) = args.lookup_long(before) {
-                    let flag = Flag::Long(long_arg_name);
-                    match takes_value {
-                        Necessary  => results.flags.push((flag, Some(after))),
-                        Forbidden  => return Err(ParseError::ForbiddenValue { flag })
-                    }
-                }
-                else {
-                    return Err(ParseError::UnknownArgument { attempt: before })
+                let &Arg { short: _, long: long_arg_name, takes_value } = args.lookup_long(before)?;
+                let flag = Flag::Long(long_arg_name);
+                match takes_value {
+                    Necessary  => results.flags.push((flag, Some(after))),
+                    Forbidden  => return Err(ParseError::ForbiddenValue { flag })
                 }
                 }
             }
             }
             else {
             else {
-                if let Some(&Arg { short: _, long: long_arg_name, takes_value }) = args.lookup_long(long_arg) {
-                    let flag = Flag::Long(long_arg_name);
-                    match takes_value {
-                        Forbidden  => results.flags.push((flag, None)),
-                        Necessary  => {
-                            if let Some(next_arg) = iter.next() {
-                                results.flags.push((flag, Some(next_arg)));
-                            }
-                            else {
-                                return Err(ParseError::NeedsValue { flag })
-                            }
+                let &Arg { short: _, long: long_arg_name, takes_value } = args.lookup_long(long_arg)?;
+                let flag = Flag::Long(long_arg_name);
+                match takes_value {
+                    Forbidden  => results.flags.push((flag, None)),
+                    Necessary  => {
+                        if let Some(next_arg) = iter.next() {
+                            results.flags.push((flag, Some(next_arg)));
+                        }
+                        else {
+                            return Err(ParseError::NeedsValue { flag })
                         }
                         }
                     }
                     }
                 }
                 }
-                else {
-                    return Err(ParseError::UnknownArgument { attempt: long_arg })
-                }
             }
             }
         }
         }
         else if bytes.starts_with(b"-") && arg != "-" {
         else if bytes.starts_with(b"-") && arg != "-" {
             let short_arg = OsStr::from_bytes(&bytes[1..]);
             let short_arg = OsStr::from_bytes(&bytes[1..]);
             if let Some((before, after)) = split_on_equals(short_arg) {
             if let Some((before, after)) = split_on_equals(short_arg) {
                 // TODO: remember to deal with the other bytes!
                 // TODO: remember to deal with the other bytes!
-                if let Some(&Arg { short, long, takes_value }) = args.lookup_short(*before.as_bytes().last().unwrap()) {
-                    let flag = Flag::Short(short.unwrap());
-                    match takes_value {
-                        Necessary  => results.flags.push((flag, Some(after))),
-                        Forbidden  => return Err(ParseError::ForbiddenValue { flag })
-                    }
-                }
-                else {
-                    return Err(ParseError::UnknownArgument { attempt: before })
+                let &Arg { short, long, takes_value } = args.lookup_short(*before.as_bytes().last().unwrap())?;
+                let flag = Flag::Short(short.unwrap());
+                match takes_value {
+                    Necessary  => results.flags.push((flag, Some(after))),
+                    Forbidden  => return Err(ParseError::ForbiddenValue { flag })
                 }
                 }
             }
             }
             else {
             else {
                 for byte in &bytes[1..] {
                 for byte in &bytes[1..] {
                     // TODO: gotta check that these don't take arguments
                     // TODO: gotta check that these don't take arguments
                     // like -c4
                     // like -c4
-                    if let Some(&Arg { short, long, takes_value }) = args.lookup_short(*byte) {
-                        let flag = Flag::Short(*byte);
-                        match takes_value {
-                            Forbidden  => results.flags.push((flag, None)),
-                            Necessary  => {
-                                if let Some(next_arg) = iter.next() {
-                                    results.flags.push((flag, Some(next_arg)));
-                                }
-                                else {
-                                    return Err(ParseError::NeedsValue { flag })
-                                }
+                    let &Arg { short, long, takes_value } = args.lookup_short(*byte)?;
+                    let flag = Flag::Short(*byte);
+                    match takes_value {
+                        Forbidden  => results.flags.push((flag, None)),
+                        Necessary  => {
+                            if let Some(next_arg) = iter.next() {
+                                results.flags.push((flag, Some(next_arg)));
+                            }
+                            else {
+                                return Err(ParseError::NeedsValue { flag })
                             }
                             }
                         }
                         }
                     }
                     }
-                    else {
-                        return Err(ParseError::UnknownShortArgument { attempt: *byte });
-                    }
                 }
                 }
             }
             }
         }
         }
@@ -233,7 +223,6 @@ mod split_test {
 #[cfg(test)]
 #[cfg(test)]
 mod test {
 mod test {
     use super::*;
     use super::*;
-    use std::ffi::OsString;
 
 
     static TEST_ARGS: &'static [Arg] = &[
     static TEST_ARGS: &'static [Arg] = &[
         Arg { short: Some(b'l'), long: "long",  takes_value: TakesValue::Forbidden },
         Arg { short: Some(b'l'), long: "long",  takes_value: TakesValue::Forbidden },