diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-07-15 16:08:16 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-07-15 16:14:15 +0800 |
| commit | a7a116110a80dee887ee2d9a2660fbff5e0cbc62 (patch) | |
| tree | 120f5f497d6ba169a57af8ea77fd8df7e8432b9d | |
| parent | c3e990a5c47dc8894899d774a0d89f089adec308 (diff) | |
feat(picker): add Route generic parameter for error routing
| -rw-r--r-- | mingling_picker/src/picker.rs | 51 | ||||
| -rw-r--r-- | mingling_picker/src/picker/parse.rs | 40 | ||||
| -rw-r--r-- | mingling_picker/src/picker/patterns.rs | 15 |
3 files changed, 59 insertions, 47 deletions
diff --git a/mingling_picker/src/picker.rs b/mingling_picker/src/picker.rs index 246e013..3926554 100644 --- a/mingling_picker/src/picker.rs +++ b/mingling_picker/src/picker.rs @@ -1,4 +1,4 @@ -use std::ops::Index; +use std::{marker::PhantomData, ops::Index}; mod parse; @@ -17,7 +17,9 @@ use crate::{Pickable, PickerArgResult, PickerFlag}; /// - Basic arguments /// - Parsing states /// - Parsing results -pub struct Picker<'a> { +pub struct Picker<'a, Route> { + route_phantom: PhantomData<Route>, + /// Internal arguments of Picker args: PickerArgs<'a>, } @@ -101,31 +103,34 @@ impl<'a> IntoIterator for &'a PickerArgs<'a> { } } -impl<'a> From<&'a [&'a str]> for Picker<'a> { +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> From<Vec<&'a str>> for Picker<'a> { +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<'a> From<Vec<String>> for Picker<'a> { +impl<'a, Route> From<Vec<String>> for Picker<'a, Route> { fn from(value: Vec<String>) -> Self { Picker { + route_phantom: PhantomData, args: PickerArgs::Owned(value), } } } -impl<'a> Picker<'a> { +impl<'a, Route> Picker<'a, Route> { /// Returns a reference to the internal `PickerArgs`. pub fn args(&self) -> &PickerArgs<'a> { &self.args @@ -157,7 +162,7 @@ impl<'a> Picker<'a> { } } -impl<'a> Index<usize> for Picker<'a> { +impl<'a, Route> Index<usize> for Picker<'a, Route> { type Output = str; fn index(&self, index: usize) -> &Self::Output { @@ -165,7 +170,7 @@ impl<'a> Index<usize> for Picker<'a> { } } -impl<'a> Index<usize> for &Picker<'a> { +impl<'a, Route> Index<usize> for &Picker<'a, Route> { type Output = str; fn index(&self, index: usize) -> &Self::Output { @@ -173,7 +178,7 @@ impl<'a> Index<usize> for &Picker<'a> { } } -impl<'a> IntoIterator for &'a Picker<'a> { +impl<'a, Route> IntoIterator for &'a Picker<'a, Route> { type Item = String; type IntoIter = PickerIter<'a>; @@ -218,9 +223,10 @@ impl<'a> ExactSizeIterator for PickerIter<'a> {} /// /// 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> { +pub trait IntoPicker<'a, Route> { /// Converts the value into a `Picker` /// /// # Examples @@ -237,13 +243,13 @@ pub trait IntoPicker<'a> { /// let args: Picker = vec!["a".to_string(), "b".to_string()].to_picker(); /// assert_eq!(args.len(), 2); /// ``` - fn to_picker(self) -> Picker<'a>; + fn to_picker(self) -> Picker<'a, Route>; /// Creates a `PickerPattern1` from the given flag for the `pick` method. /// /// This method converts the value into a `Picker` and starts a parameter /// picking chain with one flag. The result is initially `Unparsed`. - fn pick<N>(self, flag: &'a PickerFlag<'a, N>) -> PickerPattern1<'a, N> + fn pick<N>(self, flag: &'a PickerFlag<'a, N>) -> PickerPattern1<'a, N, Route> where Self: Sized, N: Pickable<'a> + Default + Sized, @@ -254,38 +260,43 @@ pub trait IntoPicker<'a> { result_1: PickerArgResult::Unparsed, default_1: None, post_1: None, + error_route: None, } } } -impl<'a> IntoPicker<'a> for &'a [&'a str] { - fn to_picker(self) -> Picker<'a> { +impl<'a, Route> IntoPicker<'a, Route> for &'a [&'a str] { + fn to_picker(self) -> Picker<'a, Route> { Picker { + route_phantom: PhantomData, args: PickerArgs::Slice(self), } } } -impl<'a> IntoPicker<'a> for &'a [String] { - fn to_picker(self) -> Picker<'a> { +impl<'a, Route> IntoPicker<'a, Route> for &'a [String] { + fn to_picker(self) -> Picker<'a, Route> { let vec: Vec<&str> = self.iter().map(|s| s.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> { +impl<'a, Route> IntoPicker<'a, Route> for Vec<&'a str> { + fn to_picker(self) -> Picker<'a, Route> { Picker { + route_phantom: PhantomData, args: PickerArgs::Vec(self), } } } -impl<'a> IntoPicker<'a> for Vec<String> { - fn to_picker(self) -> Picker<'a> { +impl<'a, Route> IntoPicker<'a, Route> for Vec<String> { + fn to_picker(self) -> Picker<'a, Route> { Picker { + route_phantom: PhantomData, args: PickerArgs::Owned(self), } } diff --git a/mingling_picker/src/picker/parse.rs b/mingling_picker/src/picker/parse.rs index 8a55e03..ab72206 100644 --- a/mingling_picker/src/picker/parse.rs +++ b/mingling_picker/src/picker/parse.rs @@ -7,7 +7,9 @@ // P.S. If there's a better way, please let me know. Thanks! // -------------------------------------------------------------------------------------------- -use crate::{Pickable, PickerArgInfo, PickerArgs, PickerFlagAttr, PickerResult, TagPhaseContext}; +use crate::{ + Pickable, PickerArgInfo, PickerArgResult, PickerArgs, PickerFlagAttr, TagPhaseContext, +}; use mingling_picker_macros::internal_repeat; internal_repeat!(1..=32 => { @@ -19,7 +21,7 @@ internal_repeat!(1..=32 => { where (T$: Pickable<'a>,+) { #[allow(clippy::type_complexity)] - pub fn parse(mut self) -> PickerResult<((T$,+))> { + pub fn parse(mut self) -> PickerArgResult<((T$,+))> { // ArgInfos let arg_infos: [PickerArgInfo; $] = [ ( @@ -27,17 +29,16 @@ internal_repeat!(1..=32 => { +) ]; - // Read & sort attrs - let mut attrs: [ + let mut bundle: [ ( // Flag Attr PickerFlagAttr, // Tag Func - Box<dyn FnOnce(&PickerArgs<'a>) -> Vec<usize>>, + Option<Box<dyn FnOnce(&PickerArgs<'a>) -> Vec<usize>>>, // Pick Func - Box<dyn FnOnce(&[&str])>, + Option<Box<dyn FnOnce(&[&str])>>, // Index usize @@ -49,23 +50,23 @@ internal_repeat!(1..=32 => { T$::get_attr(self.flag_$), // Tag Func - Box::new(|args| { + Some(Box::new(|args| { let ctx = TagPhaseContext { arg_info: &arg_infos[$], args, }; T$::tag(ctx) - }), + })), // Pick Func - Box::new(|args| { + Some(Box::new(|args| { self.result_$ = match T$::pick(args) { - PickerResult::Parsed(mut value) => { + PickerArgResult::Parsed(mut value) => { // Postprocess if let Some(post) = self.post_$ { value = post(value); } - PickerResult::Parsed(value) + PickerArgResult::Parsed(value) }, other => { if let Some(get_default) = self.default_$ { @@ -76,14 +77,14 @@ internal_repeat!(1..=32 => { value = post(value); } - PickerResult::Parsed(value) + PickerArgResult::Parsed(value) } else { other } }, } - }), + })), // Index $ @@ -91,14 +92,14 @@ internal_repeat!(1..=32 => { +) ]; - // Sort by Attr Ord (descending) - attrs.sort_by(|a, b| b.0.cmp(&a.0)); + // Sort by Bundle Ord (descending) + bundle.sort_by(|a, b| b.0.cmp(&a.0)); // Parsing - for (_, tag_func, pick_func, _idx) in attrs { + for (_, tag_func, pick_func, _idx) in bundle { // Tag phase - let tagged = tag_func(&self.args); + let tagged = (tag_func.unwrap())(&self.args); let mut args_to_pick: Vec<&str> = vec![]; for i in tagged { @@ -107,13 +108,10 @@ internal_repeat!(1..=32 => { } // Pick phase - pick_func(args_to_pick.as_slice()); + (pick_func.unwrap())(args_to_pick.as_slice()); } - // Sort by Index Ord - attrs.sort_by(|a, b| a.3.cmp(&b.3)); - PickerResult::NotFound } } }); diff --git a/mingling_picker/src/picker/patterns.rs b/mingling_picker/src/picker/patterns.rs index b828849..d8a2797 100644 --- a/mingling_picker/src/picker/patterns.rs +++ b/mingling_picker/src/picker/patterns.rs @@ -4,10 +4,11 @@ use crate::{Pickable, Picker, PickerArgResult, PickerArgs, PickerFlag}; internal_repeat!(1..=32 => { #[doc(hidden)] - pub struct PickerPattern$<'a, (T$,+)> + pub struct PickerPattern$<'a, (T$,+), Route> where (T$: Pickable<'a>,+) { pub args: PickerArgs<'a>, + pub error_route: Option<Route>, ( pub flag_$: &'a PickerFlag<'a, T$>, pub result_$: PickerArgResult<T$>, @@ -18,7 +19,7 @@ internal_repeat!(1..=32 => { }); internal_repeat!(1..=32 => { - impl<'a, (T$,+)> PickerPattern$<'a, (T$,+)> + impl<'a, (T$,+), Route> PickerPattern$<'a, (T$,+), Route> where (T$: Pickable<'a>,+) { /// Sets a default value provider for this flag. @@ -90,7 +91,7 @@ internal_repeat!(1..=32 => { }); internal_repeat!(1..32 => { - impl<'a, (T$,+)> PickerPattern$<'a, (T$,+)> + impl<'a, (T$,+), Route> PickerPattern$<'a, (T$,+), Route> where (T$: Pickable<'a>,+) { #[allow(clippy::type_complexity)] @@ -99,13 +100,14 @@ internal_repeat!(1..32 => { /// This method extends the current picking pattern by appending an additional flag. /// The previous flags and their results are preserved as part of the new pattern. /// The new flag's result is initially `Unparsed`. - pub fn pick<N>(self, flag: &'a PickerFlag<'a, N>) -> PickerPattern$+<'a, (T$,+), N> + pub fn pick<N>(self, flag: &'a PickerFlag<'a, N>) -> PickerPattern$+<'a, (T$,+), N, Route> where N: Pickable<'a>, { PickerPattern$+ { // Args args: self.args, + error_route: self.error_route, // Current flag_$+: flag, @@ -125,17 +127,18 @@ internal_repeat!(1..32 => { } }); -impl<'a> Picker<'a> { +impl<'a, Route> Picker<'a, Route> { /// Creates a `PickerPattern1` from the given flag to start a picking chain. /// /// This method initiates a parameter picking chain with one flag. /// The result is initially `Unparsed`. - pub fn pick<N>(self, flag: &'a PickerFlag<'a, N>) -> PickerPattern1<'a, N> + pub fn pick<N>(self, flag: &'a PickerFlag<'a, N>) -> PickerPattern1<'a, N, Route> where N: Pickable<'a>, { PickerPattern1 { args: self.args, + error_route: None::<Route>, flag_1: flag, result_1: PickerArgResult::Unparsed, default_1: None, |
