Skip to main content

qubit_argument/argument/
condition.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! # Condition Argument Validation
11//!
12//! Provides general condition validation functionality.
13//!
14
15use super::argument_error::{
16    ArgumentError,
17    ArgumentResult,
18};
19
20/// Check if an argument condition is true
21///
22/// This is the most basic validation function for checking arbitrary boolean conditions.
23///
24/// # Parameters
25///
26/// * `condition` - The condition to check
27///
28/// # Returns
29///
30/// Returns `Ok(())` if the condition is true, otherwise returns an error
31///
32/// # Examples
33///
34/// ```rust
35/// use qubit_argument::argument::check_argument;
36///
37/// let age = 25;
38/// assert!(check_argument(age >= 18).is_ok());
39/// assert!(check_argument(age < 18).is_err());
40/// ```
41///
42///
43#[inline]
44pub fn check_argument(condition: bool) -> ArgumentResult<()> {
45    if !condition {
46        return Err(ArgumentError::new("Argument condition not satisfied"));
47    }
48    Ok(())
49}
50
51/// Check if an argument condition is true and provide a custom error message
52///
53/// # Parameters
54///
55/// * `condition` - The condition to check
56/// * `message` - Error message when condition is not satisfied
57///
58/// # Returns
59///
60/// Returns `Ok(())` if the condition is true, otherwise returns an error with custom message
61///
62/// # Examples
63///
64/// ```rust
65/// use qubit_argument::argument::check_argument_with_message;
66///
67/// let count = 5;
68/// let result = check_argument_with_message(
69///     count > 0,
70///     "Count must be positive"
71/// );
72/// assert!(result.is_ok());
73/// ```
74///
75///
76#[inline]
77pub fn check_argument_with_message(condition: bool, message: &str) -> ArgumentResult<()> {
78    if !condition {
79        return Err(ArgumentError::new(message));
80    }
81    Ok(())
82}
83
84/// Check if an argument condition is true and use formatted message
85///
86/// # Parameters
87///
88/// * `condition` - The condition to check
89/// * `format` - Format string
90/// * `args` - Format arguments
91///
92/// # Returns
93///
94/// Returns `Ok(())` if the condition is true, otherwise returns formatted error message
95///
96/// # Examples
97///
98/// ```rust
99/// use qubit_argument::argument::check_argument_fmt;
100///
101/// let value = 150;
102/// let max = 100;
103/// let result = check_argument_fmt(
104///     value <= max,
105///     format!("Value {} exceeds maximum {}", value, max)
106/// );
107/// assert!(result.is_err());
108/// ```
109///
110///
111#[inline]
112pub fn check_argument_fmt(condition: bool, message: String) -> ArgumentResult<()> {
113    if !condition {
114        return Err(ArgumentError::new(message));
115    }
116    Ok(())
117}
118
119/// Check if a state condition is true
120///
121/// Used to validate the state of an object or system. Similar to `check_argument` but semantically for state checking.
122///
123/// # Parameters
124///
125/// * `condition` - The state condition to check
126///
127/// # Returns
128///
129/// Returns `Ok(())` if the condition is true, otherwise returns an error
130///
131/// # Examples
132///
133/// ```rust
134/// use qubit_argument::argument::check_state;
135///
136/// let is_initialized = true;
137/// assert!(check_state(is_initialized).is_ok());
138/// ```
139///
140///
141#[inline]
142pub fn check_state(condition: bool) -> ArgumentResult<()> {
143    if !condition {
144        return Err(ArgumentError::new("State condition not satisfied"));
145    }
146    Ok(())
147}
148
149/// Check if a state condition is true and provide a custom error message
150///
151/// # Parameters
152///
153/// * `condition` - The state condition to check
154/// * `message` - Error message when condition is not satisfied
155///
156/// # Returns
157///
158/// Returns `Ok(())` if the condition is true, otherwise returns an error with custom message
159///
160/// # Examples
161///
162/// ```rust
163/// use qubit_argument::argument::check_state_with_message;
164///
165/// let is_connected = false;
166/// let result = check_state_with_message(
167///     is_connected,
168///     "Connection must be established first"
169/// );
170/// assert!(result.is_err());
171/// ```
172///
173///
174#[inline]
175pub fn check_state_with_message(condition: bool, message: &str) -> ArgumentResult<()> {
176    if !condition {
177        return Err(ArgumentError::new(message));
178    }
179    Ok(())
180}
181
182/// Check boundary conditions
183///
184/// Validates that offset and length are within valid range to prevent array bounds errors.
185///
186/// # Parameters
187///
188/// * `offset` - Starting offset
189/// * `length` - Length to access
190/// * `total_length` - Total length
191///
192/// # Returns
193///
194/// Returns `Ok(())` if boundaries are valid, otherwise returns an error
195///
196/// # Examples
197///
198/// ```rust
199/// use qubit_argument::argument::check_bounds;
200///
201/// let buffer_len = 100;
202/// assert!(check_bounds(10, 20, buffer_len).is_ok());
203/// assert!(check_bounds(90, 20, buffer_len).is_err());
204/// ```
205///
206///
207#[inline]
208pub fn check_bounds(offset: usize, length: usize, total_length: usize) -> ArgumentResult<()> {
209    if offset > total_length {
210        return Err(ArgumentError::new(format!(
211            "Offset {} exceeds total length {}",
212            offset, total_length
213        )));
214    }
215
216    if length > total_length - offset {
217        return Err(ArgumentError::new(format!(
218            "Length {} starting from offset {} exceeds total length {}",
219            length, offset, total_length
220        )));
221    }
222
223    Ok(())
224}
225
226/// Check if an index is within valid range
227///
228/// # Parameters
229///
230/// * `index` - The index to check
231/// * `size` - Collection size
232///
233/// # Returns
234///
235/// Returns the index itself if valid, otherwise returns an error
236///
237/// # Examples
238///
239/// ```rust
240/// use qubit_argument::argument::check_element_index;
241///
242/// let list_size = 10;
243/// assert_eq!(check_element_index(5, list_size).unwrap(), 5);
244/// assert!(check_element_index(10, list_size).is_err());
245/// ```
246///
247///
248#[inline]
249pub fn check_element_index(index: usize, size: usize) -> ArgumentResult<usize> {
250    if index >= size {
251        return Err(ArgumentError::new(format!(
252            "Index {} out of range [0, {})",
253            index, size
254        )));
255    }
256    Ok(index)
257}
258
259/// Check if a position index is within valid range
260///
261/// Position index can equal size (for insertion operations).
262///
263/// # Parameters
264///
265/// * `index` - The position index to check
266/// * `size` - Collection size
267///
268/// # Returns
269///
270/// Returns the index itself if valid, otherwise returns an error
271///
272/// # Examples
273///
274/// ```rust
275/// use qubit_argument::argument::check_position_index;
276///
277/// let list_size = 10;
278/// assert_eq!(check_position_index(10, list_size).unwrap(), 10); // Can equal size
279/// assert!(check_position_index(11, list_size).is_err());
280/// ```
281///
282///
283#[inline]
284pub fn check_position_index(index: usize, size: usize) -> ArgumentResult<usize> {
285    if index > size {
286        return Err(ArgumentError::new(format!(
287            "Position index {} out of range [0, {}]",
288            index, size
289        )));
290    }
291    Ok(index)
292}
293
294/// Check if a position index range is valid
295///
296/// # Parameters
297///
298/// * `start` - Start index
299/// * `end` - End index
300/// * `size` - Collection size
301///
302/// # Returns
303///
304/// Returns `Ok(())` if the range is valid, otherwise returns an error
305///
306/// # Examples
307///
308/// ```rust
309/// use qubit_argument::argument::check_position_indexes;
310///
311/// let list_size = 10;
312/// assert!(check_position_indexes(2, 5, list_size).is_ok());
313/// assert!(check_position_indexes(5, 2, list_size).is_err()); // start > end
314/// ```
315///
316///
317#[inline]
318pub fn check_position_indexes(start: usize, end: usize, size: usize) -> ArgumentResult<()> {
319    if start > end {
320        return Err(ArgumentError::new(format!(
321            "Start index {} is greater than end index {}",
322            start, end
323        )));
324    }
325
326    if end > size {
327        return Err(ArgumentError::new(format!(
328            "End index {} out of range [0, {}]",
329            end, size
330        )));
331    }
332
333    Ok(())
334}