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