1use funcmap::{FuncMap, TryFuncMap};
14use polyquine::Quine;
15use proc_macro2::TokenStream;
16use serde::{Deserialize, Deserializer, Serialize, Serializer};
17use serde_with::de::DeserializeAsWrap;
18use serde_with::ser::SerializeAsWrap;
19use serde_with::{DeserializeAs, SerializeAs};
20use std::hash::{Hash, Hasher};
21use std::ops::DerefMut;
22use std::{collections::VecDeque, fmt::Display, ops::Deref, sync::Arc};
23use uniplate::{
24 Biplate, Tree, Uniplate,
25 impl_helpers::{transmute_if_same_type, try_transmute_if_same_type},
26 spez::try_biplate_to,
27};
28
29#[derive(PartialEq, Eq, Clone, Debug)]
43pub struct Moo<T> {
44 inner: Arc<T>,
45}
46
47impl<T: Quine> Quine for Moo<T> {
48 fn ctor_tokens(&self) -> TokenStream {
49 let inner = self.inner.as_ref().ctor_tokens();
50 quote::quote! { ::conjure_cp::ast::Moo::new(#inner) }
51 }
52}
53
54impl<T> Moo<T> {
55 pub fn new(value: T) -> Moo<T> {
57 Moo {
58 inner: Arc::new(value),
59 }
60 }
61}
62
63impl<T: Clone> Moo<T> {
64 pub fn make_mut(this: &mut Moo<T>) -> &mut T {
70 Arc::make_mut(&mut this.inner)
71 }
72
73 pub fn unwrap_or_clone(this: Moo<T>) -> T {
78 Arc::unwrap_or_clone(this.inner)
79 }
80}
81
82impl<T> AsRef<T> for Moo<T> {
83 fn as_ref(&self) -> &T {
84 self.inner.as_ref()
85 }
86}
87
88impl<T> Deref for Moo<T> {
89 type Target = T;
90
91 fn deref(&self) -> &Self::Target {
92 self.inner.deref()
93 }
94}
95
96impl<T: Clone> DerefMut for Moo<T> {
97 fn deref_mut(&mut self) -> &mut Self::Target {
98 Moo::make_mut(self)
99 }
100}
101
102impl<T> Uniplate for Moo<T>
103where
104 T: Uniplate,
105{
106 fn uniplate(
107 &self,
108 ) -> (
109 uniplate::Tree<Self>,
110 Box<dyn Fn(uniplate::Tree<Self>) -> Self>,
111 ) {
112 let this = Moo::clone(self);
113
114 let (tree, ctx) = try_biplate_to!((**self).clone(), Moo<T>);
117 (
118 Tree::Many(VecDeque::from([tree.clone()])),
119 Box::new(move |x| {
120 let Tree::Many(trees) = x else { panic!() };
121 let new_tree = trees.into_iter().next().unwrap();
122 let mut this = Moo::clone(&this);
123
124 if new_tree != tree {
128 let this = Moo::make_mut(&mut this);
129 *this = ctx(new_tree)
130 }
131
132 this
133 }),
134 )
135 }
136}
137
138impl<To, U> Biplate<To> for Moo<U>
139where
140 To: Uniplate,
141 U: Uniplate + Biplate<To>,
142{
143 fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
144 if let Some(self_as_to) = transmute_if_same_type::<Self, To>(self) {
145 let tree = Tree::One(self_as_to.clone());
147 let ctx = Box::new(move |x| {
148 let Tree::One(self_as_to) = x else { panic!() };
149
150 let self_as_self = try_transmute_if_same_type::<To, Self>(&self_as_to);
151
152 Moo::clone(self_as_self)
153 });
154
155 (tree, ctx)
156 } else {
157 let this = Moo::clone(self);
160
161 let (tree, ctx) = try_biplate_to!((**self).clone(), To);
164 (
165 Tree::Many(VecDeque::from([tree.clone()])),
166 Box::new(move |x| {
167 let Tree::Many(trees) = x else { panic!() };
168 let new_tree = trees.into_iter().next().unwrap();
169 let mut this = Moo::clone(&this);
170
171 if new_tree != tree {
175 let this = Moo::make_mut(&mut this);
176 *this = ctx(new_tree)
177 }
178
179 this
180 }),
181 )
182 }
183 }
184
185 fn children_bi_count(&self) -> usize {
192 if std::any::TypeId::of::<Self>() == std::any::TypeId::of::<To>() {
193 return 1;
195 }
196 <U as Biplate<To>>::children_bi_count(&**self)
197 }
198
199 fn try_replace_child_at_bi(&mut self, index: usize, child: To) -> bool {
205 if std::any::TypeId::of::<Self>() == std::any::TypeId::of::<To>() {
206 if index != 0 {
207 return false;
208 }
209 unsafe {
211 let child_as_self = std::mem::transmute_copy::<To, Self>(&child);
212 std::mem::forget(child);
213 *self = child_as_self;
214 }
215 return true;
216 }
217 if std::any::TypeId::of::<U>() == std::any::TypeId::of::<To>() {
218 if index != 0 {
219 return false;
220 }
221 let value = unsafe { std::mem::transmute_copy::<To, U>(&child) };
225 std::mem::forget(child);
226 *self = Moo::new(value);
227 return true;
228 }
229 <U as Biplate<To>>::try_replace_child_at_bi(Moo::make_mut(self), index, child)
230 }
231}
232
233impl<'de, T: Deserialize<'de>> Deserialize<'de> for Moo<T> {
234 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
235 where
236 D: serde::Deserializer<'de>,
237 {
238 Ok(Moo::new(T::deserialize(deserializer)?))
239 }
240}
241
242impl<T: Serialize> Serialize for Moo<T> {
243 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
244 where
245 S: serde::Serializer,
246 {
247 T::serialize(&**self, serializer)
248 }
249}
250
251impl<T: Display> Display for Moo<T> {
252 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
253 (**self).fmt(f)
254 }
255}
256
257impl<T: Hash> Hash for Moo<T> {
258 fn hash<H: Hasher>(&self, state: &mut H) {
259 (**self).hash(state);
260 }
261}
262
263impl<T> From<T> for Moo<T> {
264 fn from(value: T) -> Self {
265 Moo::new(value)
266 }
267}
268
269impl<A, B> FuncMap<A, B> for Moo<A>
270where
271 A: Clone,
272{
273 type Output = Moo<B>;
274
275 fn func_map<F>(self, mut f: F) -> Self::Output
276 where
277 F: FnMut(A) -> B,
278 {
279 let inner = Moo::unwrap_or_clone(self);
280 Moo::new(f(inner))
281 }
282}
283
284impl<A, B> TryFuncMap<A, B> for Moo<A>
285where
286 A: Clone,
287{
288 type Output = Moo<B>;
289
290 fn try_func_map<E, F>(self, mut f: F) -> Result<Self::Output, E>
291 where
292 F: FnMut(A) -> Result<B, E>,
293 {
294 let inner = Moo::unwrap_or_clone(self);
295 let res = f(inner)?;
296 Ok(Moo::new(res))
297 }
298}
299
300impl<T, As> SerializeAs<Moo<T>> for Moo<As>
301where
302 As: SerializeAs<T>,
303{
304 fn serialize_as<S>(source: &Moo<T>, serializer: S) -> Result<S::Ok, S::Error>
305 where
306 S: Serializer,
307 {
308 let wrap = SerializeAsWrap::<T, As>::new(&**source);
309 wrap.serialize(serializer)
310 }
311}
312
313impl<'de, T, As> DeserializeAs<'de, Moo<T>> for Moo<As>
314where
315 As: DeserializeAs<'de, T>,
316{
317 fn deserialize_as<D>(deserializer: D) -> Result<Moo<T>, D::Error>
318 where
319 D: Deserializer<'de>,
320 {
321 let wrap = DeserializeAsWrap::<T, As>::deserialize(deserializer)?;
322 Ok(Moo::new(wrap.into_inner()))
323 }
324}
325
326#[cfg(test)]
327mod replacement_tests {
328 use super::*;
329 use std::sync::atomic::{AtomicUsize, Ordering};
330
331 static CLONES: AtomicUsize = AtomicUsize::new(0);
332
333 #[derive(Debug, PartialEq, Eq)]
334 struct CloneProbe(i32);
335
336 impl Clone for CloneProbe {
337 fn clone(&self) -> Self {
338 CLONES.fetch_add(1, Ordering::Relaxed);
339 Self(self.0)
340 }
341 }
342
343 impl Uniplate for CloneProbe {
344 fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
345 let value = self.0;
346 (Tree::Zero, Box::new(move |_| Self(value)))
347 }
348 }
349
350 impl Biplate<CloneProbe> for CloneProbe {
351 fn biplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
352 (
353 Tree::One(self.clone()),
354 Box::new(|tree| {
355 let Tree::One(value) = tree else {
356 panic!("expected one child")
357 };
358 value
359 }),
360 )
361 }
362 }
363
364 #[test]
365 fn replacing_shared_pointee_does_not_clone_the_discarded_value() {
366 let mut value = Moo::new(CloneProbe(1));
367 let shared = value.clone();
368 CLONES.store(0, Ordering::Relaxed);
369 assert!(!value.try_replace_child_at_bi(1, CloneProbe(2)));
370 assert_eq!(value.0, 1);
371 assert!(value.try_replace_child_at_bi(0, CloneProbe(2)));
372 assert_eq!(value.0, 2);
373 assert_eq!(shared.0, 1);
374 assert_eq!(CLONES.load(Ordering::Relaxed), 0);
375 }
376}