1use std::cell::UnsafeCell;
2use std::fmt::{Debug, Display};
3use std::hash::{Hash, Hasher};
4use std::ops::{Deref, DerefMut};
5
6pub struct Repr<T: Debug, I: Fn(&T) -> bool> {
10 pub(crate) inner: UnsafeCell<T>,
11 invariant: I,
12 violation_message: &'static str,
13}
14impl<T: Debug, I: Fn(&T) -> bool> Repr<T, I> {
15 pub const fn new(inner: T, invariant: I) -> Self {
26 Self {
27 inner: UnsafeCell::new(inner),
28 invariant,
29 violation_message: "Invariant violated",
30 }
31 }
32 pub const fn with_msg(inner: T, invariant: I, violation_message: &'static str) -> Self {
44 Self {
45 inner: UnsafeCell::new(inner),
46 invariant,
47 violation_message,
48 }
49 }
50 #[inline]
61 pub fn read(&self) -> &T {
62 unsafe { &*self.inner.get() }
65 }
66 #[inline]
99 pub fn write(&mut self) -> ReprMutator<T, I> {
100 ReprMutator {
102 repr: self,
103 }
104 }
105 #[inline]
115 pub fn into_inner(self) -> T {
116 self.inner.into_inner()
117 }
118 pub(crate) fn check(&mut self) {
119 let data = self.inner.get_mut();
120 assert!((self.invariant)(data), "{}\nState was: {:?}", self.violation_message, data);
121 for _ in 0..10 {
123 debug_assert!((self.invariant)(data), "Invariants should be deterministic! The invariant function for this Repr is not deterministic.");
124 }
125 }
126}
127
128unsafe impl<T: Debug + Sync, I: Fn(&T) -> bool + Sync> Sync for Repr<T, I> {}
133unsafe impl<T: Debug + Send, I: Fn(&T) -> bool + Send> Send for Repr<T, I> {}
136
137impl<T: Debug, I: Fn(&T) -> bool> AsRef<T> for Repr<T, I> {
138 #[inline]
139 fn as_ref(&self) -> &T {
140 self.read()
141 }
142}
143
144impl<T: Debug + Clone, I: Fn(&T) -> bool + Clone> Clone for Repr<T, I> {
145 fn clone(&self) -> Self {
146 let inner = self.read().clone();
147 Self::with_msg(inner, self.invariant.clone(), self.violation_message)
148 }
149}
150impl<T: Debug + Hash, I: Fn(&T) -> bool> Hash for Repr<T, I> {
151 fn hash<H: Hasher>(&self, state: &mut H) {
152 self.read().hash(state);
153 }
154}
155impl<T: Debug + PartialEq, I: Fn(&T) -> bool> PartialEq for Repr<T, I> {
156 fn eq(&self, other: &Self) -> bool {
157 self.read() == other.read()
158 }
159}
160impl<T: Debug + Eq, I: Fn(&T) -> bool> Eq for Repr<T, I> {}
161
162impl<T: Debug, I: Fn(&T) -> bool> Debug for Repr<T, I> {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 write!(f, "Repr({:?})", self.read())
165 }
166}
167impl <T: Debug + Display, I: Fn(&T) -> bool> Display for Repr<T, I> {
168 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
169 write!(f, "{}", self.read())
170 }
171}
172
173#[repr(transparent)]
174pub struct ReprMutator<'a, T: Debug, I: Fn(&T) -> bool> {
175 repr: &'a mut Repr<T, I>,
177}
178impl<'a, T: Debug, I: Fn(&T) -> bool> Deref for ReprMutator<'a, T, I> {
179 type Target = T;
180 fn deref(&self) -> &Self::Target {
181 unsafe { &*self.repr.inner.get() }
184 }
185}
186impl<'a, T: Debug, I: Fn(&T) -> bool> DerefMut for ReprMutator<'a, T, I> {
187 fn deref_mut(&mut self) -> &mut Self::Target {
188 self.repr.inner.get_mut()
189 }
190}
191impl<T: Debug, I: Fn(&T) -> bool> Drop for ReprMutator<'_, T, I> {
192 fn drop(&mut self) {
193 self.repr.check();
194 }
195}
196
197impl<'a, T: Debug + Hash> Hash for ReprMutator<'a, T, fn(&T) -> bool> {
200 fn hash<H: Hasher>(&self, state: &mut H) {
201 self.deref().hash(state);
202 }
203}
204impl<'a, T: Debug + PartialEq> PartialEq for ReprMutator<'a, T, fn(&T) -> bool> {
205 fn eq(&self, other: &Self) -> bool {
206 self.deref() == other.deref()
207 }
208}
209impl<'a, T: Debug + Eq> Eq for ReprMutator<'a, T, fn(&T) -> bool> {}
210impl<'a, T: Debug + PartialOrd> PartialOrd for ReprMutator<'a, T, fn(&T) -> bool> {
211 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
212 self.deref().partial_cmp(other.deref())
213 }
214}
215impl<'a, T: Debug + Ord> Ord for ReprMutator<'a, T, fn(&T) -> bool> {
216 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
217 self.deref().cmp(other.deref())
218 }
219}