1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/// A trait defining an `is_empty` method for various types.
///
/// This trait provides a generic way to determine if a value of a given type
/// can be considered "empty". The definition of "empty" is context-specific
/// and is implemented for common Rust types like collections, strings,
/// booleans, and numeric types.
///
/// # Implementations:
/// - `String` and `&str`: Returns `true` if the string contains no characters.
/// - `Vec<T>`: Returns `true` if the vector contains no elements.
/// - `bool`: Returns `true` if the boolean value is `false`.
/// - Numeric types (integers and floats): Returns `true` if the value is `0` or `0.0`.
/// - `Option<T>`: Returns `true` if the `Option` is `None` or if `Some(value)` and `value` is `is_empty()`.
///
/// # Usage
/// This trait is particularly useful for filtering or compacting collections
/// where the concept of "emptiness" applies to the elements.
// --- Implementations for common Rust types ---
/// Implements `IsEmpty` for `String`.
///
/// A `String` is considered empty if its length is zero.
///
/// # Performance
/// This implementation directly calls the `String::is_empty()` method,
/// which is an efficient O(1) operation.
/// Implements `IsEmpty` for string slices (`&str`).
///
/// A `&str` is considered empty if its length is zero.
///
/// # Performance
/// This implementation directly calls the `&str::is_empty()` method,
/// which is an efficient O(1) operation.
/// Implements `IsEmpty` for dynamic vectors (`Vec<T>`).
///
/// A `Vec<T>` is considered empty if it contains no elements.
///
/// # Type Parameters
/// - `T`: The type of elements within the vector.
///
/// # Performance
/// This implementation directly calls the `Vec::is_empty()` method,
/// which is an efficient O(1) operation.
/// Implements `IsEmpty` for boolean values (`bool`).
///
/// A `bool` is considered empty if its value is `false`.
/// This aligns with the common interpretation of `false` as "nothing" or "non-existent"
/// in a logical context.
///
/// # Performance
/// This is a direct comparison, an efficient O(1) operation.
/// Implements `IsEmpty` for `Option<T>`.
///
/// An `Option<T>` is considered empty if it is `None` or if it is `Some(value)`
/// and the `value` itself is `is_empty()`. This provides a recursive check for emptiness.
///
/// # Type Parameters
/// - `T`: The type contained within the `Option`, which must also implement `IsEmpty`.
///
/// # Performance
/// The performance depends on the `is_empty()` implementation of the inner type `T`.
/// A macro to automatically implement `IsEmpty` for various numeric types.
///
/// This macro reduces boilerplate by generating `IsEmpty` implementations
/// for both integer and floating-point types.
///
/// # How "Empty" is Defined for Numerics
/// - For integers, a value is considered empty if it is `0`.
/// - For floating-point numbers, a value is considered empty if it is `0.0`.
///
/// # Arguments
/// - `ints`: A comma-separated list of integer types (e.g., `i8, u16`).
/// - `floats`: A comma-separated list of floating-point types (e.g., `f32, f64`).
///
/// # Performance
/// All generated implementations are direct comparisons, which are efficient O(1) operations.
// Apply the macro to a comprehensive list of standard numeric types.
impl_is_empty_for_numerics!;
/// ๐ฎ Compacts a mutable vector by removing all elements that are considered "empty".
///
/// This function iterates through the vector and retains only those elements
/// for which the `is_empty()` method returns `false`.
///
/// # Type Parameters
/// - `T`: The type of elements in the vector. Must implement the [`IsEmpty`] trait.
///
/// # Arguments
/// - `values`: A mutable reference to the `Vec<T>` to be compacted.
///
/// # Behavior
/// - Modifies the input vector **in-place**, removing elements for which `is_empty()` is true.
/// - If the vector is initially empty, it remains empty.
/// - If all elements are empty, the result is an empty vector.
/// - If no elements are empty, the vector remains unchanged.
///
/// # Performance
/// - Runs in **O(n)** time, where `n` is the number of elements.
/// - Uses `Vec::retain()` under the hood โ efficient, no reallocations.
/// - Each element is checked once. For types where `is_empty()` is O(1), overall cost is linear and very fast.
///
/// # Supported Types
/// This function works with any type that implements the `IsEmpty` trait, such as:
/// - `String`, `&str`
/// - All integers and floats (`0`, `0.0` are "empty")
/// - `bool` (`false` is "empty")
/// - `Vec<T>` where `T: IsEmpty`
/// - `Option<T>` where `T: IsEmpty`
///
/// # Examples
///
/// ### ๐ Remove empty strings
/// ```
/// use pencil_box::array::compact::compact;
/// use pencil_box::traits::IsEmpty;
///
/// let mut items = vec!["hello".to_string(), "".to_string(), "world".to_string()];
/// compact(&mut items);
/// assert_eq!(items, vec!["hello", "world"]);
/// ```
///
/// ### ๐ฆ Remove empty vectors
/// ```
/// let mut data = vec![vec![1], vec![], vec![2, 3]];
/// compact(&mut data);
/// assert_eq!(data, vec![vec![1], vec![2, 3]]);
/// ```
///
/// ### ๐งน Remove zero values
/// ```
/// let mut nums = vec![0, 1, 0, 2, 3];
/// compact(&mut nums);
/// assert_eq!(nums, vec![1, 2, 3]);
/// ```
///
/// ### โ Remove `None` and empty `Some`s
/// ```
/// let mut opts = vec![Some("hi"), None, Some("")];
/// compact(&mut opts);
/// assert_eq!(opts, vec![Some("hi")]);
/// ```
///
/// ### ๐ Leave non-empty values untouched
/// ```
/// let mut flags = vec![true, true, true];
/// compact(&mut flags);
/// assert_eq!(flags, vec![true, true, true]);
/// ```
///
/// ### ๐ญ No-op on empty input
/// ```
/// let mut empty: Vec<String> = vec![];
/// compact(&mut empty);
/// assert!(empty.is_empty());
/// ```