aboutsummaryrefslogtreecommitdiff
path: root/src/framework/standard/args.rs
diff options
context:
space:
mode:
authoracdenisSK <[email protected]>2017-09-23 23:16:26 +0200
committeracdenisSK <[email protected]>2017-09-23 23:16:26 +0200
commitab67c1dd60b5f49541815b2527e8a3cb7712e182 (patch)
treeb7d7f1d5c0342c80488972e4e0157dc964a9baea /src/framework/standard/args.rs
parentDowngrade sodiumoxide to v0.0.14 (diff)
downloadserenity-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.rs112
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>()?)
}
}