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/parse.rs | |
| parent | 2636b92bb475eae00790511d0068126fd0884fbf (diff) | |
refactor: remove unnecessary `Default` bound from `Pickable` trait
Diffstat (limited to 'mingling_picker/src/picker/parse.rs')
| -rw-r--r-- | mingling_picker/src/picker/parse.rs | 110 |
1 files changed, 106 insertions, 4 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 } } }); |
