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}