aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-07-15 16:08:10 +0800
committer魏曹先生 <1992414357@qq.com>2026-07-15 16:08:10 +0800
commitc3e990a5c47dc8894899d774a0d89f089adec308 (patch)
tree85e8bdc834cc57bf41694f4c86e5bfd3386fcd09
parent7620fd1d1e9ff4105c2d93c80c73b2c2ec1cbc9a (diff)
refactor: rename `PickerResult` to `PickerArgResult` and add new
`PickerResult` struct
-rw-r--r--mingling_picker/src/infos.rs144
-rw-r--r--mingling_picker/src/pickable.rs6
-rw-r--r--mingling_picker/src/pickable/implements.rs4
-rw-r--r--mingling_picker/src/picker.rs7
-rw-r--r--mingling_picker/src/picker/patterns.rs29
-rw-r--r--mingling_picker/src/picker/result.rs54
6 files changed, 161 insertions, 83 deletions
diff --git a/mingling_picker/src/infos.rs b/mingling_picker/src/infos.rs
index ce9d198..95a54da 100644
--- a/mingling_picker/src/infos.rs
+++ b/mingling_picker/src/infos.rs
@@ -3,12 +3,12 @@ use crate::{Pickable, PickerFlag};
/// Represents the result of parsing or looking up a value.
///
/// This enum is generic over the type being parsed. It models four possible outcomes:
-/// - [`Unparsed`](PickerResult::Unparsed): The value has not yet been parsed (default).
-/// - [`Parsed`](PickerResult::Parsed): The value was successfully parsed into `Type`.
-/// - [`NotFound`](PickerResult::NotFound): The requested value could not be found.
-/// - [`ParseError`](PickerResult::ParseError): The input could not be parsed due to a format error.
+/// - [`Unparsed`](PickerArgResult::Unparsed): The value has not yet been parsed (default).
+/// - [`Parsed`](PickerArgResult::Parsed): The value was successfully parsed into `Type`.
+/// - [`NotFound`](PickerArgResult::NotFound): The requested value could not be found.
+/// - [`ParseError`](PickerArgResult::ParseError): The input could not be parsed due to a format error.
#[derive(Default)]
-pub enum PickerResult<Type> {
+pub enum PickerArgResult<Type> {
/// The value has not yet been parsed (default).
#[default]
Unparsed,
@@ -23,216 +23,216 @@ pub enum PickerResult<Type> {
ParseError,
}
-impl<Type, E> From<Result<Type, E>> for PickerResult<Type> {
- /// Converts a `Result<Type, E>` into a `PickerResult<Type>`.
+impl<Type, E> From<Result<Type, E>> for PickerArgResult<Type> {
+ /// Converts a `Result<Type, E>` into a `PickerArgResult<Type>`.
///
- /// - `Ok(value)` maps to [`Parsed(value)`](PickerResult::Parsed).
- /// - `Err(_)` maps to [`ParseError`](PickerResult::ParseError).
+ /// - `Ok(value)` maps to [`Parsed(value)`](PickerArgResult::Parsed).
+ /// - `Err(_)` maps to [`ParseError`](PickerArgResult::ParseError).
fn from(result: Result<Type, E>) -> Self {
match result {
- Ok(value) => PickerResult::Parsed(value),
- Err(_) => PickerResult::ParseError,
+ Ok(value) => PickerArgResult::Parsed(value),
+ Err(_) => PickerArgResult::ParseError,
}
}
}
-impl<Type> From<Option<Type>> for PickerResult<Type> {
- /// Converts an `Option<Type>` into a `PickerResult<Type>`.
+impl<Type> From<Option<Type>> for PickerArgResult<Type> {
+ /// Converts an `Option<Type>` into a `PickerArgResult<Type>`.
///
- /// - `Some(value)` maps to [`Parsed(value)`](PickerResult::Parsed).
- /// - `None` maps to [`NotFound`](PickerResult::NotFound).
+ /// - `Some(value)` maps to [`Parsed(value)`](PickerArgResult::Parsed).
+ /// - `None` maps to [`NotFound`](PickerArgResult::NotFound).
fn from(option: Option<Type>) -> Self {
match option {
- Some(value) => PickerResult::Parsed(value),
- None => PickerResult::NotFound,
+ Some(value) => PickerArgResult::Parsed(value),
+ None => PickerArgResult::NotFound,
}
}
}
-impl<Type> PickerResult<Type> {
- /// Returns `true` if the result is [`Parsed`](PickerResult::Parsed).
+impl<Type> PickerArgResult<Type> {
+ /// Returns `true` if the result is [`Parsed`](PickerArgResult::Parsed).
///
/// # Examples
///
/// ```
- /// use mingling_picker::PickerResult;
+ /// use mingling_picker::PickerArgResult;
///
- /// let result: PickerResult<i32> = PickerResult::Parsed(42);
+ /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42);
/// assert!(result.is_parsed());
///
- /// let result: PickerResult<i32> = PickerResult::NotFound;
+ /// let result: PickerArgResult<i32> = PickerArgResult::NotFound;
/// assert!(!result.is_parsed());
/// ```
pub fn is_parsed(&self) -> bool {
- matches!(self, PickerResult::Parsed(_))
+ matches!(self, PickerArgResult::Parsed(_))
}
- /// Returns `true` if the result is [`Parsed`](PickerResult::Parsed) or [`NotFound`](PickerResult::NotFound).
+ /// Returns `true` if the result is [`Parsed`](PickerArgResult::Parsed) or [`NotFound`](PickerArgResult::NotFound).
/// i.e., the value exists (was either found or not yet parsed, but not a parse error).
/// Typically indicates the value was "found" in some sense.
///
/// # Examples
///
/// ```
- /// use mingling_picker::PickerResult;
+ /// use mingling_picker::PickerArgResult;
///
- /// let result: PickerResult<i32> = PickerResult::Parsed(42);
+ /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42);
/// assert!(result.is_found());
///
- /// let result: PickerResult<i32> = PickerResult::NotFound;
+ /// let result: PickerArgResult<i32> = PickerArgResult::NotFound;
/// assert!(result.is_found());
///
- /// let result: PickerResult<i32> = PickerResult::ParseError;
+ /// let result: PickerArgResult<i32> = PickerArgResult::ParseError;
/// assert!(!result.is_found());
/// ```
pub fn is_found(&self) -> bool {
- matches!(self, PickerResult::Parsed(_) | PickerResult::NotFound)
+ matches!(self, PickerArgResult::Parsed(_) | PickerArgResult::NotFound)
}
- /// Returns `true` if the result is [`ParseError`](PickerResult::ParseError).
+ /// Returns `true` if the result is [`ParseError`](PickerArgResult::ParseError).
///
/// # Examples
///
/// ```
- /// use mingling_picker::PickerResult;
+ /// use mingling_picker::PickerArgResult;
///
- /// let result: PickerResult<i32> = PickerResult::ParseError;
+ /// let result: PickerArgResult<i32> = PickerArgResult::ParseError;
/// assert!(result.is_err());
///
- /// let result: PickerResult<i32> = PickerResult::Parsed(10);
+ /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(10);
/// assert!(!result.is_err());
/// ```
pub fn is_err(&self) -> bool {
- matches!(self, PickerResult::ParseError)
+ matches!(self, PickerArgResult::ParseError)
}
- /// Returns `Some(&Type)` if [`Parsed`](PickerResult::Parsed), otherwise `None`.
+ /// Returns `Some(&Type)` if [`Parsed`](PickerArgResult::Parsed), otherwise `None`.
///
/// # Examples
///
/// ```
- /// use mingling_picker::PickerResult;
+ /// use mingling_picker::PickerArgResult;
///
- /// let result: PickerResult<i32> = PickerResult::Parsed(42);
+ /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42);
/// assert_eq!(result.parsed(), Some(&42));
///
- /// let result: PickerResult<i32> = PickerResult::NotFound;
+ /// let result: PickerArgResult<i32> = PickerArgResult::NotFound;
/// assert_eq!(result.parsed(), None);
/// ```
pub fn parsed(&self) -> Option<&Type> {
- if let PickerResult::Parsed(value) = self {
+ if let PickerArgResult::Parsed(value) = self {
Some(value)
} else {
None
}
}
- /// Returns the contained [`Parsed`](PickerResult::Parsed) value or panics with a given message.
+ /// Returns the contained [`Parsed`](PickerArgResult::Parsed) value or panics with a given message.
///
/// # Panics
- /// Panics if the value is not [`Parsed`](PickerResult::Parsed), with a message including the provided `msg`.
+ /// Panics if the value is not [`Parsed`](PickerArgResult::Parsed), with a message including the provided `msg`.
///
/// # Examples
///
/// ```should_panic
- /// use mingling_picker::PickerResult;
+ /// use mingling_picker::PickerArgResult;
///
- /// let result: PickerResult<i32> = PickerResult::NotFound;
+ /// let result: PickerArgResult<i32> = PickerArgResult::NotFound;
/// result.expect("expected a parsed value");
/// ```
pub fn expect(self, msg: &str) -> Type {
match self {
- PickerResult::Parsed(value) => value,
+ PickerArgResult::Parsed(value) => value,
_ => panic!("{}", msg),
}
}
- /// Returns the contained [`Parsed`](PickerResult::Parsed) value or panics.
+ /// Returns the contained [`Parsed`](PickerArgResult::Parsed) value or panics.
///
/// # Panics
- /// Panics if the value is not [`Parsed`](PickerResult::Parsed).
+ /// Panics if the value is not [`Parsed`](PickerArgResult::Parsed).
///
/// # Examples
///
/// ```
- /// use mingling_picker::PickerResult;
+ /// use mingling_picker::PickerArgResult;
///
- /// let result: PickerResult<i32> = PickerResult::Parsed(42);
+ /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42);
/// assert_eq!(result.unwrap(), 42);
/// ```
///
/// ```should_panic
- /// use mingling_picker::PickerResult;
+ /// use mingling_picker::PickerArgResult;
///
- /// let result: PickerResult<i32> = PickerResult::NotFound;
+ /// let result: PickerArgResult<i32> = PickerArgResult::NotFound;
/// result.unwrap();
/// ```
pub fn unwrap(self) -> Type {
match self {
- PickerResult::Parsed(value) => value,
- PickerResult::Unparsed => {
- panic!("called `PickerResult::unwrap()` on an `Unparsed` value")
+ PickerArgResult::Parsed(value) => value,
+ PickerArgResult::Unparsed => {
+ panic!("called `PickerArgResult::unwrap()` on an `Unparsed` value")
}
- PickerResult::NotFound => {
- panic!("called `PickerResult::unwrap()` on a `NotFound` value")
+ PickerArgResult::NotFound => {
+ panic!("called `PickerArgResult::unwrap()` on a `NotFound` value")
}
- PickerResult::ParseError => {
- panic!("called `PickerResult::unwrap()` on a `ParseError` value")
+ PickerArgResult::ParseError => {
+ panic!("called `PickerArgResult::unwrap()` on a `ParseError` value")
}
}
}
- /// Returns the contained [`Parsed`](PickerResult::Parsed) value or a provided `default`.
+ /// Returns the contained [`Parsed`](PickerArgResult::Parsed) value or a provided `default`.
///
/// # Examples
///
/// ```
- /// use mingling_picker::PickerResult;
+ /// use mingling_picker::PickerArgResult;
///
- /// let result: PickerResult<i32> = PickerResult::Parsed(42);
+ /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42);
/// assert_eq!(result.unwrap_or(0), 42);
///
- /// let result: PickerResult<i32> = PickerResult::NotFound;
+ /// let result: PickerArgResult<i32> = PickerArgResult::NotFound;
/// assert_eq!(result.unwrap_or(0), 0);
/// ```
pub fn unwrap_or(self, default: Type) -> Type {
match self {
- PickerResult::Parsed(value) => value,
+ PickerArgResult::Parsed(value) => value,
_ => default,
}
}
- /// Returns the contained [`Parsed`](PickerResult::Parsed) value or computes it from a closure.
+ /// Returns the contained [`Parsed`](PickerArgResult::Parsed) value or computes it from a closure.
///
/// # Examples
///
/// ```
- /// use mingling_picker::PickerResult;
+ /// use mingling_picker::PickerArgResult;
///
- /// let result: PickerResult<i32> = PickerResult::Parsed(42);
+ /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42);
/// assert_eq!(result.unwrap_or_else(|| 0), 42);
///
- /// let result: PickerResult<i32> = PickerResult::NotFound;
+ /// let result: PickerArgResult<i32> = PickerArgResult::NotFound;
/// assert_eq!(result.unwrap_or_else(|| 0), 0);
/// ```
pub fn unwrap_or_else<F: FnOnce() -> Type>(self, f: F) -> Type {
match self {
- PickerResult::Parsed(value) => value,
+ PickerArgResult::Parsed(value) => value,
_ => f(),
}
}
- /// Returns the contained [`Parsed`](PickerResult::Parsed) value or the default value of `Type`.
+ /// Returns the contained [`Parsed`](PickerArgResult::Parsed) value or the default value of `Type`.
///
/// # Examples
///
/// ```
- /// use mingling_picker::PickerResult;
+ /// use mingling_picker::PickerArgResult;
///
- /// let result: PickerResult<i32> = PickerResult::Parsed(42);
+ /// let result: PickerArgResult<i32> = PickerArgResult::Parsed(42);
/// assert_eq!(result.unwrap_or_default(), 42);
///
- /// let result: PickerResult<i32> = PickerResult::NotFound;
+ /// let result: PickerArgResult<i32> = PickerArgResult::NotFound;
/// assert_eq!(result.unwrap_or_default(), 0);
/// ```
pub fn unwrap_or_default(self) -> Type
@@ -240,7 +240,7 @@ impl<Type> PickerResult<Type> {
Type: Default,
{
match self {
- PickerResult::Parsed(value) => value,
+ PickerArgResult::Parsed(value) => value,
_ => Type::default(),
}
}
diff --git a/mingling_picker/src/pickable.rs b/mingling_picker/src/pickable.rs
index 8bb012a..808830c 100644
--- a/mingling_picker/src/pickable.rs
+++ b/mingling_picker/src/pickable.rs
@@ -1,4 +1,4 @@
-use crate::{PickerArgInfo, PickerArgs, PickerFlag, PickerFlagAttr, PickerResult};
+use crate::{PickerArgInfo, PickerArgResult, PickerArgs, PickerFlag, PickerFlagAttr};
mod implements;
@@ -64,9 +64,9 @@ where
///
/// # Returns
///
- /// Returns [`PickerResult<Self>`], i.e., the `Self` instance on success, or an appropriate
+ /// Returns [`PickerArgResult<Self>`], i.e., the `Self` instance on success, or an appropriate
/// error message on failure.
- fn pick(raw_strs: &[&str]) -> PickerResult<Self>;
+ fn pick(raw_strs: &[&str]) -> PickerArgResult<Self>;
}
/// Tag phase context, providing the necessary argument and state information for
diff --git a/mingling_picker/src/pickable/implements.rs b/mingling_picker/src/pickable/implements.rs
index cbf22c8..7d19a8c 100644
--- a/mingling_picker/src/pickable/implements.rs
+++ b/mingling_picker/src/pickable/implements.rs
@@ -9,7 +9,7 @@ impl<'a> Pickable<'a> for String {
vec![]
}
- fn pick(_raw_strs: &[&str]) -> crate::PickerResult<Self> {
+ fn pick(_raw_strs: &[&str]) -> crate::PickerArgResult<Self> {
todo!()
}
}
@@ -23,7 +23,7 @@ impl<'a> Pickable<'a> for Vec<String> {
vec![]
}
- fn pick(_raw_strs: &[&str]) -> crate::PickerResult<Self> {
+ fn pick(_raw_strs: &[&str]) -> crate::PickerArgResult<Self> {
todo!()
}
}
diff --git a/mingling_picker/src/picker.rs b/mingling_picker/src/picker.rs
index 99ab2a9..246e013 100644
--- a/mingling_picker/src/picker.rs
+++ b/mingling_picker/src/picker.rs
@@ -5,7 +5,10 @@ mod parse;
mod patterns;
pub use patterns::*;
-use crate::{Pickable, PickerFlag, PickerResult};
+mod result;
+pub use result::*;
+
+use crate::{Pickable, PickerArgResult, PickerFlag};
/// Picker, used to record all states of a parameter parsing
///
@@ -248,7 +251,7 @@ pub trait IntoPicker<'a> {
PickerPattern1 {
args: self.to_picker().args,
flag_1: flag,
- result_1: PickerResult::Unparsed,
+ result_1: PickerArgResult::Unparsed,
default_1: None,
post_1: None,
}
diff --git a/mingling_picker/src/picker/patterns.rs b/mingling_picker/src/picker/patterns.rs
index 4f54f9d..b828849 100644
--- a/mingling_picker/src/picker/patterns.rs
+++ b/mingling_picker/src/picker/patterns.rs
@@ -1,6 +1,6 @@
use mingling_picker_macros::internal_repeat;
-use crate::{Pickable, Picker, PickerArgs, PickerFlag, PickerResult};
+use crate::{Pickable, Picker, PickerArgResult, PickerArgs, PickerFlag};
internal_repeat!(1..=32 => {
#[doc(hidden)]
@@ -10,7 +10,7 @@ internal_repeat!(1..=32 => {
pub args: PickerArgs<'a>,
(
pub flag_$: &'a PickerFlag<'a, T$>,
- pub result_$: PickerResult<T$>,
+ pub result_$: PickerArgResult<T$>,
pub default_$: Option<Box<dyn FnOnce() -> T$>>,
pub post_$: Option<Box<dyn FnOnce(T$) -> T$>>,
+)
@@ -43,6 +43,27 @@ internal_repeat!(1..=32 => {
self
}
+ /// Uses the default value for this flag's type if the flag is not provided.
+ ///
+ /// If the flag is not provided by the user at runtime, the default value for `T$`
+ /// (as defined by the `Default` trait) will be used.
+ ///
+ /// # Example
+ ///
+ /// ```ignore
+ /// let pattern = picker
+ /// .pick(&my_flag)
+ /// .or_default();
+ /// ```
+ #[allow(clippy::type_complexity)]
+ pub fn or_default(mut self) -> Self
+ where
+ T$: Default,
+ {
+ self.default_$ = Some(Box::new(|| T$::default()));
+ self
+ }
+
/// Attaches a post-processing function to this flag.
///
/// After the flag's value is parsed (or defaulted), the given closure will be
@@ -88,7 +109,7 @@ internal_repeat!(1..32 => {
// Current
flag_$+: flag,
- result_$+: PickerResult::Unparsed,
+ result_$+: PickerArgResult::Unparsed,
default_$+: None,
post_$+: None,
@@ -116,7 +137,7 @@ impl<'a> Picker<'a> {
PickerPattern1 {
args: self.args,
flag_1: flag,
- result_1: PickerResult::Unparsed,
+ result_1: PickerArgResult::Unparsed,
default_1: None,
post_1: None,
}
diff --git a/mingling_picker/src/picker/result.rs b/mingling_picker/src/picker/result.rs
new file mode 100644
index 0000000..bd283cf
--- /dev/null
+++ b/mingling_picker/src/picker/result.rs
@@ -0,0 +1,54 @@
+use mingling_picker_macros::internal_repeat;
+
+internal_repeat!(1..=32 => {
+ #[doc(hidden)]
+ pub struct PickerResult$<(T$,+), Route> {
+ /// The route selected by the picker, if any.
+ /// If this is `Some`, the picker chose to follow a route instead of selecting values,
+ /// and all value fields (`v1`, `v2`, ...) will be `None`.
+ ///
+ /// Note: "route" here refers to an alternative path/choice, not a network route.
+ pub route: Option<Route>,
+
+ (
+ #[doc = concat!("The optional value for the ", $, "th type parameter.")]
+ pub v$: Option<T$>,
+ +)
+ }
+});
+
+internal_repeat!(1..=32 => {
+ impl<(T$,+), Route> PickerResult$<(T$,+), Route> {
+ /// Unwraps the result, panicking if a route was selected.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `self.route` is `Some(...)`.
+ pub fn unwrap(self) -> ((T$,+)) {
+ ((self.v$.unwrap(),+))
+ }
+
+ /// Returns the individual option values without checking the route.
+ pub fn unpack(self) -> ((Option<T$>,+)) {
+ ((self.v$,+))
+ }
+
+ /// Converts to a `Result`, returning `Err(route)` if a route was selected,
+ /// or `Ok(values)` otherwise.
+ pub fn to_result(self) -> Result<((T$,+)), Route> {
+ if let Some(r) = self.route {
+ return Err(r);
+ }
+ Ok(self.unwrap())
+ }
+
+ /// Converts to an `Option`, returning `None` if a route was selected,
+ /// or `Some(values)` otherwise.
+ pub fn to_option(self) -> Option<((T$,+))> {
+ if let Some(_) = self.route {
+ return None;
+ }
+ Some(self.unwrap())
+ }
+ }
+});