1use std::marker::PhantomData;
2use std::ops::{Deref, DerefMut, Index, IndexMut};
3
4use serde::Serialize;
5
6use crate::{Adapter, Mutation, MutationKind, Observe, Observer};
7
8pub struct SnapshotObserver<'i, T> {
71 ptr: *mut T,
72 snapshot: T,
73 phantom: PhantomData<&'i mut T>,
74}
75
76impl<'i, T: Clone + PartialEq> Observer<'i> for SnapshotObserver<'i, T> {
77 #[inline]
78 fn observe(value: &'i mut T) -> Self {
79 Self {
80 ptr: value as *mut T,
81 snapshot: value.clone(),
82 phantom: PhantomData,
83 }
84 }
85
86 fn collect<A: Adapter>(this: Self) -> Result<Option<Mutation<A>>, A::Error>
87 where
88 T: Serialize,
89 {
90 Ok(if this.snapshot != *this {
91 Some(Mutation {
92 path_rev: vec![],
93 operation: MutationKind::Replace(A::serialize_value(&*this)?),
94 })
95 } else {
96 None
97 })
98 }
99}
100
101impl<'i, T> Deref for SnapshotObserver<'i, T> {
102 type Target = T;
103 fn deref(&self) -> &Self::Target {
104 unsafe { &*self.ptr }
105 }
106}
107
108impl<'i, T> DerefMut for SnapshotObserver<'i, T> {
109 fn deref_mut(&mut self) -> &mut Self::Target {
110 unsafe { &mut *self.ptr }
111 }
112}
113
114impl<'i, T: Index<U>, U> Index<U> for SnapshotObserver<'i, T> {
115 type Output = T::Output;
116 fn index(&self, index: U) -> &Self::Output {
117 (**self).index(index)
118 }
119}
120
121impl<'i, T: IndexMut<U>, U> IndexMut<U> for SnapshotObserver<'i, T> {
122 fn index_mut(&mut self, index: U) -> &mut Self::Output {
123 (**self).index_mut(index)
124 }
125}
126
127impl<'i, T: PartialEq<U>, U: ?Sized> PartialEq<U> for SnapshotObserver<'i, T> {
128 fn eq(&self, other: &U) -> bool {
129 (**self).eq(other)
130 }
131}
132
133impl<'i, T: PartialOrd<U>, U: ?Sized> PartialOrd<U> for SnapshotObserver<'i, T> {
134 fn partial_cmp(&self, other: &U) -> Option<std::cmp::Ordering> {
135 (**self).partial_cmp(other)
136 }
137}
138
139macro_rules! impl_assign_ops {
140 ($($trait:ident => $method:ident),* $(,)?) => {
141 $(
142 impl<'i, T: ::std::ops::$trait<U>, U> ::std::ops::$trait<U> for SnapshotObserver<'i, T> {
143 fn $method(&mut self, rhs: U) {
144 (**self).$method(rhs);
145 }
146 }
147 )*
148 };
149}
150
151impl_assign_ops! {
152 AddAssign => add_assign,
153 SubAssign => sub_assign,
154 MulAssign => mul_assign,
155 DivAssign => div_assign,
156 RemAssign => rem_assign,
157 BitAndAssign => bitand_assign,
158 BitOrAssign => bitor_assign,
159 BitXorAssign => bitxor_assign,
160 ShlAssign => shl_assign,
161 ShrAssign => shr_assign,
162}
163
164macro_rules! impl_ops_copy {
165 ($($trait:ident => $method:ident),* $(,)?) => {
166 $(
167 impl<'i, T: Copy + ::std::ops::$trait<U>, U> ::std::ops::$trait<U> for SnapshotObserver<'i, T> {
168 type Output = T::Output;
169 fn $method(self, rhs: U) -> Self::Output {
170 (*self).$method(rhs)
171 }
172 }
173 )*
174 };
175}
176
177impl_ops_copy! {
178 Add => add,
179 Sub => sub,
180 Mul => mul,
181 Div => div,
182 Rem => rem,
183 BitAnd => bitand,
184 BitOr => bitor,
185 BitXor => bitxor,
186 Shl => shl,
187 Shr => shr,
188}
189
190macro_rules! impl_observe {
191 ($($ty:ty $(=> $target:ty)?),* $(,)?) => {
192 $(
193 impl Observe for $ty {
194 type Observer<'i> = SnapshotObserver<'i, $ty>
195 where
196 Self: 'i;
197 }
198 )*
199 };
200}
201
202impl_observe! {
203 usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64, bool,
204}