aboutsummaryrefslogtreecommitdiff
path: root/src/framework
diff options
context:
space:
mode:
authoracdenisSK <[email protected]>2017-08-20 23:07:05 +0200
committeracdenisSK <[email protected]>2017-08-21 17:11:57 +0200
commit03b6d78885b3a59ffa781ded3682c2dd24e65aa7 (patch)
tree63d4cd5ab9f718692fbe172ed949cbe64932e664 /src/framework
parentRevamp the args to an `Args` struct (diff)
downloadserenity-03b6d78885b3a59ffa781ded3682c2dd24e65aa7.tar.xz
serenity-03b6d78885b3a59ffa781ded3682c2dd24e65aa7.zip
feature-flag the vec_shift dependency
Diffstat (limited to 'src/framework')
-rw-r--r--src/framework/standard/args.rs124
1 files changed, 124 insertions, 0 deletions
diff --git a/src/framework/standard/args.rs b/src/framework/standard/args.rs
new file mode 100644
index 0000000..020ce6d
--- /dev/null
+++ b/src/framework/standard/args.rs
@@ -0,0 +1,124 @@
+use vec_shift::Shift;
+use std::str::FromStr;
+use std::error::Error as StdError;
+use utils::parse_quotes;
+
+/// Defines how an operation on an `Args` method failed.
+#[derive(Debug)]
+pub enum Error {
+ /// "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>),
+}
+
+type Result<T> = ::std::result::Result<T, Error>;
+
+#[derive(Debug, Clone)]
+pub struct Args {
+ delimiter: String,
+ delimiter_split: Vec<String>,
+}
+
+impl Args {
+ pub fn new(message: &str, delimiter: &str) -> Self {
+ Args {
+ delimiter: delimiter.to_string(),
+ delimiter_split: message.split(delimiter).map(|s| s.to_string()).collect(),
+ }
+ }
+
+ /// 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 {
+ if self.delimiter_split.is_empty() {
+ return Err(Error::Eos);
+ }
+
+ self.delimiter_split.shift()
+ .ok_or(Error::Eos)?
+ .parse::<T>()
+ .map_err(|e| Error::Parse(Box::new(e)))
+ }
+
+ /// Like [`single`], but doesn't remove the element.
+ ///
+ /// [`single`]: #method.single
+ pub fn single_n<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static {
+ if self.delimiter_split.is_empty() {
+ return Err(Error::Eos);
+ }
+
+ self.delimiter_split.get(0)
+ .ok_or(Error::Eos)?
+ .parse::<T>()
+ .map_err(|e| Error::Parse(Box::new(e)))
+ }
+
+ /// Skips if there's a first element, but also returns it.
+ pub fn skip(&mut self) -> Option<String> {
+ self.delimiter_split.shift()
+ }
+
+ /// Like [`skip`], but allows for multiple at once.
+ ///
+ /// [`skip`]: #method.skip
+ pub fn skip_for(&mut self, i: u32) -> Option<Vec<String>> {
+ let mut vec = Vec::with_capacity(i as usize);
+
+ for _ in 0..i {
+ vec.push(match self.delimiter_split.shift() {
+ Some(x) => x,
+ None => return None,
+ });
+ }
+
+ Some(vec)
+ }
+
+ /// 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)?).remove(0).parse::<T>().map_err(|e| Error::Parse(Box::new(e)))
+ }
+
+ /// Like [`single_quoted`], but doesn't remove the element.
+ ///
+ /// [`single_quoted`]: #method.single_quoted
+ pub fn single_quoted_n<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static {
+ parse_quotes(&self.delimiter_split.get(0).ok_or(Error::Eos)?).remove(0).parse::<T>().map_err(|e| Error::Parse(Box::new(e)))
+ }
+
+ /// 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 {
+ 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)))).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 {
+ 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)))).collect()
+ }
+
+ /// This method is just `internal_vector.join(delimiter)`
+ pub fn full(&self) -> String {
+ self.delimiter_split.join(&self.delimiter)
+ }
+}
+
+impl ::std::ops::Deref for Args {
+ type Target = [String];
+
+ fn deref(&self) -> &Self::Target {
+ &self.delimiter_split
+ }
+} \ No newline at end of file