From 5f330da4e4335fe92208052612d3e96e43c704b6 Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Fri, 3 Dec 2021 23:27:17 -0300 Subject: Begin CommandNode port --- src/args.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 12 deletions(-) (limited to 'src/args.rs') diff --git a/src/args.rs b/src/args.rs index 7e84b48..2b8eecf 100644 --- a/src/args.rs +++ b/src/args.rs @@ -5,7 +5,9 @@ //! Argument processing. +use ::std::any::Any; use ::std::future::Future; +use ::std::io::Cursor; use ::std::pin::Pin; use crate::strcursor::StringReader; @@ -13,7 +15,8 @@ use crate::suggestion::Suggestions; use crate::suggestion::SuggestionsBuilder; // FIXME delete when implemented -pub struct CommandContext<'a, T>(::std::marker::PhantomData<(&'a str, T)>); +/// The parsing context of a command. +pub struct CommandContext<'i, S, E>(::std::marker::PhantomData<(&'i str, S, E)>); /// An argument parser. /// @@ -29,33 +32,39 @@ pub struct CommandContext<'a, T>(::std::marker::PhantomData<(&'a str, T)>); /// A very basic `bool` argument type: /// /// ``` +/// use ::std::io::Cursor; +/// /// use ::iosonism::args::ArgumentType; /// use ::iosonism::strcursor::{ReadError, StringReader}; /// /// struct BoolArgumentType; /// -/// impl<'i, R, S, E> ArgumentType<'i, R, S, E> for BoolArgumentType -/// where R: StringReader<'i>, E: ReadError<'i, R> { +/// impl ArgumentType for BoolArgumentType +/// where for<'i> E: ReadError<'i, Cursor<&'i str>> +/// { /// type Result = bool; -/// fn parse(&self, reader: &mut R) -> Result { +/// fn parse<'i>( +/// &self, +/// reader: &mut Cursor<&'i str>, +/// ) -> Result where E: 'i { /// reader.read_bool() /// } /// } /// ``` -pub trait ArgumentType<'i, R: StringReader<'i>, S, E> { +pub trait ArgumentType { /// The parsed type of the argument. - type Result: Sized + 'static + ::std::any::Any; + type Result: Sized + 'static + Any; /// Parses an argument of this type, returning the parsed argument. - fn parse(&self, reader: &mut R) -> Result; + fn parse<'i>( + &self, + reader: &mut Cursor<&'i str>, + ) -> Result where E: 'i; /// Creates suggestions for this argument. - // The hope here is that S is lightweight enough for one to clone into the - // closure. Unfortunately making it borrowable would be a pain. - // FIXME: this API doesn't look great, can we make it better somehow? - fn list_suggestions( + fn list_suggestions<'i>( &self, - context: &CommandContext<'i, S>, + context: &CommandContext<'i, S, E>, builder: SuggestionsBuilder<'i>, ) -> Pin + Send + 'i>> { let _ = context; @@ -68,3 +77,43 @@ pub trait ArgumentType<'i, R: StringReader<'i>, S, E> { Vec::new() } } + +/// Wrapper around `ArgumentType`, but with `Any`. +pub(crate) trait ArgumentTypeAny { + /// Parses an argument of this type, returning the parsed argument. + fn parse<'i>( + &self, + reader: &mut Cursor<&'i str>, + ) -> Result, E> where E: 'i; + + /// Creates suggestions for this argument. + fn list_suggestions<'i>( + &self, + context: &CommandContext<'i, S, E>, + builder: SuggestionsBuilder<'i>, + ) -> Pin + Send + 'i>>; + + /// Returns examples for this argument. + fn get_examples(&self) -> Vec<&str>; +} + +impl, S, E> ArgumentTypeAny for T { + fn parse<'i>( + &self, + reader: &mut Cursor<&'i str>, + ) -> Result, E> where E: 'i { + self.parse(reader).map(|x| Box::new(x) as _) + } + + fn list_suggestions<'i>( + &self, + context: &CommandContext<'i, S, E>, + builder: SuggestionsBuilder<'i>, + ) -> Pin + Send + 'i>> { + self.list_suggestions(context, builder) + } + + fn get_examples(&self) -> Vec<&str> { + self.get_examples() + } +} -- cgit 1.4.1