diff options
Diffstat (limited to 'arg_picker/src/picker.rs')
| -rw-r--r-- | arg_picker/src/picker.rs | 543 |
1 files changed, 0 insertions, 543 deletions
diff --git a/arg_picker/src/picker.rs b/arg_picker/src/picker.rs deleted file mode 100644 index e8256ce..0000000 --- a/arg_picker/src/picker.rs +++ /dev/null @@ -1,543 +0,0 @@ -// Doc Not Optimize -use std::{marker::PhantomData, ops::Index}; - -mod parse; - -mod patterns; -pub use patterns::*; - -mod result; -pub use result::*; - -use crate::{Pickable, PickerArg, PickerArgResult}; - -#[doc = include_str!("../README.md")] -pub struct Picker<'a, Route = ()> { - pub(crate) route_phantom: PhantomData<Route>, - - /// Internal arguments of Picker - pub(crate) args: PickerArgs<'a>, -} - -impl<'a> Picker<'a> { - /// Creates a new `Picker` from the command-line arguments (excluding the program name). - /// - /// This is equivalent to calling `std::env::args().skip(1)`, which - /// collects all arguments passed to the program except the first one - /// (the executable path). - #[must_use] - pub fn from_args() -> Self { - Self::from_args_skip(1) - } - - /// Creates a new `Picker` from the command-line arguments, skipping the - /// first `skip` entries. - /// - /// This method is useful when you want more control over which arguments - /// are included. For example, pass `skip = 2` to skip both the program - /// name and the first argument. - #[must_use] - pub fn from_args_skip(skip: usize) -> Self { - let args = std::env::args().skip(skip).collect::<Vec<String>>(); - Picker { - route_phantom: PhantomData, - args: PickerArgs::Owned(args), - } - } - - /// Changes the route (phantom type parameter) of the `Picker`. - /// - /// This method allows converting a `Picker` from one route type to another, - /// while preserving the same underlying arguments. The route type is typically - /// used to distinguish different parsing contexts or to carry compile-time - /// state information through the picking chain. - #[must_use] - pub fn with_route<NewRoute>(self) -> Picker<'a, NewRoute> - where - Self: Sized, - { - Picker { - route_phantom: PhantomData, - args: self.args, - } - } -} - -/// Internal arguments of Picker -/// -/// - `Slice` - borrowed slice of string slices -/// - `Vec` - owned vector of borrowed string slices -/// - `Owned` - owned vector of owned strings -pub enum PickerArgs<'a> { - /// Borrowed slice of string slices - Slice(&'a [&'a str]), - /// Owned vector of borrowed string slices - Vec(Vec<&'a str>), - /// Owned vector of owned strings - Owned(Vec<String>), -} - -impl<'a> From<PickerArgs<'a>> for Vec<String> { - fn from(value: PickerArgs<'a>) -> Self { - match value { - PickerArgs::Slice(items) => items.iter().map(ToString::to_string).collect(), - PickerArgs::Vec(items) => items.into_iter().map(ToString::to_string).collect(), - PickerArgs::Owned(items) => items, - } - } -} - -impl<'a> From<&'a PickerArgs<'a>> for Vec<&'a str> { - fn from(value: &'a PickerArgs<'a>) -> Self { - match value { - PickerArgs::Slice(items) => items.to_vec(), - PickerArgs::Vec(items) => items.clone(), - PickerArgs::Owned(items) => items.iter().map(String::as_str).collect(), - } - } -} - -impl Default for PickerArgs<'_> { - fn default() -> Self { - Self::Vec(vec![]) - } -} - -impl<'a> PickerArgs<'a> { - /// Returns the number of arguments. - #[must_use] - pub const fn len(&self) -> usize { - match self { - PickerArgs::Slice(items) => items.len(), - PickerArgs::Vec(items) => items.len(), - PickerArgs::Owned(items) => items.len(), - } - } - - /// Returns `true` if there are no arguments. - #[must_use] - pub const fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Returns an iterator over the arguments, yielding `&str` values. - #[must_use] - pub fn iter(&'a self) -> PickerIter<'a> { - match self { - PickerArgs::Slice(items) => PickerIter::Slice(items.iter()), - PickerArgs::Vec(items) => PickerIter::Vec(items.iter()), - PickerArgs::Owned(items) => PickerIter::Owned(items.iter()), - } - } - - /// Returns a reference to the argument at `index`, if it exists. - #[must_use] - pub fn get(&self, index: usize) -> Option<&str> { - match self { - PickerArgs::Slice(items) => items.get(index).copied(), - PickerArgs::Vec(items) => items.get(index).copied(), - PickerArgs::Owned(items) => items.get(index).map(String::as_str), - } - } -} - -impl Index<usize> for PickerArgs<'_> { - type Output = str; - - fn index(&self, index: usize) -> &Self::Output { - match self { - PickerArgs::Slice(items) => items[index], - PickerArgs::Vec(items) => items[index], - PickerArgs::Owned(items) => &items[index], - } - } -} - -impl<'a> IntoIterator for &'a PickerArgs<'a> { - type Item = &'a str; - type IntoIter = PickerIter<'a>; - - fn into_iter(self) -> Self::IntoIter { - match self { - PickerArgs::Slice(items) => PickerIter::Slice(items.iter()), - PickerArgs::Vec(items) => PickerIter::Vec(items.iter()), - PickerArgs::Owned(items) => PickerIter::Owned(items.iter()), - } - } -} - -impl<'a, Route> From<PickerArgs<'a>> for Picker<'a, Route> { - fn from(args: PickerArgs<'a>) -> Self { - Picker { - route_phantom: PhantomData, - args, - } - } -} - -impl<'a, Route> From<&'a [&'a str]> for Picker<'a, Route> { - fn from(value: &'a [&'a str]) -> Self { - Picker { - route_phantom: PhantomData, - args: PickerArgs::Slice(value), - } - } -} - -impl<'a, Route> From<Vec<&'a str>> for Picker<'a, Route> { - fn from(value: Vec<&'a str>) -> Self { - Picker { - route_phantom: PhantomData, - args: PickerArgs::Vec(value), - } - } -} - -impl<Route> From<Vec<String>> for Picker<'_, Route> { - fn from(value: Vec<String>) -> Self { - Picker { - route_phantom: PhantomData, - args: PickerArgs::Owned(value), - } - } -} - -impl<'a, Route> Picker<'a, Route> { - /// Returns a reference to the internal `PickerArgs`. - #[must_use] - pub const fn args(&self) -> &PickerArgs<'a> { - &self.args - } - - /// Returns a mutable reference to the internal `PickerArgs`. - pub const fn args_mut(&mut self) -> &mut PickerArgs<'a> { - &mut self.args - } - - /// Consumes `self` and returns the internal `PickerArgs`. - #[must_use] - pub fn into_args(self) -> PickerArgs<'a> { - self.args - } - - /// Returns the number of arguments. - #[must_use] - pub const fn len(&self) -> usize { - self.args.len() - } - - /// Returns `true` if there are no arguments. - #[must_use] - pub const fn is_empty(&self) -> bool { - self.args.is_empty() - } - - /// Returns an iterator over the arguments, yielding `&str` values. - #[must_use] - pub fn iter(&'a self) -> PickerIter<'a> { - self.args.iter() - } -} - -impl Index<usize> for Picker<'_> { - type Output = str; - - fn index(&self, index: usize) -> &Self::Output { - &self.args[index] - } -} - -impl<'a, Route> Index<usize> for &'a Picker<'a, Route> { - type Output = str; - - fn index(&self, index: usize) -> &Self::Output { - &self.args[index] - } -} - -impl<'a, Route> IntoIterator for &'a Picker<'a, Route> { - type Item = &'a str; - type IntoIter = PickerIter<'a>; - - fn into_iter(self) -> Self::IntoIter { - self.args.iter() - } -} - -/// Iterator for `Picker` (and `PickerArgs`), yielding `&'a str` values. -pub enum PickerIter<'a> { - /// Iterates over a borrowed slice (`&[&str]`) - Slice(std::slice::Iter<'a, &'a str>), - /// Iterates over an owned vector of borrowed string slices (`Vec<&str>`) - Vec(std::slice::Iter<'a, &'a str>), - /// Iterates over an owned vector of owned strings (`Vec<String>`) - Owned(std::slice::Iter<'a, String>), -} - -impl<'a> Iterator for PickerIter<'a> { - type Item = &'a str; - - fn next(&mut self) -> Option<Self::Item> { - match self { - PickerIter::Slice(iter) | PickerIter::Vec(iter) => iter.next().copied(), - PickerIter::Owned(iter) => iter.next().map(String::as_str), - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - match self { - PickerIter::Slice(iter) | PickerIter::Vec(iter) => iter.size_hint(), - PickerIter::Owned(iter) => iter.size_hint(), - } - } -} - -impl ExactSizeIterator for PickerIter<'_> {} - -impl<'a, Route> Picker<'a, Route> { - /// Creates a `PickerPattern1` from the given arg to start a picking chain. - /// - /// This method initiates a parameter picking chain with one arg. - /// The result is initially `Unparsed`. - pub fn pick<N>(self, arg: impl Into<&'a PickerArg<'a, N>>) -> PickerPattern1<'a, N, Route> - where - N: Pickable<'a>, - { - Self::build_pattern1(self.args, arg.into(), None::<Route>) - } - - /// Creates a `PickerPattern1` from the given arg. - /// If parsing fails, attempts the fallback arg. - pub fn pick_or<N, F>( - self, - arg: impl Into<&'a PickerArg<'a, N>>, - or_arg: F, - ) -> PickerPattern1<'a, N, Route> - where - N: Pickable<'a>, - F: FnMut() -> N + 'static, - { - self.pick(arg).or(or_arg) - } - - /// Creates a `PickerPattern1` from the given arg. - /// If parsing fails, uses the provided default value. - pub fn pick_or_default<N>( - self, - arg: impl Into<&'a PickerArg<'a, N>>, - ) -> PickerPattern1<'a, N, Route> - where - N: Pickable<'a> + Default, - { - self.pick(arg).or_default() - } - - /// Creates a `PickerPattern1` from the given arg. - /// If parsing fails, switches to the given error route. - pub fn pick_or_route<N, F>( - self, - arg: impl Into<&'a PickerArg<'a, N>>, - error_route: F, - ) -> PickerPattern1<'a, N, Route> - where - N: Pickable<'a>, - F: FnMut() -> Route + 'static, - { - self.pick(arg).or_route(error_route) - } -} - -/// Trait for converting types into a `Picker` -/// -/// Implemented for: -/// - `&[&str]` (borrowed slice) -/// - `&[String]` (borrowed slice of owned strings) -/// - `Vec<&str>` (owned vector of borrowed strings) -/// - `Vec<String>` (owned vector of owned strings) -pub trait IntoPicker<'a> { - /// Converts the value into a `Picker` - /// - /// # Examples - /// - /// ``` - /// use arg_picker::{IntoPicker, Picker}; - /// - /// let args: Picker = (&["hello", "world"][..]).to_picker(); - /// assert_eq!(args.len(), 2); - /// - /// let args: Picker = vec!["foo", "bar"].to_picker(); - /// assert_eq!(args.len(), 2); - /// - /// let args: Picker = vec!["a".to_string(), "b".to_string()].to_picker(); - /// assert_eq!(args.len(), 2); - /// ``` - fn to_picker(self) -> Picker<'a, ()>; - - /// Creates a `PickerPattern1` from the given arg for the `pick` method. - /// - /// This method converts the value into a `Picker` and starts a parameter - /// picking chain with one arg. The result is initially `Unparsed`. - fn pick<N>(self, arg: impl Into<&'a PickerArg<'a, N>>) -> PickerPattern1<'a, N, ()> - where - Self: Sized, - N: Pickable<'a> + Sized, - { - Picker::build_pattern1(self.to_picker().args, arg.into(), None::<()>) - } - - /// Starts building a picker pattern with the first argument, using a default value provider. - /// - /// This is a shorthand for calling `.pick(arg).or(func)`. - /// - /// # Type Parameters - /// - /// * `Next` — The nominal type of the first argument; must implement [`Pickable`]. - /// - /// # Parameters - /// - /// * `arg` — The argument definition, typically obtained from [`crate::macros::arg`]. - /// * `func` — A closure that provides a default value if the arg is not provided by the user. - fn pick_or<Next, F>( - self, - arg: impl Into<&'a PickerArg<'a, Next>>, - func: F, - ) -> PickerPattern1<'a, Next, ()> - where - Self: Sized, - Next: Pickable<'a> + Sized, - F: FnMut() -> Next + 'static, - { - self.pick(arg).or(func) - } - - /// Starts building a picker pattern with the first argument, using a default value. - /// - /// This is a shorthand for calling `.pick(arg).or_default()`. - /// - /// # Type Parameters - /// - /// * `Next` — The nominal type of the first argument; must implement [`Pickable`] and [`Default`]. - /// - /// # Parameters - /// - /// * `arg` — The argument definition, typically obtained from [`crate::macros::arg`]. - fn pick_or_default<Next>( - self, - arg: impl Into<&'a PickerArg<'a, Next>>, - ) -> PickerPattern1<'a, Next, ()> - where - Self: Sized, - Next: Pickable<'a> + Default + Sized, - { - self.pick(arg).or_default() - } - - /// Starts building a picker pattern with the first argument, using a route if the arg is not provided. - /// - /// This is a shorthand for calling `.pick(arg).or_route(func)`. - /// - /// # Type Parameters - /// - /// * `Next` — The nominal type of the first argument; must implement [`Pickable`]. - /// - /// # Parameters - /// - /// * `arg` — The argument definition, typically obtained from [`crate::macros::arg`]. - /// * `func` — A closure that produces a route value if the arg is not provided by the user. - fn pick_or_route<Next, F, Route>( - self, - arg: impl Into<&'a PickerArg<'a, Next>>, - func: F, - ) -> PickerPattern1<'a, Next, Route> - where - Self: Sized, - Next: Pickable<'a> + Sized, - F: FnMut() -> Route + 'static, - { - self.pick(arg).with_route::<Route>().or_route(func) - } - - /// Converts the value into a `Picker` with a specified route type. - /// - /// This method allows changing the route (phantom type parameter) of the picker. - /// The route type is typically used to distinguish different parsing contexts or - /// to carry compile-time state information through the picking chain. - fn with_route<NewRoute>(self) -> Picker<'a, NewRoute> - where - Self: Sized, - { - Picker { - route_phantom: PhantomData, - args: self.to_picker().args, - } - } -} - -impl<'a> IntoPicker<'a> for &'a [&'a str] { - fn to_picker(self) -> Picker<'a, ()> { - Picker { - route_phantom: PhantomData, - args: PickerArgs::Slice(self), - } - } -} - -impl<'a> IntoPicker<'a> for &'a [String] { - fn to_picker(self) -> Picker<'a, ()> { - let vec: Vec<&str> = self.iter().map(String::as_str).collect(); - Picker { - route_phantom: PhantomData, - args: PickerArgs::Vec(vec), - } - } -} - -impl<'a> IntoPicker<'a> for Vec<&'a str> { - fn to_picker(self) -> Picker<'a, ()> { - Picker { - route_phantom: PhantomData, - args: PickerArgs::Vec(self), - } - } -} - -impl<'a> IntoPicker<'a> for &'a Vec<String> { - fn to_picker(self) -> Picker<'a, ()> { - let slice: Vec<&str> = self.iter().map(String::as_str).collect(); - Picker { - route_phantom: PhantomData, - args: PickerArgs::Vec(slice), - } - } -} - -impl<'a> IntoPicker<'a> for Vec<String> { - fn to_picker(self) -> Picker<'a, ()> { - Picker { - route_phantom: PhantomData, - args: PickerArgs::Owned(self), - } - } -} - -impl<'a, Route> Picker<'a, Route> { - /// Build the `PickerPattern` via Arguments - pub fn build_pattern1<N>( - args: PickerArgs<'a>, - arg: &'a PickerArg<'a, N>, - error_route: Option<Route>, - ) -> PickerPattern1<'a, N, Route> - where - N: Pickable<'a>, - { - PickerPattern1 { - args, - error_route, - arg_1: arg, - result_1: PickerArgResult::Unparsed, - route_1: None, - default_1: None, - post_1: None, - } - } -} |
