diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-04-25 21:06:12 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-04-25 21:06:12 +0800 |
| commit | 87bbc88548a4dadbc04998732de4cabfc93f3524 (patch) | |
| tree | bf5f83f33213e835e401e9570fd1932eabb3f3ba | |
| parent | 26e6d3a81af0ab54c63386d68a155d2f5907c137 (diff) | |
Refactor picker to return single values instead of single-element tuples
| -rw-r--r-- | CHANGELOG.md | 29 | ||||
| -rw-r--r-- | docs/pages/3-features/1-parser.md | 2 | ||||
| -rw-r--r-- | mingling/src/parser/picker.rs | 180 |
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 |
