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}