From 79ec6878877f0fd9246d67d3cd4f8cc2d1200150 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Fri, 17 Jul 2026 11:08:07 +0800 Subject: refactor: rename `mingling_picker` to `arg_picker` --- mingling_picker/src/picker/parse.rs | 177 ---------------------------- mingling_picker/src/picker/patterns.rs | 205 --------------------------------- mingling_picker/src/picker/result.rs | 56 --------- 3 files changed, 438 deletions(-) delete mode 100644 mingling_picker/src/picker/parse.rs delete mode 100644 mingling_picker/src/picker/patterns.rs delete mode 100644 mingling_picker/src/picker/result.rs (limited to 'mingling_picker/src/picker') diff --git a/mingling_picker/src/picker/parse.rs b/mingling_picker/src/picker/parse.rs deleted file mode 100644 index 698baac..0000000 --- a/mingling_picker/src/picker/parse.rs +++ /dev/null @@ -1,177 +0,0 @@ -// -------------------------------------------------------------------------------------------- -// I have to say, the code generated by this `internal_repeat!` macro is really UGLY. -// -// But I have to admit, this is a **trade-off**. To achieve the syntax of `pick().pick().pick()` -// while ensuring type safety, this is the best approach I could think of. -// -// P.S. If there's a better way, please let me know. Thanks! -// -------------------------------------------------------------------------------------------- -// -// Then, I must disable `clippy::type_complexity` — this guy is way too noisy. -#![allow(clippy::type_complexity)] - -use crate::{Pickable, PickerArgAttr, PickerArgInfo, PickerArgResult, PickerArgs, TagPhaseContext}; -use mingling_picker_macros::internal_repeat; - -internal_repeat!(1..=32 => { - use crate::PickerPattern$; - use crate::PickerResult$; -}); - -internal_repeat!(1..=32 => { - impl<'a, (T$,+), Route> PickerPattern$<'a, (T$,+), Route> - where (T$: Pickable<'a>,+) { - /// Unwraps the result, panicking if a route was selected. - /// - /// # Panics - /// - /// Panics if a route was selected. - pub fn unwrap(self) -> ((T$,+)) { - let p = self.parse(); - ((p.v$.unwrap(),+)) - } - - /// Returns the individual option values without checking the route. - pub fn unpack(self) -> ((Option,+)) { - let p = self.parse(); - ((p.v$,+)) - } - - /// Converts to a `Result`, returning `Err(route)` if a route was selected, - /// or `Ok(values)` otherwise. - pub fn to_result(self) -> Result<((T$,+)), Route> { - let p = self.parse(); - if let Some(r) = p.route { - return Err(r); - } - Ok(p.unwrap()) - } - - /// Converts to an `Option`, returning `None` if a route was selected, - /// or `Some(values)` otherwise. - pub fn to_option(self) -> Option<((T$,+))> { - let p = self.parse(); - if p.route.is_some() { - return None; - } - Some(p.unwrap()) - } - } -}); - -internal_repeat!(1..=32 => { - impl<'a, (T$,+), Route> PickerPattern$<'a, (T$,+), Route> - where (T$: Pickable<'a>,+) - { - pub fn parse(mut self) -> PickerResult$<(T$,+), Route> { - // ArgInfos - let arg_infos: [PickerArgInfo; $] = [ - ( - PickerArgInfo::from(self.arg_$), - +) - ]; - - let mut bundle: [ - ( - // Arg Attr - PickerArgAttr, - - // Tag Func - Box, &[u8]) -> Vec>, - - // Pick Func - Box)>, - - // Index - usize - ) - ; $] = [ - ( - ( - // Arg Attr - T$::get_attr(self.arg_$), - - // Tag Func - Box::new(|args, mask| { - let ctx = TagPhaseContext { - arg_info: &arg_infos[$-], - args, - mask - }; - T$::tag(ctx) - }), - - // Pick Func - Box::new(|args, error_route| { - self.result_$ = match T$::pick(args) { - PickerArgResult::Parsed(mut value) => { - // Postprocess - if let Some(post) = self.post_$ { - value = post(value); - } - PickerArgResult::Parsed(value) - }, - other => { - if let Some(get_default) = self.default_$ { - let mut value = get_default(); - - // Postprocess - if let Some(post) = self.post_$ { - value = post(value); - } - - PickerArgResult::Parsed(value) - } else { - if error_route.is_none() { - if let Some(get_route) = self.route_$ { - *error_route = Some(get_route().into()); - } - } - other - } - }, - - } - }), - - // Index - $ - ), - +) - ]; - - // Sort by Bundle Ord (descending) - bundle.sort_by(|a, b| b.0.cmp(&a.0)); - - // Mask — size = number of args (not args), so use args length - let mut mask: Vec = vec![0u8; self.args.len()]; - - // Parsing - for (_, tag_func, pick_func, _idx) in bundle { - - // Tag phase - let tagged = tag_func(&self.args, mask.as_slice()); - let mut args_to_pick: Vec<&str> = vec![]; - - for i in tagged { - mask[i] = 1; - - // Update args to pick - args_to_pick.push(self.args.get(i).unwrap_or_default()); - } - - // Pick phase - pick_func(args_to_pick.as_slice(), &mut self.error_route); - } - - // Combine Result - let result: PickerResult$<(T$,+), Route> = PickerResult$ { - route: self.error_route, - ( - v$: self.result_$.to_option(), - +) - }; - result - } - } -}); diff --git a/mingling_picker/src/picker/patterns.rs b/mingling_picker/src/picker/patterns.rs deleted file mode 100644 index 78ae2b0..0000000 --- a/mingling_picker/src/picker/patterns.rs +++ /dev/null @@ -1,205 +0,0 @@ -use mingling_picker_macros::internal_repeat; - -use crate::{Pickable, PickerArg, PickerArgResult, PickerArgs}; - -internal_repeat!(1..=32 => { - #[doc(hidden)] - pub struct PickerPattern$<'a, (T$,+), Route> - where (T$: Pickable<'a>,+) - { - pub args: PickerArgs<'a>, - pub error_route: Option, - ( - pub(crate) arg_$: &'a PickerArg<'a, T$>, - pub(crate) result_$: PickerArgResult, - pub(crate) default_$: Option T$>>, - pub(crate) route_$: Option Route>>, - pub(crate) post_$: Option T$>>, - +) - } -}); - -internal_repeat!(1..=32 => { - impl<'a, (T$,+), Route> PickerPattern$<'a, (T$,+), Route> - where (T$: Pickable<'a>,+) - { - /// Sets a default value provider for this arg. - /// - /// If the arg is not provided by the user at runtime, the given closure will be - /// called to produce a default value. The closure is expected to return `T$`. - /// - /// # Example - /// - #[allow(clippy::type_complexity)] - pub fn or(mut self, func: F) -> Self - where - F: FnMut() -> T$, - F: 'static, - { - self.default_$ = Some(Box::new(func)); - self - } - - /// Uses the default value for this arg's type if the arg is not provided. - /// - /// If the arg is not provided by the user at runtime, the default value for `T$` - /// (as defined by the `Default` trait) will be used. - /// - /// # Example - /// - #[allow(clippy::type_complexity)] - pub fn or_default(mut self) -> Self - where - T$: Default, - { - self.default_$ = Some(Box::new(|| T$::default())); - self - } - - /// Sets a route for when the arg is not provided. - /// - /// If the arg is not provided by the user at runtime, the given closure will be - /// called to produce a route value that will be returned early. - /// - /// # Example - /// - pub fn or_route(mut self, func: F) -> Self - where - F: FnMut() -> Route, - F: 'static, - { - self.route_$ = Some(Box::new(func)); - self - } - - - /// Resets the route for this picker pattern, allowing a different route type. - /// - /// This method converts the current `PickerPattern` into a new one with a different - /// route type `NewRoute`. All existing arg configurations, defaults, and post- - /// processing functions are preserved, but the `error_route` and individual - /// `route_$` fields are cleared (set to `None`). - /// - /// This is useful when you want to change the error/redirect route type mid-chain, - /// for example when composing patterns from different contexts that use different - /// route enums. - #[allow(clippy::type_complexity)] - pub fn with_route(self) -> PickerPattern$<'a, (T$,+), NewRoute> - { - PickerPattern$ { - args: self.args, - error_route: None, - ( - arg_$: self.arg_$, - result_$: self.result_$, - default_$: self.default_$, - route_$: None, - post_$: self.post_$, - +) - } - } - - /// Attaches a post-processing function to this arg. - /// - /// After the arg's value is parsed (or defaulted), the given closure will be - /// invoked with the parsed value and its return value will be used as the final - /// result. This allows transforming or validating the parsed value. - /// - /// # Example - /// - #[allow(clippy::type_complexity)] - pub fn post(mut self, func: F) -> Self - where - F: FnMut(T$) -> T$, - F: 'static, - { - self.post_$ = Some(Box::new(func)); - self - } - } -}); - -internal_repeat!(1..32 => { - impl<'a, (T$,+), Route> PickerPattern$<'a, (T$,+), Route> - where (T$: Pickable<'a>,+) - { - #[allow(clippy::type_complexity)] - /// Adds a new arg to the picking chain, returning a new `PickerPattern` with one more type parameter. - /// - /// This method extends the current picking pattern by appending an additional arg. - /// The previous args and their results are preserved as part of the new pattern. - /// The new arg's result is initially `Unparsed`. - pub fn pick(self, arg: impl Into<&'a PickerArg<'a, N>>) -> PickerPattern$+<'a, (T$,+), N, Route> - where - N: Pickable<'a>, - { - PickerPattern$+ { - // Args - args: self.args, - error_route: self.error_route, - - // Current - arg_$+: arg.into(), - result_$+: PickerArgResult::Unparsed, - default_$+: None, - route_$+: None, - post_$+: None, - - // Prev - ( - arg_$: self.arg_$, - result_$: self.result_$, - default_$: self.default_$, - route_$: self.route_$, - post_$: self.post_$, - +) - } - } - - /// Picks a new arg with a default value provider in a single call. - /// - /// This is a shorthand for calling `.pick(arg).or(func)`. - /// - /// # Example - /// - #[allow(clippy::type_complexity)] - pub fn pick_or(self, arg: impl Into<&'a PickerArg<'a, N>>, func: F) -> PickerPattern$+<'a, (T$,+), N, Route> - where - N: Pickable<'a>, - F: FnMut() -> N + 'static, - F: 'static, - { - self.pick(arg).or(func) - } - - /// Picks a new arg with a default value in a single call. - /// - /// This is a shorthand for calling `.pick(arg).or_default()`. - /// - /// # Example - /// - #[allow(clippy::type_complexity)] - pub fn pick_or_default(self, arg: impl Into<&'a PickerArg<'a, N>>) -> PickerPattern$+<'a, (T$,+), N, Route> - where - N: Pickable<'a> + Default, - { - self.pick(arg).or_default() - } - - /// Picks a new arg with a route in a single call. - /// - /// This is a shorthand for calling `.pick(arg).or_route(func)`. - /// - /// # Example - /// - #[allow(clippy::type_complexity)] - pub fn pick_or_route(self, arg: impl Into<&'a PickerArg<'a, N>>, func: F) -> PickerPattern$+<'a, (T$,+), N, Route> - where - N: Pickable<'a>, - F: FnMut() -> Route + 'static, - F: 'static, - { - self.pick(arg).or_route(func) - } - } -}); diff --git a/mingling_picker/src/picker/result.rs b/mingling_picker/src/picker/result.rs deleted file mode 100644 index 9cd78ae..0000000 --- a/mingling_picker/src/picker/result.rs +++ /dev/null @@ -1,56 +0,0 @@ -#![allow(clippy::type_complexity)] // Aha, Type Gymnastics! - -use mingling_picker_macros::internal_repeat; - -internal_repeat!(1..=32 => { - #[doc(hidden)] - pub struct PickerResult$<(T$,+), Route> { - /// The route selected by the picker, if any. - /// If this is `Some`, the picker chose to follow a route instead of selecting values, - /// and all value fields (`v1`, `v2`, ...) will be `None`. - /// - /// Note: "route" here refers to an alternative path/choice, not a network route. - pub route: Option, - - ( - #[doc = concat!("The optional value for the ", $, "th type parameter.")] - pub v$: Option, - +) - } -}); - -internal_repeat!(1..=32 => { - impl<(T$,+), Route> PickerResult$<(T$,+), Route> { - /// Unwraps the result, panicking if a route was selected. - /// - /// # Panics - /// - /// Panics if `self.route` is `Some(...)`. - pub fn unwrap(self) -> ((T$,+)) { - ((self.v$.unwrap(),+)) - } - - /// Returns the individual option values without checking the route. - pub fn unpack(self) -> ((Option,+)) { - ((self.v$,+)) - } - - /// Converts to a `Result`, returning `Err(route)` if a route was selected, - /// or `Ok(values)` otherwise. - pub fn to_result(self) -> Result<((T$,+)), Route> { - if let Some(r) = self.route { - return Err(r); - } - Ok(self.unwrap()) - } - - /// Converts to an `Option`, returning `None` if a route was selected, - /// or `Some(values)` otherwise. - pub fn to_option(self) -> Option<((T$,+))> { - if let Some(_) = self.route { - return None; - } - Some(self.unwrap()) - } - } -}); -- cgit