From 03b6d78885b3a59ffa781ded3682c2dd24e65aa7 Mon Sep 17 00:00:00 2001 From: acdenisSK Date: Sun, 20 Aug 2017 23:07:05 +0200 Subject: feature-flag the vec_shift dependency --- src/framework/standard/args.rs | 124 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 src/framework/standard/args.rs (limited to 'src/framework') 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), +} + +type Result = ::std::result::Result; + +#[derive(Debug, Clone)] +pub struct Args { + delimiter: String, + delimiter_split: Vec, +} + +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(&mut self) -> Result where T::Err: StdError + 'static { + if self.delimiter_split.is_empty() { + return Err(Error::Eos); + } + + self.delimiter_split.shift() + .ok_or(Error::Eos)? + .parse::() + .map_err(|e| Error::Parse(Box::new(e))) + } + + /// Like [`single`], but doesn't remove the element. + /// + /// [`single`]: #method.single + pub fn single_n(&mut self) -> Result 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::() + .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 { + self.delimiter_split.shift() + } + + /// Like [`skip`], but allows for multiple at once. + /// + /// [`skip`]: #method.skip + pub fn skip_for(&mut self, i: u32) -> Option> { + 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(&mut self) -> Result where T::Err: StdError + 'static { + parse_quotes(&self.delimiter_split.shift().ok_or(Error::Eos)?).remove(0).parse::().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(&mut self) -> Result where T::Err: StdError + 'static { + parse_quotes(&self.delimiter_split.get(0).ok_or(Error::Eos)?).remove(0).parse::().map_err(|e| Error::Parse(Box::new(e))) + } + + /// Like [`list`], but takes quotes into account. + /// + /// [`list`]: #method.list + pub fn multiple_quoted(self) -> Result> 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::().map_err(|e| Error::Parse(Box::new(e)))).collect() + } + + /// Empty outs the internal vector while parsing (if necessary) and returning them + pub fn list(self) -> Result> where T::Err: StdError + 'static { + if self.delimiter_split.is_empty() { + return Err(Error::Eos); + } + + self.delimiter_split.into_iter().map(|s| s.parse::().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 -- cgit v1.2.3