aboutsummaryrefslogtreecommitdiff
path: root/mingling_picker/src/picker
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-07-15 15:37:39 +0800
committer魏曹先生 <1992414357@qq.com>2026-07-15 15:37:39 +0800
commit7620fd1d1e9ff4105c2d93c80c73b2c2ec1cbc9a (patch)
tree4d4d8985a4e98044aed7acfab7bafadfada7de2e /mingling_picker/src/picker
parent2636b92bb475eae00790511d0068126fd0884fbf (diff)
refactor: remove unnecessary `Default` bound from `Pickable` trait
Diffstat (limited to 'mingling_picker/src/picker')
-rw-r--r--mingling_picker/src/picker/parse.rs110
-rw-r--r--mingling_picker/src/picker/patterns.rs10
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,