version_track/
versioned.rs1use std::ops::{Deref, DerefMut};
2
3use crate::Version;
4
5#[derive(Debug)]
7pub struct Versioned<T> {
8 value: T,
9 version: Version,
10}
11
12impl<T> Versioned<T> {
13 #[inline]
15 pub fn new(value: T) -> Self {
16 Self::with_version(value, Version::new())
17 }
18
19 #[inline]
21 pub fn with_version(value: T, version: Version) -> Self {
22 Self { value, version }
23 }
24
25 #[inline]
27 pub fn version(&self) -> Version {
28 self.version
29 }
30}
31
32impl<T> Default for Versioned<T>
33where T: Default
34{
35 #[inline]
37 fn default() -> Self {
38 Self::new(T::default())
39 }
40}
41
42#[allow(clippy::expl_impl_clone_on_copy)]
43impl<T> Clone for Versioned<T>
44where T: Clone
45{
46 #[inline]
49 fn clone(&self) -> Self {
50 Self::new(self.value.clone())
51 }
52}
53
54impl<T> Copy for Versioned<T> where T: Copy {}
55
56impl<T> Deref for Versioned<T> {
57 type Target = T;
58
59 #[must_use]
61 #[inline]
62 fn deref(&self) -> &Self::Target {
63 &self.value
64 }
65}
66
67impl<T> AsRef<T> for Versioned<T> {
68 #[must_use]
70 #[inline]
71 fn as_ref(&self) -> &T {
72 self
73 }
74}
75
76impl<T> DerefMut for Versioned<T> {
77 #[must_use]
79 #[inline]
80 fn deref_mut(&mut self) -> &mut Self::Target {
81 self.version.increment();
82 &mut self.value
83 }
84}
85
86impl<T> AsMut<T> for Versioned<T> {
87 #[must_use]
89 #[inline]
90 fn as_mut(&mut self) -> &mut T {
91 self
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98 use crate::SENTINEL_VERSION;
99
100 #[derive(Debug, PartialEq, Copy, Clone)]
101 struct TestType {
102 value: usize,
103 }
104
105 impl Default for TestType {
106 fn default() -> Self {
107 Self { value: 42 }
108 }
109 }
110
111 #[test]
112 fn new() {
113 let versioned_value = Versioned::new(42);
114 assert_eq!(*versioned_value, 42);
115 }
116
117 #[test]
118 fn with_version() {
119 let versioned_value = Versioned::with_version(42, SENTINEL_VERSION);
120 assert_eq!(*versioned_value, 42);
121 assert_eq!(versioned_value.version(), SENTINEL_VERSION);
122 }
123
124 #[test]
125 fn version() {
126 let versioned_value = Versioned::with_version(42, SENTINEL_VERSION);
127 assert_eq!(versioned_value.version(), SENTINEL_VERSION);
128 }
129
130 #[test]
131 fn default_impl() {
132 let versioned_value = Versioned::<TestType>::default();
133 assert_eq!(*versioned_value, TestType::default());
134 }
135
136 #[test]
137 #[allow(clippy::clone_on_copy)]
138 fn clone_impl() {
139 let versioned_value = Versioned::new(TestType::default());
140 let initial_version = versioned_value.version();
141 let cloned = versioned_value.clone();
142 assert_eq!(*cloned, *versioned_value);
143 assert_ne!(initial_version, cloned.version());
144 }
145
146 #[test]
147 fn deref() {
148 let versioned_value = Versioned::new(TestType::default());
149 let initial_version = versioned_value.version();
150 assert_eq!(&*versioned_value, &TestType::default());
151 assert_eq!(initial_version, versioned_value.version());
152 }
153
154 #[test]
155 fn as_ref() {
156 let versioned_value = Versioned::new(TestType::default());
157 let initial_version = versioned_value.version();
158 assert_eq!(versioned_value.as_ref(), &TestType::default());
159 assert_eq!(initial_version, versioned_value.version());
160 }
161
162 #[test]
163 fn deref_mut() {
164 let mut versioned_value = Versioned::new(TestType::default());
165 let initial_version = versioned_value.version();
166 let value = &mut *versioned_value;
167 value.value = 99;
168 assert_eq!(*versioned_value, TestType { value: 99 });
169 assert_ne!(initial_version, versioned_value.version());
170 }
171
172 #[test]
173 fn as_mut() {
174 let mut versioned_value = Versioned::new(TestType::default());
175 let initial_version = versioned_value.version();
176 let value = versioned_value.as_mut();
177 value.value = 99;
178 assert_eq!(*versioned_value, TestType { value: 99 });
179 assert_ne!(initial_version, versioned_value.version());
180 }
181}