qubit_argument/argument/constraint/range_constraint.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//! Numeric range constraints.
9
10use crate::argument::ArgumentBound;
11
12/// A numeric range with independently inclusive, exclusive, or absent bounds.
13///
14/// # Examples
15///
16/// ```
17/// use qubit_argument::{ArgumentBound, ArgumentValue, RangeConstraint};
18///
19/// let range = RangeConstraint::new(
20/// ArgumentBound::Included(ArgumentValue::from(1_i32)),
21/// ArgumentBound::Excluded(ArgumentValue::from(5_i32)),
22/// );
23/// assert!(matches!(range.lower(), ArgumentBound::Included(_)));
24/// ```
25///
26/// ```compile_fail
27/// #![deny(unused_must_use)]
28/// use qubit_argument::{ArgumentBound, RangeConstraint};
29///
30/// RangeConstraint::new(ArgumentBound::Unbounded, ArgumentBound::Unbounded);
31/// ```
32#[must_use]
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct RangeConstraint {
35 /// The lower endpoint, including whether it is inclusive, exclusive, or
36 /// absent.
37 lower: ArgumentBound,
38 /// The upper endpoint, including whether it is inclusive, exclusive, or
39 /// absent.
40 upper: ArgumentBound,
41}
42
43impl RangeConstraint {
44 /// Creates a range from its lower and upper bounds.
45 ///
46 /// The bounds are retained exactly as supplied and are not ordered or
47 /// otherwise validated.
48 ///
49 /// # Parameters
50 ///
51 /// * `lower` - The lower endpoint and its inclusion mode.
52 /// * `upper` - The upper endpoint and its inclusion mode.
53 ///
54 /// # Returns
55 ///
56 /// The range containing the supplied bounds.
57 #[inline]
58 pub fn new(lower: ArgumentBound, upper: ArgumentBound) -> Self {
59 Self { lower, upper }
60 }
61
62 /// Returns the lower bound of this range.
63 ///
64 /// # Returns
65 ///
66 /// A reference to the lower endpoint and its inclusion mode.
67 #[must_use = "the caller should inspect the lower range bound"]
68 #[inline]
69 pub fn lower(&self) -> &ArgumentBound {
70 &self.lower
71 }
72
73 /// Returns the upper bound of this range.
74 ///
75 /// # Returns
76 ///
77 /// A reference to the upper endpoint and its inclusion mode.
78 #[must_use = "the caller should inspect the upper range bound"]
79 #[inline]
80 pub fn upper(&self) -> &ArgumentBound {
81 &self.upper
82 }
83
84 /// Consumes this range and returns its lower and upper bounds.
85 ///
86 /// The first tuple element is the lower bound and the second is the upper
87 /// bound.
88 ///
89 /// # Returns
90 ///
91 /// The owned lower and upper bounds, in that order.
92 #[must_use = "the caller should inspect the range bounds"]
93 #[inline]
94 pub fn into_bounds(self) -> (ArgumentBound, ArgumentBound) {
95 let Self { lower, upper } = self;
96 (lower, upper)
97 }
98}