From 7620fd1d1e9ff4105c2d93c80c73b2c2ec1cbc9a Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Wed, 15 Jul 2026 15:37:39 +0800 Subject: refactor: remove unnecessary `Default` bound from `Pickable` trait --- mingling_picker/src/picker/parse.rs | 110 ++++++++++++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 4 deletions(-) (limited to 'mingling_picker/src/picker/parse.rs') 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) -> Vec>, + + // Pick Func + Box, + + // 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 } } }); -- cgit