aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md29
-rw-r--r--docs/pages/3-features/1-parser.md2
-rw-r--r--mingling/src/parser/picker.rs180
3 files changed, 161 insertions, 50 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ce51fec..6dee222 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,9 +13,32 @@
#### **BREAKING CHANGES**:
-1. Removed macro `dispatcher_render!` from `mingling_macros`
-2. The `<..., Group>` in `Program<Collect, Group>` no longer requires `std::fmt::Display`
-3. Changed `Program<Collect, Group>` to `Program<Collect>` (merged the Group and Collect types)
+1. **\[macros\]** Removed macro `dispatcher_render!` from `mingling_macros`
+2. **\[core\]** The `<..., Group>` in `Program<Collect, Group>` no longer requires `std::fmt::Display`
+3. **\[core\]** Changed `Program<Collect, Group>` to `Program<Collect>` (merged the Group and Collect types)
+4. **\[picker\]** When performing `unpack` or `unpack_directly` on the result of the first `pick` of `Picker`, it no longer returns a tuple
+
+```rust
+// Before
+#[chain]
+fn parse_sth(prev: SomeEntry) -> NextProcess {
+ let str: String = Picker::<()>::new(prev.inner)
+ .pick_or((), "None")
+ .unpack_directly().0;
+ let parsed = Something::new(ok);
+ parsed
+}
+
+// Now
+#[chain]
+fn parse_sth(prev: SomeEntry) -> NextProcess {
+ let str: String = Picker::<()>::new(prev.inner)
+ .pick_or((), "None")
+ .unpack_directly(); // Directly return the type instead of a tuple
+ let parsed = Something::new(ok);
+ parsed
+}
+```
---
diff --git a/docs/pages/3-features/1-parser.md b/docs/pages/3-features/1-parser.md
index 9c48cfd..1490218 100644
--- a/docs/pages/3-features/1-parser.md
+++ b/docs/pages/3-features/1-parser.md
@@ -44,7 +44,7 @@ fn parse_hello(prev: HelloEntry) -> NextProcess {
// fallback to "World" if it doesn't exist
let first = picker
.pick_or((), "World")
- .unpack_directly().0;
+ .unpack_directly();
ParsedHello::new(first).to_render()
}
diff --git a/mingling/src/parser/picker.rs b/mingling/src/parser/picker.rs
index 449351a..bcb461a 100644
--- a/mingling/src/parser/picker.rs
+++ b/mingling/src/parser/picker.rs
@@ -140,9 +140,10 @@ pub trait Pickable {
fn pick(args: &mut Argument, flag: Flag) -> Option<Self::Output>;
}
-#[doc(hidden)]
-macro_rules! define_pick_structs {
- ($n:tt $final:ident $final_val:ident $($T:ident $val:ident),+) => {
+/// Internal macro: generates the struct definition and common methods
+/// (after, after_or_route, operate_args) for Pick2 through Pick12.
+macro_rules! define_pick_struct {
+ ($n:ident $final:ident $final_val:ident $($T:ident $val:ident),+) => {
#[doc(hidden)]
pub struct $n<$($T,)+ R>
where
@@ -154,39 +155,10 @@ macro_rules! define_pick_structs {
route: Option<R>,
}
- impl<$($T,)+ R> From<$n<$($T,)+ R>> for ($($T,)+)
- where
- $($T: Pickable,)+
- {
- fn from(pick: $n<$($T,)+ R>) -> Self {
- ($(pick.$val,)+)
- }
- }
-
impl<$($T,)+ R> $n<$($T,)+ R>
where
$($T: Pickable,)+
{
- /// Unpacks the builder into a tuple of extracted values.
- ///
- /// Returns `Ok((T1, T2, ...))` if all required flags were present.
- /// Returns `Err(R)` if a required flag was missing and a route was provided via `pick_or_route`.
- pub fn unpack(self) -> Result<($($T,)+), R> {
- match self.route {
- Some(route) => Err(route),
- None => Ok(($(self.$val,)+)),
- }
- }
-
- /// Unpacks the builder into a tuple of extracted values.
- ///
- /// Returns the tuple of extracted values regardless of whether any required flags were missing.
- /// If a required flag was missing and a route was provided via `pick_or_route`, the default value
- /// for that type is included in the tuple.
- pub fn unpack_directly(self) -> ($($T,)+) {
- ($(self.$val,)+)
- }
-
/// Applies a transformation to the last extracted value.
///
/// Takes a closure that receives the last extracted value and returns a new value of the same type.
@@ -226,7 +198,7 @@ macro_rules! define_pick_structs {
self
}
- /// Applies an operation to the parsed arguments and returns the modified `Picker`.
+ /// Applies an operation to the parsed arguments and returns the modified builder.
///
/// Takes a closure that receives the current `Argument` and returns a new `Argument`.
/// The returned `Argument` replaces the original arguments in the builder.
@@ -239,6 +211,131 @@ macro_rules! define_pick_structs {
};
}
+/// Internal macro: generates `From` impl for PickN into a tuple.
+macro_rules! impl_pick_from_tuple {
+ ($n:ident $($T:ident $val:ident),+) => {
+ impl<$($T,)+ R> From<$n<$($T,)+ R>> for ($($T,)+)
+ where
+ $($T: Pickable,)+
+ {
+ fn from(pick: $n<$($T,)+ R>) -> Self {
+ ($(pick.$val,)+)
+ }
+ }
+ };
+}
+
+/// Internal macro: generates `unpack` and `unpack_directly` for PickN (N >= 2)
+/// that return a tuple.
+macro_rules! impl_pick_unpack_tuple {
+ ($n:ident $($T:ident $val:ident),+) => {
+ impl<$($T,)+ R> $n<$($T,)+ R>
+ where
+ $($T: Pickable,)+
+ {
+ /// Unpacks the builder into a tuple of extracted values.
+ ///
+ /// Returns `Ok((T1, T2, ...))` if all required flags were present.
+ /// Returns `Err(R)` if a required flag was missing and a route was provided via `pick_or_route`.
+ pub fn unpack(self) -> Result<($($T,)+), R> {
+ match self.route {
+ Some(route) => Err(route),
+ None => Ok(($(self.$val,)+)),
+ }
+ }
+
+ /// Unpacks the builder into a tuple of extracted values.
+ ///
+ /// Returns the tuple of extracted values regardless of whether any required flags were missing.
+ /// If a required flag was missing and a route was provided via `pick_or_route`, the default value
+ /// for that type is included in the tuple.
+ pub fn unpack_directly(self) -> ($($T,)+) {
+ ($(self.$val,)+)
+ }
+ }
+ };
+}
+
+define_pick_struct! { Pick1 T1 val_1 T1 val_1 }
+
+impl<T1, R> From<Pick1<T1, R>> for (T1,)
+where
+ T1: Pickable,
+{
+ fn from(pick: Pick1<T1, R>) -> Self {
+ (pick.val_1,)
+ }
+}
+
+impl<T1, R> Pick1<T1, R>
+where
+ T1: Pickable,
+{
+ /// Unpacks the builder into a tuple of extracted values.
+ ///
+ /// Returns `Ok((T1, T2, ...))` if all required flags were present.
+ /// Returns `Err(R)` if a required flag was missing and a route was provided via `pick_or_route`.
+ pub fn unpack(self) -> Result<T1, R> {
+ match self.route {
+ Some(route) => Err(route),
+ None => Ok(self.val_1),
+ }
+ }
+
+ /// Unpacks the builder into a tuple of extracted values.
+ ///
+ /// Returns the tuple of extracted values regardless of whether any required flags were missing.
+ /// If a required flag was missing and a route was provided via `pick_or_route`, the default value
+ /// for that type is included in the tuple.
+ pub fn unpack_directly(self) -> T1 {
+ self.val_1
+ }
+}
+
+define_pick_struct! { Pick2 T2 val_2 T1 val_1, T2 val_2 }
+impl_pick_from_tuple! { Pick2 T1 val_1, T2 val_2 }
+impl_pick_unpack_tuple! { Pick2 T1 val_1, T2 val_2 }
+
+define_pick_struct! { Pick3 T3 val_3 T1 val_1, T2 val_2, T3 val_3 }
+impl_pick_from_tuple! { Pick3 T1 val_1, T2 val_2, T3 val_3 }
+impl_pick_unpack_tuple! { Pick3 T1 val_1, T2 val_2, T3 val_3 }
+
+define_pick_struct! { Pick4 T4 val_4 T1 val_1, T2 val_2, T3 val_3, T4 val_4 }
+impl_pick_from_tuple! { Pick4 T1 val_1, T2 val_2, T3 val_3, T4 val_4 }
+impl_pick_unpack_tuple! { Pick4 T1 val_1, T2 val_2, T3 val_3, T4 val_4 }
+
+define_pick_struct! { Pick5 T5 val_5 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5 }
+impl_pick_from_tuple! { Pick5 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5 }
+impl_pick_unpack_tuple! { Pick5 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5 }
+
+define_pick_struct! { Pick6 T6 val_6 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6 }
+impl_pick_from_tuple! { Pick6 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6 }
+impl_pick_unpack_tuple! { Pick6 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6 }
+
+define_pick_struct! { Pick7 T7 val_7 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7 }
+impl_pick_from_tuple! { Pick7 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7 }
+impl_pick_unpack_tuple! { Pick7 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7 }
+
+define_pick_struct! { Pick8 T8 val_8 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8 }
+impl_pick_from_tuple! { Pick8 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8 }
+impl_pick_unpack_tuple! { Pick8 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8 }
+
+define_pick_struct! { Pick9 T9 val_9 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9 }
+impl_pick_from_tuple! { Pick9 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9 }
+impl_pick_unpack_tuple! { Pick9 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9 }
+
+define_pick_struct! { Pick10 T10 val_10 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10 }
+impl_pick_from_tuple! { Pick10 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10 }
+impl_pick_unpack_tuple! { Pick10 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10 }
+
+define_pick_struct! { Pick11 T11 val_11 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10, T11 val_11 }
+impl_pick_from_tuple! { Pick11 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10, T11 val_11 }
+impl_pick_unpack_tuple! { Pick11 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10, T11 val_11 }
+
+define_pick_struct! { Pick12 T12 val_12 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10, T11 val_11, T12 val_12 }
+impl_pick_from_tuple! { Pick12 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10, T11 val_11, T12 val_12 }
+impl_pick_unpack_tuple! { Pick12 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10, T11 val_11, T12 val_12 }
+
#[doc(hidden)]
macro_rules! impl_pick_structs {
($n:ident $next:ident $next_val:ident $($T:ident $val:ident),+) => {
@@ -338,19 +435,6 @@ macro_rules! impl_pick_structs {
};
}
-define_pick_structs! { Pick1 T1 val_1 T1 val_1 }
-define_pick_structs! { Pick2 T2 val_2 T1 val_1, T2 val_2 }
-define_pick_structs! { Pick3 T3 val_3 T1 val_1, T2 val_2, T3 val_3 }
-define_pick_structs! { Pick4 T4 val_4 T1 val_1, T2 val_2, T3 val_3, T4 val_4 }
-define_pick_structs! { Pick5 T5 val_5 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5 }
-define_pick_structs! { Pick6 T6 val_6 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6 }
-define_pick_structs! { Pick7 T7 val_7 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7 }
-define_pick_structs! { Pick8 T8 val_8 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8 }
-define_pick_structs! { Pick9 T9 val_9 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9 }
-define_pick_structs! { Pick10 T10 val_10 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10 }
-define_pick_structs! { Pick11 T11 val_11 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10, T11 val_11 }
-define_pick_structs! { Pick12 T12 val_12 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10, T11 val_11, T12 val_12 }
-
impl_pick_structs! { Pick1 Pick2 val_2 T1 val_1 }
impl_pick_structs! { Pick2 Pick3 val_3 T1 val_1, T2 val_2 }
impl_pick_structs! { Pick3 Pick4 val_4 T1 val_1, T2 val_2, T3 val_3 }
@@ -363,6 +447,10 @@ impl_pick_structs! { Pick9 Pick10 val_10 T1 val_1, T2 val_2, T3 val_3, T4 val_4,
impl_pick_structs! { Pick10 Pick11 val_11 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10 }
impl_pick_structs! { Pick11 Pick12 val_12 T1 val_1, T2 val_2, T3 val_3, T4 val_4, T5 val_5, T6 val_6, T7 val_7, T8 val_8, T9 val_9, T10 val_10, T11 val_11 }
+// ============================================================================
+// PickableEnum: 为枚举类型提供默认的 Pickable 实现
+// ============================================================================
+
pub trait PickableEnum: EnumTag + Default {}
impl<T> Pickable for T