diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-07-15 15:37:39 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-07-15 15:37:39 +0800 |
| commit | 7620fd1d1e9ff4105c2d93c80c73b2c2ec1cbc9a (patch) | |
| tree | 4d4d8985a4e98044aed7acfab7bafadfada7de2e /mingling_picker/src/picker | |
| parent | 2636b92bb475eae00790511d0068126fd0884fbf (diff) | |
refactor: remove unnecessary `Default` bound from `Pickable` trait
Diffstat (limited to 'mingling_picker/src/picker')
| -rw-r--r-- | mingling_picker/src/picker/parse.rs | 110 | ||||
| -rw-r--r-- | mingling_picker/src/picker/patterns.rs | 10 |
2 files changed, 111 insertions, 9 deletions
diff --git a/mingling_picker/src/picker/parse.rs b/mingling_picker/src/picker/parse.rs index f69e078..8a55e03 100644 --- a/mingling_picker/src/picker/parse.rs +++ b/mingling_picker/src/picker/parse.rs @@ -1,4 +1,13 @@ -use crate::{Pickable, PickerResult}; +// -------------------------------------------------------------------------------------------- +// 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! +// -------------------------------------------------------------------------------------------- + +use crate::{Pickable, PickerArgInfo, PickerArgs, PickerFlagAttr, PickerResult, TagPhaseContext}; use mingling_picker_macros::internal_repeat; internal_repeat!(1..=32 => { @@ -7,11 +16,104 @@ internal_repeat!(1..=32 => { internal_repeat!(1..=32 => { impl<'a, (T$,+)> PickerPattern$<'a, (T$,+)> - where (T$: Pickable<'a> + Default,+) + where (T$: Pickable<'a>,+) { #[allow(clippy::type_complexity)] - pub fn parse(self) -> PickerResult<((T$,+))> { - todo!() + pub fn parse(mut self) -> PickerResult<((T$,+))> { + // ArgInfos + let arg_infos: [PickerArgInfo; $] = [ + ( + PickerArgInfo::from(self.flag_$), + +) + ]; + + // Read & sort attrs + let mut attrs: [ + ( + // Flag Attr + PickerFlagAttr, + + // Tag Func + Box<dyn FnOnce(&PickerArgs<'a>) -> Vec<usize>>, + + // Pick Func + Box<dyn FnOnce(&[&str])>, + + // Index + usize + ) + ; $] = [ + ( + ( + // Flag Attr + T$::get_attr(self.flag_$), + + // Tag Func + Box::new(|args| { + let ctx = TagPhaseContext { + arg_info: &arg_infos[$], + args, + }; + T$::tag(ctx) + }), + + // Pick Func + Box::new(|args| { + self.result_$ = match T$::pick(args) { + PickerResult::Parsed(mut value) => { + // Postprocess + if let Some(post) = self.post_$ { + value = post(value); + } + PickerResult::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); + } + + PickerResult::Parsed(value) + } else { + other + } + }, + + } + }), + + // Index + $ + ), + +) + ]; + + // Sort by Attr Ord (descending) + attrs.sort_by(|a, b| b.0.cmp(&a.0)); + + // Parsing + for (_, tag_func, pick_func, _idx) in attrs { + + // Tag phase + let tagged = tag_func(&self.args); + let mut args_to_pick: Vec<&str> = vec![]; + + for i in tagged { + // Update args to pick + args_to_pick.push(self.args.get(i).unwrap_or_default()); + } + + // Pick phase + pick_func(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 b12f151..4f54f9d 100644 --- a/mingling_picker/src/picker/patterns.rs +++ b/mingling_picker/src/picker/patterns.rs @@ -5,7 +5,7 @@ use crate::{Pickable, Picker, PickerArgs, PickerFlag, PickerResult}; internal_repeat!(1..=32 => { #[doc(hidden)] pub struct PickerPattern$<'a, (T$,+)> - where (T$: Pickable<'a> + Default,+) + where (T$: Pickable<'a>,+) { pub args: PickerArgs<'a>, ( @@ -19,7 +19,7 @@ internal_repeat!(1..=32 => { internal_repeat!(1..=32 => { impl<'a, (T$,+)> PickerPattern$<'a, (T$,+)> - where (T$: Pickable<'a> + Default,+) + where (T$: Pickable<'a>,+) { /// Sets a default value provider for this flag. /// @@ -70,7 +70,7 @@ internal_repeat!(1..=32 => { internal_repeat!(1..32 => { impl<'a, (T$,+)> PickerPattern$<'a, (T$,+)> - where (T$: Pickable<'a> + Default,+) + where (T$: Pickable<'a>,+) { #[allow(clippy::type_complexity)] /// Adds a new flag to the picking chain, returning a new `PickerPattern` with one more type parameter. @@ -80,7 +80,7 @@ internal_repeat!(1..32 => { /// The new flag's result is initially `Unparsed`. pub fn pick<N>(self, flag: &'a PickerFlag<'a, N>) -> PickerPattern$+<'a, (T$,+), N> where - N: Pickable<'a> + Default, + N: Pickable<'a>, { PickerPattern$+ { // Args @@ -111,7 +111,7 @@ impl<'a> Picker<'a> { /// The result is initially `Unparsed`. pub fn pick<N>(self, flag: &'a PickerFlag<'a, N>) -> PickerPattern1<'a, N> where - N: Pickable<'a> + Default, + N: Pickable<'a>, { PickerPattern1 { args: self.args, |
