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