cjtoolkit_structured_validator/common/
flag_error.rs

1//! This module contains a function for flagging an error in a `Result` type.
2//!
3//! # Use Case
4//! - Propagating errors in a `Result` type.
5//! - Tracking whether an error occurred in a `Result` type.
6
7/// Flags an error while propagating the result of a `Result` type.
8///
9/// This function takes a mutable boolean reference (`flag`) and a `Result` value.
10/// If the `Result` is an error (`Err`), it sets the `flag` to `true`, allowing the
11/// caller to track if an error occurred without consuming the `Result`.
12///
13/// The original `Result` is then returned unchanged.
14///
15/// # Type Parameters
16/// - `T`: The type contained in the `Ok` variant of the `Result`.
17/// - `E`: The type contained in the `Err` variant of the `Result`.
18///
19/// # Arguments
20/// - `flag`: A mutable reference to a boolean flag that will be set to `true`
21///   if the `Result` contains an error.
22/// - `result`: The `Result` to check for an error.
23///
24/// # Returns
25/// - Returns the provided `Result` value for further use or propagation.
26///
27/// # Examples
28/// ```rust
29/// use cjtoolkit_structured_validator::common::flag_error::flag_error;
30/// let mut error_occurred = false;
31/// let result: Result<i32, &str> = Err("An error occurred");
32///
33/// let checked_result = flag_error(&mut error_occurred, result);
34///
35/// assert!(error_occurred); // Flag has been set to true.
36/// assert!(checked_result.is_err()); // The result is returned unchanged.
37/// ```
38///
39/// ```rust
40/// use cjtoolkit_structured_validator::common::flag_error::flag_error;
41/// let mut error_occurred = false;
42/// let result: Result<i32, &str> = Ok(42);
43///
44/// let checked_result = flag_error(&mut error_occurred, result);
45///
46/// assert!(!error_occurred); // Flag remains false.
47/// assert_eq!(checked_result, Ok(42)); // The result is returned unchanged.
48/// ```
49pub fn flag_error<T, E>(flag: &mut bool, result: Result<T, E>) -> Result<T, E> {
50    if result.is_err() {
51        *flag = true;
52    }
53    result
54}
55
56/// A structure that provides a counter for managing flags or similar use cases.
57///
58/// The `FlagCounter` struct is designed to keep track of an incrementable count,
59/// typically to represent or manage a counter for specific operations or states.
60///
61/// # Fields
62///
63/// * `count`:
64///   - The current value of the counter.
65///   - Represented as a `usize` (unsigned integer).
66pub struct FlagCounter {
67    count: usize,
68}
69
70impl FlagCounter {
71    /// Creates and returns a new instance of the struct with the `count` field initialized to 0.
72    ///
73    /// # Returns
74    ///
75    /// A new instance of the struct.
76    pub fn new() -> Self {
77        Self { count: 0 }
78    }
79
80    /// Checks the provided `Result`, increments an internal error count if it is `Err`, and returns the `Result` unchanged.
81    ///
82    /// # Type Parameters
83    /// - `T`: The type of the value inside the `Ok` variant of the `Result`.
84    /// - `E`: The type of the error inside the `Err` variant of the `Result`.
85    ///
86    /// # Arguments
87    /// - `result`: A `Result` value to be checked for an error.
88    ///
89    /// # Behavior
90    /// - If the provided `Result` is `Err`, the method increments the internal error count (`self.count`).
91    /// - Regardless of whether it is `Ok` or `Err`, the original `Result` is returned unchanged.
92    ///
93    /// # Returns
94    /// Returns the provided `Result` value as-is.
95    pub fn check<T, E>(&mut self, result: Result<T, E>) -> Result<T, E> {
96        if result.is_err() {
97            self.count += 1;
98        }
99        result
100    }
101
102    /// Checks if the current object is flagged.
103    ///
104    /// # Returns
105    /// * `true` - If the `count` property of the object is greater than 0.
106    /// * `false` - If the `count` property of the object is 0 or less.
107    ///
108    /// # Usage
109    /// This function acts as a flagging mechanism. For example,
110    /// it can be used to determine if there are any active or positive counts that
111    /// signify certain conditions.
112    ///
113    /// # Note
114    /// The `count` field must be initialized appropriately before calling this function.
115    pub fn is_flagged(&self) -> bool {
116        self.count > 0
117    }
118
119    /// Returns the current value of the `count` field.
120    ///
121    /// # Returns
122    /// * `usize` - The value of the `count` field.
123    pub fn get_count(&self) -> usize {
124        self.count
125    }
126}
127
128#[cfg(test)]
129mod tests {
130    use super::*;
131
132    #[test]
133    fn test_flag_error() {
134        let mut flag = false;
135        let result: Result<(), ()> = flag_error(&mut flag, Ok(()));
136        assert!(result.is_ok());
137        assert!(!flag);
138    }
139
140    #[test]
141    fn test_flag_error_err() {
142        let mut flag = false;
143        let result: Result<(), ()> = flag_error(&mut flag, Err(()));
144        assert!(result.is_err());
145        assert!(flag);
146    }
147}