serde_saphyr/
anchors.rs

1use std::borrow::Borrow;
2use std::fmt;
3use std::marker::PhantomData;
4use std::ops::Deref;
5use std::rc::{Rc, Weak as RcWeak};
6use std::sync::{Arc, Weak as ArcWeak};
7
8use serde::de::{Error as _, Visitor};
9
10use crate::anchor_store;
11
12/// A wrapper around [`Rc<T>`] that opt-ins a field for **anchor emission** (e.g. serialization by reference).
13///
14/// This type behaves like a normal [`Rc<T>`] but signals that the value
15/// should be treated as an *anchorable* reference — for instance,
16/// when serializing graphs or shared structures where pointer identity matters.
17///
18/// # Examples
19///
20/// ```
21/// use std::rc::Rc;
22/// use serde_saphyr::RcAnchor;
23///
24/// // Create from an existing Rc
25/// let rc = Rc::new(String::from("Hello"));
26/// let anchor1 = RcAnchor::from(rc.clone());
27///
28/// // Or directly from a value (Rc::new is called internally)
29/// let anchor2: RcAnchor<String> = RcAnchor::from(Rc::new(String::from("World")));
30///
31/// assert_eq!(*anchor1.0, "Hello");
32/// assert_eq!(*anchor2.0, "World");
33/// ```
34#[repr(transparent)]
35#[derive(Clone)]
36pub struct RcAnchor<T: ?Sized>(pub Rc<T>);
37
38/// A wrapper around [`Arc<T>`] that opt-ins a field for **anchor emission** (e.g. serialization by reference).
39///
40/// It behaves exactly like an [`Arc<T>`] but explicitly marks shared ownership
41/// as an *anchor* for reference tracking or cross-object linking.
42///
43/// # Examples
44///
45/// ```
46/// use std::sync::Arc;
47/// use serde_saphyr::ArcAnchor;
48///
49/// // Create from an existing Arc
50/// let arc = Arc::new(String::from("Shared"));
51/// let anchor1 = ArcAnchor::from(arc.clone());
52///
53/// // Or create directly from a value
54/// let anchor2: ArcAnchor<String> = ArcAnchor::from(Arc::new(String::from("Data")));
55///
56/// assert_eq!(*anchor1.0, "Shared");
57/// assert_eq!(*anchor2.0, "Data");
58/// ```
59#[repr(transparent)]
60#[derive(Clone)]
61pub struct ArcAnchor<T: ?Sized>(pub Arc<T>);
62
63/// A wrapper around [`Weak<T>`] (from [`std::rc`]) that opt-ins for **anchor emission**.
64///
65/// When serialized, if the weak reference is **dangling** (i.e., the value was dropped),
66/// it emits `null` to indicate that the target no longer exists.
67/// Provides convenience methods like [`upgrade`](Self::upgrade) and [`is_dangling`](Self::is_dangling).
68///
69/// > **Note on deserialization:** `null` deserializes back into a dangling weak (`Weak::new()`).
70/// > Non-`null` cannot be safely reconstructed into a `Weak` without a shared registry; we reject it.
71/// > Ask if you want an ID/registry-based scheme to restore sharing.
72///
73/// # Examples
74///
75/// ```
76/// use std::rc::Rc;
77/// use serde_saphyr::{RcAnchor, RcWeakAnchor};
78///
79/// let rc_anchor = RcAnchor::from(Rc::new(String::from("Persistent")));
80///
81/// // Create a weak anchor from a strong reference
82/// let weak_anchor = RcWeakAnchor::from(&rc_anchor.0);
83///
84/// assert!(weak_anchor.upgrade().is_some());
85/// drop(rc_anchor);
86/// assert!(weak_anchor.upgrade().is_none());
87/// ```
88#[repr(transparent)]
89#[derive(Clone)]
90pub struct RcWeakAnchor<T: ?Sized>(pub RcWeak<T>);
91
92/// A wrapper around [`Weak<T>`] (from [`std::sync`]) that opt-ins for **anchor emission**.
93///
94/// This variant is thread-safe and uses [`Arc`] / [`Weak`] instead of [`Rc`].
95/// If the weak reference is **dangling**, it serializes as `null`.
96///
97/// > **Deserialization note:** `null` → dangling weak. Non-`null` is rejected unless a registry is used.
98///
99/// # Examples
100///
101/// ```
102/// use std::sync::Arc;
103/// use serde_saphyr::{ArcAnchor, ArcWeakAnchor};
104///
105/// let arc_anchor = ArcAnchor::from(Arc::new(String::from("Thread-safe")));
106///
107/// // Create a weak anchor from the strong reference
108/// let weak_anchor = ArcWeakAnchor::from(&arc_anchor.0);
109///
110/// assert!(weak_anchor.upgrade().is_some());
111/// drop(arc_anchor);
112/// assert!(weak_anchor.upgrade().is_none());
113/// ```
114#[repr(transparent)]
115#[derive(Clone)]
116pub struct ArcWeakAnchor<T: ?Sized>(pub ArcWeak<T>);
117
118// ===== From conversions (strong -> anchor) =====
119
120impl<T: ?Sized> From<Rc<T>> for RcAnchor<T> {
121    #[inline]
122    fn from(rc: Rc<T>) -> Self { RcAnchor(rc) }
123}
124impl<T: ?Sized> From<Arc<T>> for ArcAnchor<T> {
125    #[inline]
126    fn from(arc: Arc<T>) -> Self { ArcAnchor(arc) }
127}
128
129// ===== From conversions (strong -> weak anchor) =====
130
131impl<T: ?Sized> From<&Rc<T>> for RcWeakAnchor<T> {
132    #[inline]
133    fn from(rc: &Rc<T>) -> Self { RcWeakAnchor(Rc::downgrade(rc)) }
134}
135impl<T: ?Sized> From<Rc<T>> for RcWeakAnchor<T> {
136    #[inline]
137    fn from(rc: Rc<T>) -> Self { RcWeakAnchor(Rc::downgrade(&rc)) }
138}
139impl<T: ?Sized> From<&RcAnchor<T>> for RcWeakAnchor<T> {
140    #[inline]
141    fn from(rca: &RcAnchor<T>) -> Self { RcWeakAnchor(Rc::downgrade(&rca.0)) }
142}
143impl<T: ?Sized> From<&Arc<T>> for ArcWeakAnchor<T> {
144    #[inline]
145    fn from(arc: &Arc<T>) -> Self { ArcWeakAnchor(Arc::downgrade(arc)) }
146}
147impl<T: ?Sized> From<Arc<T>> for ArcWeakAnchor<T> {
148    #[inline]
149    fn from(arc: Arc<T>) -> Self { ArcWeakAnchor(Arc::downgrade(&arc)) }
150}
151impl<T: ?Sized> From<&ArcAnchor<T>> for ArcWeakAnchor<T> {
152    #[inline]
153    fn from(ara: &ArcAnchor<T>) -> Self { ArcWeakAnchor(Arc::downgrade(&ara.0)) }
154}
155
156// ===== Ergonomics: Deref / AsRef / Borrow / Into =====
157
158impl<T: ?Sized> Deref for RcAnchor<T> {
159    type Target = Rc<T>;
160    #[inline]
161    fn deref(&self) -> &Self::Target { &self.0 }
162}
163impl<T: ?Sized> Deref for ArcAnchor<T> {
164    type Target = Arc<T>;
165    #[inline]
166    fn deref(&self) -> &Self::Target { &self.0 }
167}
168impl<T: ?Sized> AsRef<Rc<T>> for RcAnchor<T> {
169    #[inline]
170    fn as_ref(&self) -> &Rc<T> { &self.0 }
171}
172impl<T: ?Sized> AsRef<Arc<T>> for ArcAnchor<T> {
173    #[inline]
174    fn as_ref(&self) -> &Arc<T> { &self.0 }
175}
176impl<T: ?Sized> Borrow<Rc<T>> for RcAnchor<T> {
177    #[inline]
178    fn borrow(&self) -> &Rc<T> { &self.0 }
179}
180impl<T: ?Sized> Borrow<Arc<T>> for ArcAnchor<T> {
181    #[inline]
182    fn borrow(&self) -> &Arc<T> { &self.0 }
183}
184impl<T: ?Sized> From<RcAnchor<T>> for Rc<T> {
185    #[inline]
186    fn from(a: RcAnchor<T>) -> Rc<T> { a.0 }
187}
188impl<T: ?Sized> From<ArcAnchor<T>> for Arc<T> {
189    #[inline]
190    fn from(a: ArcAnchor<T>) -> Arc<T> { a.0 }
191}
192
193// ===== Weak helpers =====
194
195impl<T: ?Sized> RcWeakAnchor<T> {
196    /// Try to upgrade the weak reference to [`Rc<T>`].
197    /// Returns [`None`] if the value has been dropped.
198    #[inline]
199    pub fn upgrade(&self) -> Option<Rc<T>> { self.0.upgrade() }
200
201    /// Returns `true` if the underlying value has been dropped (no strong refs remain).
202    #[inline]
203    pub fn is_dangling(&self) -> bool { self.0.strong_count() == 0 }
204}
205impl<T: ?Sized> ArcWeakAnchor<T> {
206    /// Try to upgrade the weak reference to [`Arc<T>`].
207    /// Returns [`None`] if the value has been dropped.
208    #[inline]
209    pub fn upgrade(&self) -> Option<Arc<T>> { self.0.upgrade() }
210
211    /// Returns `true` if the underlying value has been dropped (no strong refs remain).
212    #[inline]
213    pub fn is_dangling(&self) -> bool { self.0.strong_count() == 0 }
214}
215
216// ===== Pointer-equality PartialEq/Eq =====
217
218impl<T: ?Sized> PartialEq for RcAnchor<T> {
219    #[inline]
220    fn eq(&self, other: &Self) -> bool { Rc::ptr_eq(&self.0, &other.0) }
221}
222impl<T: ?Sized> Eq for RcAnchor<T> {}
223
224impl<T: ?Sized> PartialEq for ArcAnchor<T> {
225    #[inline]
226    fn eq(&self, other: &Self) -> bool { Arc::ptr_eq(&self.0, &other.0) }
227}
228impl<T: ?Sized> Eq for ArcAnchor<T> {}
229
230impl<T: ?Sized> PartialEq for RcWeakAnchor<T> {
231    #[inline]
232    fn eq(&self, other: &Self) -> bool {
233        match (self.0.upgrade(), other.0.upgrade()) {
234            (Some(a), Some(b)) => Rc::ptr_eq(&a, &b),
235            (None, None) => true,
236            _ => false,
237        }
238    }
239}
240impl<T: ?Sized> Eq for RcWeakAnchor<T> {}
241
242impl<T: ?Sized> PartialEq for ArcWeakAnchor<T> {
243    #[inline]
244    fn eq(&self, other: &Self) -> bool {
245        match (self.0.upgrade(), other.0.upgrade()) {
246            (Some(a), Some(b)) => Arc::ptr_eq(&a, &b),
247            (None, None) => true,
248            _ => false,
249        }
250    }
251}
252impl<T: ?Sized> Eq for ArcWeakAnchor<T> {}
253
254// ===== Debug =====
255
256impl<T: ?Sized> fmt::Debug for RcAnchor<T> {
257    #[inline]
258    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
259        write!(f, "RcAnchor({:p})", Rc::as_ptr(&self.0))
260    }
261}
262impl<T: ?Sized> fmt::Debug for ArcAnchor<T> {
263    #[inline]
264    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265        write!(f, "ArcAnchor({:p})", Arc::as_ptr(&self.0))
266    }
267}
268impl<T: ?Sized> fmt::Debug for RcWeakAnchor<T> {
269    #[inline]
270    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271        if let Some(rc) = self.0.upgrade() {
272            write!(f, "RcWeakAnchor(upgrade={:p})", Rc::as_ptr(&rc))
273        } else {
274            write!(f, "RcWeakAnchor(dangling)")
275        }
276    }
277}
278impl<T: ?Sized> fmt::Debug for ArcWeakAnchor<T> {
279    #[inline]
280    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281        if let Some(arc) = self.0.upgrade() {
282            write!(f, "ArcWeakAnchor(upgrade={:p})", Arc::as_ptr(&arc))
283        } else {
284            write!(f, "ArcWeakAnchor(dangling)")
285        }
286    }
287}
288
289// ===== Default =====
290
291impl<T: Default> Default for RcAnchor<T> {
292    #[inline]
293    fn default() -> Self { RcAnchor(Rc::new(T::default())) }
294}
295impl<T: Default> Default for ArcAnchor<T> {
296    fn default() -> Self { ArcAnchor(Arc::new(T::default())) }
297}
298
299// -------------------------------
300// Deserialize impls
301// -------------------------------
302impl<'de, T> serde::de::Deserialize<'de> for RcAnchor<T>
303where
304    T: serde::de::Deserialize<'de> + 'static,
305{
306    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
307    where
308        D: serde::de::Deserializer<'de>,
309    {
310        struct RcAnchorVisitor<T>(PhantomData<T>);
311
312        impl<'de, T> Visitor<'de> for RcAnchorVisitor<T>
313        where
314            T: serde::de::Deserialize<'de> + 'static,
315        {
316            type Value = RcAnchor<T>;
317
318            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
319                f.write_str("an RcAnchor newtype")
320            }
321
322            fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
323            where
324                D: serde::de::Deserializer<'de>,
325            {
326                let anchor_id = anchor_store::current_rc_anchor();
327                let existing = match anchor_id {
328                    Some(id) => Some((id, anchor_store::get_rc::<T>(id).map_err(D::Error::custom)?)),
329                    None => None,
330                };
331
332                let value = T::deserialize(deserializer)?;
333                if let Some((_, Some(rc))) = existing {
334                    drop(value);
335                    return Ok(RcAnchor(rc));
336                }
337                if let Some((id, None)) = existing {
338                    let rc = Rc::new(value);
339                    anchor_store::store_rc(id, rc.clone());
340                    return Ok(RcAnchor(rc));
341                }
342                Ok(RcAnchor(Rc::new(value)))
343            }
344        }
345
346        deserializer.deserialize_newtype_struct("__yaml_rc_anchor", RcAnchorVisitor(PhantomData))
347    }
348}
349
350impl<'de, T> serde::de::Deserialize<'de> for ArcAnchor<T>
351where
352    T: serde::de::Deserialize<'de> + Send + Sync + 'static,
353{
354    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
355    where
356        D: serde::de::Deserializer<'de>,
357    {
358        struct ArcAnchorVisitor<T>(PhantomData<T>);
359
360        impl<'de, T> Visitor<'de> for ArcAnchorVisitor<T>
361        where
362            T: serde::de::Deserialize<'de> + Send + Sync + 'static,
363        {
364            type Value = ArcAnchor<T>;
365
366            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
367                f.write_str("an ArcAnchor newtype")
368            }
369
370            fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
371            where
372                D: serde::de::Deserializer<'de>,
373            {
374                let anchor_id = anchor_store::current_arc_anchor();
375                let existing = match anchor_id {
376                    Some(id) => Some((id, anchor_store::get_arc::<T>(id).map_err(D::Error::custom)?)),
377                    None => None,
378                };
379
380                let value = T::deserialize(deserializer)?;
381                if let Some((_, Some(arc))) = existing {
382                    drop(value);
383                    return Ok(ArcAnchor(arc));
384                }
385                if let Some((id, None)) = existing {
386                    let arc = Arc::new(value);
387                    anchor_store::store_arc(id, arc.clone());
388                    return Ok(ArcAnchor(arc));
389                }
390                Ok(ArcAnchor(Arc::new(value)))
391            }
392        }
393
394        deserializer.deserialize_newtype_struct("__yaml_arc_anchor", ArcAnchorVisitor(PhantomData))
395    }
396}
397
398// -------------------------------
399// Deserialize impls for WEAK anchors (RcWeakAnchor / ArcWeakAnchor)
400// -------------------------------
401impl<'de, T> serde::de::Deserialize<'de> for RcWeakAnchor<T>
402where
403    T: serde::de::Deserialize<'de> + 'static,
404{
405    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
406    where
407        D: serde::de::Deserializer<'de>,
408    {
409        struct RcWeakVisitor<T>(PhantomData<T>);
410        impl<'de, T> Visitor<'de> for RcWeakVisitor<T>
411        where
412            T: serde::de::Deserialize<'de> + 'static,
413        {
414            type Value = RcWeakAnchor<T>;
415            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
416                f.write_str("an RcWeakAnchor referring to a previously defined strong anchor (via alias)")
417            }
418            fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
419            where
420                D: serde::de::Deserializer<'de>,
421            {
422                // Anchor context is established by de.rs when the special name is used.
423                let id = anchor_store::current_rc_anchor().ok_or_else(|| D::Error::custom("weak Rc anchor must refer to an existing strong anchor via alias"))?;
424                // Consume and ignore the inner node to keep the stream in sync (alias replay injects the full target node).
425                let _ = <serde::de::IgnoredAny as serde::de::Deserialize>::deserialize(deserializer)?;
426                // Look up the strong reference by id and downgrade.
427                match anchor_store::get_rc::<T>(id).map_err(D::Error::custom)? {
428                    Some(rc) => Ok(RcWeakAnchor(Rc::downgrade(&rc))),
429                    None => Err(D::Error::custom("weak Rc anchor refers to unknown anchor id; strong anchor must be defined before weak")),
430                }
431            }
432        }
433        deserializer.deserialize_newtype_struct("__yaml_rc_weak_anchor", RcWeakVisitor(PhantomData))
434    }
435}
436
437impl<'de, T> serde::de::Deserialize<'de> for ArcWeakAnchor<T>
438where
439    T: serde::de::Deserialize<'de> + Send + Sync + 'static,
440{
441    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
442    where
443        D: serde::de::Deserializer<'de>,
444    {
445        struct ArcWeakVisitor<T>(PhantomData<T>);
446        impl<'de, T> Visitor<'de> for ArcWeakVisitor<T>
447        where
448            T: serde::de::Deserialize<'de> + Send + Sync + 'static,
449        {
450            type Value = ArcWeakAnchor<T>;
451            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
452                f.write_str("an ArcWeakAnchor referring to a previously defined strong anchor (via alias)")
453            }
454            fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
455            where
456                D: serde::de::Deserializer<'de>,
457            {
458                let id = anchor_store::current_arc_anchor().ok_or_else(|| D::Error::custom("weak Arc anchor must refer to an existing strong anchor via alias"))?;
459                // Consume and ignore the inner node (alias replay injects the target node events).
460                let _ = <serde::de::IgnoredAny as serde::de::Deserialize>::deserialize(deserializer)?;
461                match anchor_store::get_arc::<T>(id).map_err(D::Error::custom)? {
462                    Some(arc) => Ok(ArcWeakAnchor(Arc::downgrade(&arc))),
463                    None => Err(D::Error::custom("weak Arc anchor refers to unknown anchor id; strong anchor must be defined before weak")),
464                }
465            }
466        }
467        deserializer.deserialize_newtype_struct("__yaml_arc_weak_anchor", ArcWeakVisitor(PhantomData))
468    }
469}
470