summary refs log tree commit diff stats
path: root/src/args.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/args.rs')
-rw-r--r--src/args.rs95
1 files changed, 93 insertions, 2 deletions
diff --git a/src/args.rs b/src/args.rs
index 178203d..2a9bc28 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -9,9 +9,16 @@ use ::std::any::Any;
 use ::std::borrow::Cow;
 use ::std::future::Future;
 use ::std::io::Cursor;
+use ::std::marker::PhantomData;
+use ::std::num::ParseFloatError;
+use ::std::num::ParseIntError;
+use ::std::ops::RangeBounds;
 use ::std::pin::Pin;
+use ::std::str::FromStr;
 
-use crate::strcursor::{StringReader, ReadError};
+use crate::error::RangeError;
+use crate::error::ReadError;
+use crate::strcursor::StringReader;
 use crate::suggestion::Suggestions;
 use crate::suggestion::SuggestionsBuilder;
 
@@ -34,7 +41,8 @@ pub struct CommandContext<'i, S, E>(::std::marker::PhantomData<(&'i str, S, E)>)
 /// use ::std::io::Cursor;
 ///
 /// use ::iosonism::args::ArgumentType;
-/// use ::iosonism::strcursor::{ReadError, StringReader};
+/// use ::iosonism::error::ReadError;
+/// use ::iosonism::strcursor::StringReader;
 ///
 /// struct BoolArgumentType;
 ///
@@ -120,6 +128,7 @@ impl<T: ArgumentType<S, E>, S, E> ArgumentTypeAny<S, E> for T {
 /// A boolean argument.
 // FIXME add examples/expand docs
 // FIXME add tests
+#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash, Default)]
 pub struct BoolArgumentType;
 
 /// An `ArgumentType` for `bool`.
@@ -158,3 +167,85 @@ where for<'i> E: ReadError<'i, Cursor<&'i str>>
         Cow::Borrowed(&["true", "false"])
     }
 }
+
+/// An integer argument.
+#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash, Default)]
+pub struct IntegerArgumentType<T, R: RangeBounds<T>> {
+    /// The valid range for this argument.
+    pub range: R,
+    /// PhantomData for the type.
+    pub _ty: PhantomData<T>,
+}
+
+/// An `ArgumentType` for integer types.
+impl<S, E, T, R> ArgumentType<S, E> for IntegerArgumentType<T, R>
+where
+    for<'i> E: ReadError<'i, Cursor<&'i str>>,
+    for<'i> E: RangeError<'i, Cursor<&'i str>, T, R>,
+    R: RangeBounds<T>,
+    T: PartialOrd<T> + FromStr<Err=ParseIntError> + Any,
+{
+    /// An `IntegerArgumentType` parses an integer type.
+    type Result = T;
+
+    /// Attempts to parse an integer from the `reader`.
+    fn parse<'i>(
+        &self,
+        reader: &mut Cursor<&'i str>,
+    ) -> Result<T, E> where E: 'i {
+        let start = reader.position();
+        let value = reader.read_integer()?;
+        if self.range.contains(&value) {
+            Ok(value)
+        } else {
+            reader.set_position(start);
+            Err(E::value_not_in_range(reader, &value, &self.range))
+        }
+    }
+
+    /// Returns examples
+    fn get_examples(&self) -> Cow<'static, [&str]> {
+        Cow::Borrowed(&["0", "123", "-123"])
+    }
+}
+
+/// A float argument.
+#[derive(Copy, Clone, PartialEq, Debug, PartialOrd, Default)]
+pub struct FloatArgumentType<T, R: RangeBounds<T>> {
+    /// The valid range for this argument.
+    pub range: R,
+    /// PhantomData for the type.
+    pub _ty: PhantomData<T>,
+}
+
+/// An `ArgumentType` for float types.
+impl<S, E, T, R> ArgumentType<S, E> for FloatArgumentType<T, R>
+where
+    for<'i> E: ReadError<'i, Cursor<&'i str>>,
+    for<'i> E: RangeError<'i, Cursor<&'i str>, T, R>,
+    R: RangeBounds<T>,
+    T: PartialOrd<T> + FromStr<Err=ParseFloatError> + Any,
+{
+    /// A `FloatArgumentType` parses a float type.
+    type Result = T;
+
+    /// Attempts to parse a float from the `reader`.
+    fn parse<'i>(
+        &self,
+        reader: &mut Cursor<&'i str>,
+    ) -> Result<T, E> where E: 'i {
+        let start = reader.position();
+        let value = reader.read_float()?;
+        if self.range.contains(&value) {
+            Ok(value)
+        } else {
+            reader.set_position(start);
+            Err(E::value_not_in_range(reader, &value, &self.range))
+        }
+    }
+
+    /// Returns examples
+    fn get_examples(&self) -> Cow<'static, [&str]> {
+        Cow::Borrowed(&["0", "1.2", ".5", "-1", "-.5", "-1234.56"])
+    }
+}