1use core::marker::PhantomData;
6
7pub trait SizeTracker: Clone {
9 const INIT: Self;
11 const IS_TRACKING: bool;
13 fn increment(&mut self);
15 fn decrement(&mut self);
17 fn get(&self) -> usize;
19 fn set(&mut self, size: usize);
21 fn swap(&mut self, other: &mut Self);
23}
24
25#[derive(Clone, Copy)]
31#[repr(transparent)]
32pub struct NonTrackingSize(PhantomData<()>);
33impl SizeTracker for NonTrackingSize {
34 const INIT: Self = NonTrackingSize(PhantomData);
35 const IS_TRACKING: bool = false;
36 #[inline]
37 fn increment(&mut self) {}
38 #[inline]
39 fn decrement(&mut self) {}
40 #[inline]
41 fn get(&self) -> usize {
42 panic!("Cannot get the size if we are not tracking the size.")
43 }
44 #[inline]
45 fn set(&mut self, _size: usize) {}
46 #[inline]
47 fn swap(&mut self, _other: &mut Self) {}
48}
49
50#[derive(Clone, Copy)]
55#[repr(transparent)]
56pub struct TrackingSize(usize);
57impl SizeTracker for TrackingSize {
58 const INIT: Self = TrackingSize(0);
59 const IS_TRACKING: bool = true;
60 #[inline]
61 fn increment(&mut self) {
62 self.0 += 1;
63 }
64 #[inline]
65 fn decrement(&mut self) {
66 self.0 -= 1;
67 }
68 #[inline]
69 fn get(&self) -> usize {
70 self.0
71 }
72 #[inline]
73 fn set(&mut self, size: usize) {
74 self.0 = size;
75 }
76 #[inline]
77 fn swap(&mut self, other: &mut Self) {
78 core::mem::swap(&mut self.0, &mut other.0);
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 #[should_panic(expected = "Cannot get the size if we are not tracking the size.")]
88 fn test_non_tracking_size_get_panics() {
89 let tracker = NonTrackingSize::INIT;
90 let _ = tracker.get();
91 }
92
93 #[test]
94 fn test_non_tracking_size_set_swap() {
95 let mut tracker1 = NonTrackingSize::INIT;
96 let mut tracker2 = NonTrackingSize::INIT;
97 tracker1.increment();
98 tracker1.decrement();
99 tracker1.set(10);
100 tracker1.swap(&mut tracker2);
101 assert!(!NonTrackingSize::IS_TRACKING);
102 }
103
104 #[test]
105 fn test_tracking_size_increment_decrement() {
106 let mut tracker = TrackingSize::INIT;
107 assert!(TrackingSize::IS_TRACKING);
108 assert_eq!(tracker.get(), 0);
109 tracker.increment();
110 assert_eq!(tracker.get(), 1);
111 tracker.increment();
112 assert_eq!(tracker.get(), 2);
113 tracker.decrement();
114 assert_eq!(tracker.get(), 1);
115 }
116
117 #[test]
118 fn test_tracking_size_set() {
119 let mut tracker = TrackingSize::INIT;
120 tracker.set(100);
121 assert_eq!(tracker.get(), 100);
122 }
123
124 #[test]
125 fn test_tracking_size_swap() {
126 let mut tracker1 = TrackingSize::INIT;
127 tracker1.set(100);
128 let mut tracker2 = TrackingSize::INIT;
129 tracker2.set(50);
130
131 tracker1.swap(&mut tracker2);
132 assert_eq!(tracker1.get(), 50);
133 assert_eq!(tracker2.get(), 100);
134 }
135}