qubit_argument/argument/option_argument.rs
1// =============================================================================
2// Copyright (c) 2025 - 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Ownership-preserving validation for optional arguments.
9
10use crate::argument::{
11 ArgumentError,
12 ArgumentErrorKind,
13 ArgumentResult,
14 sealed::Sealed,
15};
16
17/// Validates optional arguments without requiring their values to be cloned.
18///
19/// A required value can be extracted with [`Self::require_some`]. Conditional
20/// validation borrows a present value only for the validator call and returns
21/// the original option on success.
22///
23/// The trait is sealed and implemented only for `Option<T>`.
24pub trait OptionArgument<T>: Sealed + Sized {
25 /// Requires this option to contain a value.
26 ///
27 /// A present value is moved out and returned without cloning. An absent
28 /// value returns [`ArgumentErrorKind::Missing`] at `path`.
29 fn require_some(self, path: &str) -> ArgumentResult<T>;
30
31 /// Validates a present value by temporary borrow.
32 ///
33 /// `validator` receives a shared reference when this option is present. A
34 /// successful validator returns the original option without cloning its
35 /// value; it introduces no failure kind of its own and propagates any
36 /// [`ArgumentErrorKind`] returned by `validator` unchanged. An absent
37 /// option is returned without executing `validator`.
38 fn validate_if_some<F>(self, validator: F) -> ArgumentResult<Self>
39 where
40 F: FnOnce(&T) -> ArgumentResult<()>;
41}
42
43impl<T> OptionArgument<T> for Option<T> {
44 /// Extracts a present value or reports that `path` is missing.
45 ///
46 /// The contained value is moved without cloning. An absent option returns
47 /// [`ArgumentErrorKind::Missing`].
48 #[inline]
49 fn require_some(self, path: &str) -> ArgumentResult<T> {
50 match self {
51 Some(value) => Ok(value),
52 None => Err(ArgumentError::new(path, ArgumentErrorKind::Missing)),
53 }
54 }
55
56 /// Borrows and validates a present value, then returns the original option.
57 ///
58 /// A validator error is returned unchanged. When this option is absent,
59 /// `validator` is not executed.
60 #[inline]
61 fn validate_if_some<F>(self, validator: F) -> ArgumentResult<Self>
62 where
63 F: FnOnce(&T) -> ArgumentResult<()>,
64 {
65 if let Some(value) = self.as_ref() {
66 validator(value)?;
67 }
68 Ok(self)
69 }
70}