diff options
| author | acdenisSK <[email protected]> | 2017-09-23 23:16:26 +0200 |
|---|---|---|
| committer | acdenisSK <[email protected]> | 2017-09-23 23:16:26 +0200 |
| commit | ab67c1dd60b5f49541815b2527e8a3cb7712e182 (patch) | |
| tree | b7d7f1d5c0342c80488972e4e0157dc964a9baea /src/framework/standard/args.rs | |
| parent | Downgrade sodiumoxide to v0.0.14 (diff) | |
| download | serenity-ab67c1dd60b5f49541815b2527e8a3cb7712e182.tar.xz serenity-ab67c1dd60b5f49541815b2527e8a3cb7712e182.zip | |
Revamp errors in `Args` and commands
Diffstat (limited to 'src/framework/standard/args.rs')
| -rw-r--r-- | src/framework/standard/args.rs | 112 |
1 files changed, 72 insertions, 40 deletions
diff --git a/src/framework/standard/args.rs b/src/framework/standard/args.rs index d22b1a8..d03076f 100644 --- a/src/framework/standard/args.rs +++ b/src/framework/standard/args.rs @@ -1,21 +1,59 @@ use vec_shift::Shift; use std::str::FromStr; use std::error::Error as StdError; +use std::fmt; use utils::parse_quotes; /// Defines how an operation on an `Args` method failed. #[derive(Debug)] -pub enum Error { +pub enum Error<E: StdError> { /// "END-OF-STRING", more precisely, there isn't anything to parse anymore. Eos, /// A parsing operation failed; the error in it can be of any returned from the `FromStr` /// trait. - Parse(Box<StdError>), + Parse(E), } -type Result<T> = ::std::result::Result<T, Error>; +impl<E: StdError> From<E> for Error<E> { + fn from(e: E) -> Self { + Error::Parse(e) + } +} + +impl<E: StdError> StdError for Error<E> { + fn description(&self) -> &str { + use self::Error::*; + + match *self { + Eos => "end-of-string", + Parse(ref e) => e.description(), + } + } + + fn cause(&self) -> Option<&StdError> { + use self::Error::*; + + match *self { + Parse(ref e) => Some(e), + _ => None, + } + } +} -#[derive(Debug, Clone)] +impl<E: StdError> fmt::Display for Error<E> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::Error::*; + + match *self { + Eos => write!(f, "end of string"), + Parse(ref e) => fmt::Display::fmt(&e, f), + } + } +} + +type Result<T, E> = ::std::result::Result<T, Error<E>>; + +#[derive(Clone, Debug)] pub struct Args { delimiter: String, delimiter_split: Vec<String>, @@ -36,33 +74,31 @@ impl Args { } /// Removes the first element, parses it to a specific type if necessary, returns. - pub fn single<T: FromStr>(&mut self) -> Result<T> - where T::Err: StdError + 'static { + pub fn single<T: FromStr>(&mut self) -> Result<T, T::Err> + where T::Err: StdError { if self.delimiter_split.is_empty() { return Err(Error::Eos); } - self.delimiter_split + Ok(self.delimiter_split .shift() .ok_or(Error::Eos)? - .parse::<T>() - .map_err(|e| Error::Parse(Box::new(e))) + .parse::<T>()?) } /// Like [`single`], but doesn't remove the element. /// /// [`single`]: #method.single - pub fn single_n<T: FromStr>(&self) -> Result<T> - where T::Err: StdError + 'static { + pub fn single_n<T: FromStr>(&self) -> Result<T, T::Err> + where T::Err: StdError { if self.delimiter_split.is_empty() { return Err(Error::Eos); } - self.delimiter_split + Ok(self.delimiter_split .get(0) .ok_or(Error::Eos)? - .parse::<T>() - .map_err(|e| Error::Parse(Box::new(e))) + .parse::<T>()?) } /// Skips if there's a first element, but also returns it. @@ -87,50 +123,48 @@ impl Args { /// Like [`single`], but takes quotes into account. /// /// [`single`]: #method.single - pub fn single_quoted<T: FromStr>(&mut self) -> Result<T> - where T::Err: StdError + 'static { - parse_quotes(&self.delimiter_split.shift().ok_or(Error::Eos)?) + pub fn single_quoted<T: FromStr>(&mut self) -> Result<T, T::Err> + where T::Err: StdError { + Ok(parse_quotes(&self.delimiter_split.shift().ok_or(Error::Eos)?) .remove(0) - .parse::<T>() - .map_err(|e| Error::Parse(Box::new(e))) + .parse::<T>()?) } /// Like [`single_quoted`], but doesn't remove the element. /// /// [`single_quoted`]: #method.single_quoted - pub fn single_quoted_n<T: FromStr>(&self) -> Result<T> - where T::Err: StdError + 'static { - parse_quotes(&self.delimiter_split.get(0).ok_or(Error::Eos)?) + pub fn single_quoted_n<T: FromStr>(&self) -> Result<T, T::Err> + where T::Err: StdError { + Ok(parse_quotes(&self.delimiter_split.get(0).ok_or(Error::Eos)?) .remove(0) - .parse::<T>() - .map_err(|e| Error::Parse(Box::new(e))) + .parse::<T>()?) } /// Like [`list`], but takes quotes into account. /// /// [`list`]: #method.list - pub fn multiple_quoted<T: FromStr>(self) -> Result<Vec<T>> - where T::Err: StdError + 'static { + pub fn multiple_quoted<T: FromStr>(self) -> Result<Vec<T>, T::Err> + where T::Err: StdError { if self.delimiter_split.is_empty() { return Err(Error::Eos); } parse_quotes(&self.delimiter_split.join(&self.delimiter)) .into_iter() - .map(|s| s.parse::<T>().map_err(|e| Error::Parse(Box::new(e)))) + .map(|s| s.parse::<T>().map_err(|e| Error::Parse(e))) .collect() } /// Empty outs the internal vector while parsing (if necessary) and returning them - pub fn list<T: FromStr>(self) -> Result<Vec<T>> - where T::Err: StdError + 'static { + pub fn list<T: FromStr>(self) -> Result<Vec<T>, T::Err> + where T::Err: StdError { if self.delimiter_split.is_empty() { return Err(Error::Eos); } self.delimiter_split .into_iter() - .map(|s| s.parse::<T>().map_err(|e| Error::Parse(Box::new(e)))) + .map(|s| s.parse::<T>().map_err(|e| Error::Parse(e))) .collect() } @@ -138,8 +172,8 @@ impl Args { pub fn full(&self) -> String { self.delimiter_split.join(&self.delimiter) } /// Returns the first argument that can be converted and removes it from the list. - pub fn find<T: FromStr>(&mut self) -> Result<T> - where T::Err: StdError + 'static { + pub fn find<T: FromStr>(&mut self) -> Result<T, T::Err> + where T::Err: StdError { if self.delimiter_split.is_empty() { return Err(Error::Eos); } @@ -152,30 +186,28 @@ impl Args { let value = self.delimiter_split .get(index) .ok_or(Error::Eos)? - .parse::<T>() - .map_err(|e| Error::Parse(Box::new(e))); + .parse::<T>()?; self.delimiter_split.remove(index); - value + Ok(value) }, _ => Err(Error::Eos), } } /// Returns the first argument that can be converted and does not remove it from the list. - pub fn find_n<T: FromStr>(&self) -> Result<T> - where T::Err: StdError + 'static { + pub fn find_n<T: FromStr>(&self) -> Result<T, T::Err> + where T::Err: StdError { if self.delimiter_split.is_empty() { return Err(Error::Eos); } - self.delimiter_split + Ok(self.delimiter_split .iter() .find(|e| e.parse::<T>().is_ok()) .ok_or(Error::Eos)? - .parse::<T>() - .map_err(|e| Error::Parse(Box::new(e))) + .parse::<T>()?) } } |