Skip to main content

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}