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