1
+ // A struct representing a simple counter with a name (using a static string slice)
2
+ struct NamedCounter {
3
+ name : & ' static str ,
4
+ count : u32 ,
5
+ limit : u32 ,
6
+ enabled : bool ,
7
+ }
8
+
9
+ impl NamedCounter {
10
+ // --- Associated Functions (Constructors) ---
11
+
12
+ // Primary constructor
13
+ fn new ( name : & ' static str , limit : u32 ) -> Self {
14
+ NamedCounter {
15
+ name,
16
+ count : 0 ,
17
+ limit,
18
+ enabled : true , // Start enabled by default
19
+ }
20
+ }
21
+
22
+ // Another constructor for a disabled counter
23
+ fn new_disabled ( name : & ' static str , limit : u32 ) -> Self {
24
+ let mut counter = Self :: new ( name, limit) ; // Call the primary constructor
25
+ counter. enabled = false ;
26
+ counter
27
+ }
28
+
29
+ // --- Methods taking &self (Immutable Access) ---
30
+
31
+ // Get the current count
32
+ fn get_count ( & self ) -> u32 {
33
+ self . count
34
+ }
35
+
36
+ // Get the name
37
+ fn get_name ( & self ) -> & ' static str {
38
+ self . name
39
+ }
40
+
41
+ // Get the limit
42
+ fn get_limit ( & self ) -> u32 {
43
+ self . limit
44
+ }
45
+
46
+ // Check if the counter is enabled
47
+ fn is_enabled ( & self ) -> bool {
48
+ self . enabled
49
+ }
50
+
51
+ // Check if the counter has reached its limit
52
+ fn is_at_limit ( & self ) -> bool {
53
+ // Example of calling other &self methods
54
+ self . get_count ( ) >= self . get_limit ( )
55
+ }
56
+
57
+ // --- Methods taking &mut self (Mutable Access) ---
58
+
59
+ // Increment the counter by 1, respecting the limit and enabled status.
60
+ // Returns true if incremented, false otherwise.
61
+ fn increment ( & mut self ) -> bool {
62
+ if !self . enabled {
63
+ // Not enabled, cannot increment
64
+ return false ;
65
+ }
66
+ if self . is_at_limit ( ) { // Calls &self method `is_at_limit`
67
+ // Already at limit, cannot increment
68
+ return false ;
69
+ }
70
+
71
+ // Can increment
72
+ self . count += 1 ;
73
+ true // Return true indicating success
74
+ }
75
+
76
+ // Increment the counter by a specific amount. Clamps at the limit.
77
+ // Returns the actual amount the counter was incremented by.
78
+ fn increment_by ( & mut self , amount : u32 ) -> u32 {
79
+ if !self . enabled {
80
+ return 0 ; // Not enabled, incremented by 0
81
+ }
82
+
83
+ let current_count = self . count ;
84
+ let potential_count = current_count + amount;
85
+
86
+ if potential_count >= self . limit {
87
+ // Clamp to limit
88
+ self . count = self . limit ;
89
+ // Return how much was actually added to reach the limit
90
+ self . limit - current_count
91
+ } else {
92
+ // Increase count by the full amount
93
+ self . count = potential_count;
94
+ amount // Full amount was added
95
+ }
96
+ }
97
+
98
+ // Reset the counter to zero
99
+ fn reset ( & mut self ) {
100
+ self . count = 0 ;
101
+ }
102
+
103
+ // Enable the counter
104
+ fn enable ( & mut self ) {
105
+ self . enabled = true ;
106
+ }
107
+
108
+ // Disable the counter
109
+ fn disable ( & mut self ) {
110
+ self . enabled = false ;
111
+ }
112
+
113
+ // Set a new limit. Clamps count if necessary.
114
+ fn set_limit ( & mut self , new_limit : u32 ) {
115
+ self . limit = new_limit;
116
+ // Clamp count if it now exceeds the new limit
117
+ if self . count > self . limit {
118
+ self . count = self . limit ;
119
+ }
120
+ }
121
+ } // end impl NamedCounter
122
+
123
+
124
+ fn main ( ) {
125
+ // === Test Case 1: Basic Operations ===
126
+ let mut counter1 = NamedCounter :: new ( "Clicks" , 5 ) ;
127
+
128
+ // Initial state assertions
129
+ assert ! ( counter1. get_name( ) == "Clicks" ) ;
130
+ assert ! ( counter1. get_count( ) == 0 ) ;
131
+ assert ! ( counter1. get_limit( ) == 5 ) ;
132
+ assert ! ( counter1. is_enabled( ) ) ;
133
+ assert ! ( !counter1. is_at_limit( ) ) ;
134
+
135
+ // Test increment
136
+ assert ! ( counter1. increment( ) ) ; // Should succeed (returns true)
137
+ assert ! ( counter1. get_count( ) == 1 ) ;
138
+ assert ! ( !counter1. is_at_limit( ) ) ;
139
+
140
+ // Test increment_by
141
+ let added = counter1. increment_by ( 2 ) ;
142
+ assert ! ( added == 2 ) ; // Should have added 2
143
+ assert ! ( counter1. get_count( ) == 3 ) ;
144
+ assert ! ( !counter1. is_at_limit( ) ) ;
145
+
146
+ // Increment to limit
147
+ assert ! ( counter1. increment( ) ) ; // count = 4, returns true
148
+ assert ! ( counter1. get_count( ) == 4 ) ;
149
+ assert ! ( counter1. increment( ) ) ; // count = 5 (at limit), returns true
150
+ assert ! ( counter1. get_count( ) == 5 ) ;
151
+ assert ! ( counter1. is_at_limit( ) ) ;
152
+
153
+ // Try incrementing past limit
154
+ assert ! ( !counter1. increment( ) ) ; // Should fail (returns false)
155
+ assert ! ( counter1. get_count( ) == 5 ) ; // Count should remain 5
156
+ assert ! ( counter1. is_at_limit( ) ) ;
157
+
158
+ // Try increment_by past limit (clamping)
159
+ let added_past_limit = counter1. increment_by ( 3 ) ;
160
+ assert ! ( added_past_limit == 0 ) ; // Added 0 because already at limit 5
161
+ assert ! ( counter1. get_count( ) == 5 ) ;
162
+ assert ! ( counter1. is_at_limit( ) ) ;
163
+
164
+
165
+ // === Test Case 2: Disabling and Enabling ===
166
+ counter1. disable ( ) ;
167
+ assert ! ( !counter1. is_enabled( ) ) ;
168
+ assert ! ( counter1. get_count( ) == 5 ) ; // Count unchanged
169
+
170
+ // Try incrementing while disabled
171
+ assert ! ( !counter1. increment( ) ) ; // Should fail (returns false)
172
+ assert ! ( counter1. get_count( ) == 5 ) ;
173
+
174
+ // Try increment_by while disabled
175
+ let added_while_disabled = counter1. increment_by ( 2 ) ;
176
+ assert ! ( added_while_disabled == 0 ) ; // Added 0
177
+ assert ! ( counter1. get_count( ) == 5 ) ;
178
+
179
+ // Re-enable
180
+ counter1. enable ( ) ;
181
+ assert ! ( counter1. is_enabled( ) ) ;
182
+ assert ! ( !counter1. increment( ) ) ; // Still at limit, should fail (returns false)
183
+ assert ! ( counter1. get_count( ) == 5 ) ;
184
+
185
+
186
+ // === Test Case 3: Changing Limit ===
187
+ counter1. set_limit ( 10 ) ;
188
+ assert ! ( counter1. get_limit( ) == 10 ) ;
189
+ assert ! ( counter1. get_count( ) == 5 ) ; // Count is still 5
190
+ assert ! ( counter1. is_enabled( ) ) ;
191
+ assert ! ( !counter1. is_at_limit( ) ) ; // No longer at limit
192
+
193
+ // Increment now that limit is higher
194
+ assert ! ( counter1. increment( ) ) ; // count = 6, returns true
195
+ assert ! ( counter1. get_count( ) == 6 ) ;
196
+
197
+ // Increment_by with new limit
198
+ let added_new_limit = counter1. increment_by ( 3 ) ; // 6 + 3 = 9
199
+ assert ! ( added_new_limit == 3 ) ; // Added 3
200
+ assert ! ( counter1. get_count( ) == 9 ) ;
201
+ assert ! ( !counter1. is_at_limit( ) ) ;
202
+
203
+ // Increment_by that hits the new limit exactly
204
+ let added_to_limit = counter1. increment_by ( 1 ) ; // 9 + 1 = 10
205
+ assert ! ( added_to_limit == 1 ) ; // Added 1
206
+ assert ! ( counter1. get_count( ) == 10 ) ;
207
+ assert ! ( counter1. is_at_limit( ) ) ;
208
+
209
+ // Increment_by that exceeds new limit (clamping)
210
+ let added_over_limit = counter1. increment_by ( 5 ) ; // Try 10 + 5 -> clamps to 10
211
+ assert ! ( added_over_limit == 0 ) ; // Added 0 because already at limit 10
212
+ assert ! ( counter1. get_count( ) == 10 ) ;
213
+ assert ! ( counter1. is_at_limit( ) ) ;
214
+
215
+ // Lower the limit below the current count
216
+ counter1. set_limit ( 7 ) ;
217
+ assert ! ( counter1. get_limit( ) == 7 ) ;
218
+ assert ! ( counter1. get_count( ) == 7 ) ; // Count should be clamped to new limit
219
+ assert ! ( counter1. is_at_limit( ) ) ;
220
+
221
+ // Try incrementing after clamping
222
+ assert ! ( !counter1. increment( ) ) ; // Should fail (at new limit, returns false)
223
+ assert ! ( counter1. get_count( ) == 7 ) ;
224
+
225
+
226
+ // === Test Case 4: Resetting ===
227
+ counter1. reset ( ) ;
228
+ assert ! ( counter1. get_count( ) == 0 ) ;
229
+ assert ! ( counter1. get_limit( ) == 7 ) ; // Limit unchanged by reset
230
+ assert ! ( counter1. is_enabled( ) ) ; // Enabled status unchanged by reset
231
+ assert ! ( !counter1. is_at_limit( ) ) ;
232
+
233
+
234
+ // === Test Case 5: Disabled Constructor ===
235
+ let mut counter2 = NamedCounter :: new_disabled ( "Skips" , 100 ) ;
236
+
237
+ // Initial state assertions for disabled counter
238
+ assert ! ( counter2. get_name( ) == "Skips" ) ;
239
+ assert ! ( counter2. get_count( ) == 0 ) ;
240
+ assert ! ( counter2. get_limit( ) == 100 ) ;
241
+ assert ! ( !counter2. is_enabled( ) ) ; // Should be disabled
242
+ assert ! ( !counter2. is_at_limit( ) ) ;
243
+
244
+ // Try incrementing while initially disabled
245
+ assert ! ( !counter2. increment( ) ) ; // returns false
246
+ assert ! ( counter2. get_count( ) == 0 ) ;
247
+
248
+ // Enable and increment
249
+ counter2. enable ( ) ;
250
+ assert ! ( counter2. is_enabled( ) ) ;
251
+ assert ! ( counter2. increment( ) ) ; // returns true
252
+ assert ! ( counter2. get_count( ) == 1 ) ;
253
+
254
+
255
+ // === Test Case 6: Edge case with large numbers / saturation ===
256
+ let mut counter3 = NamedCounter :: new ( "OverflowTest" , u32:: MAX ) ;
257
+ assert ! ( counter3. get_count( ) == 0 ) ;
258
+ assert ! ( counter3. get_limit( ) == u32 :: MAX ) ;
259
+
260
+ // Increment by a large amount, but less than limit
261
+ let added_large = counter3. increment_by ( u32:: MAX - 10 ) ;
262
+ assert ! ( added_large == u32 :: MAX - 10 ) ;
263
+ assert ! ( counter3. get_count( ) == u32 :: MAX - 10 ) ;
264
+
265
+ // Increment to exactly the limit
266
+ let added_to_max = counter3. increment_by ( 10 ) ;
267
+ assert ! ( added_to_max == 10 ) ;
268
+ assert ! ( counter3. get_count( ) == u32 :: MAX ) ;
269
+ assert ! ( counter3. is_at_limit( ) ) ;
270
+
271
+ // Try to increment past MAX (should add 0 due to limit check/saturation)
272
+ let added_past_max = counter3. increment_by ( 5 ) ;
273
+ assert ! ( added_past_max == 0 ) ;
274
+ assert ! ( counter3. get_count( ) == u32 :: MAX ) ;
275
+
276
+ // If execution reaches here without panicking, all assertions passed.
277
+ }
0 commit comments