Skip to main content

serde_saphyr/ser/
wrapper_impls.rs

1use serde_core::ser::{self, Serialize, SerializeTupleStruct, Serializer};
2use std::cell::RefCell;
3use std::rc::Rc;
4use std::sync::{Arc, Mutex};
5
6#[cfg(feature = "comments")]
7use crate::Commented;
8use crate::{
9    ArcAnchor, ArcRecursion, ArcRecursive, ArcWeakAnchor, DoubleQuoted, FlowMap, FlowSeq,
10    NullableTilde, RcAnchor, RcRecursion, RcRecursive, RcWeakAnchor, SingleQuoted, SpaceAfter,
11    Tagged,
12};
13
14#[cfg(feature = "comments")]
15use super::NAME_TUPLE_COMMENTED;
16use super::{
17    NAME_DOUBLE_QUOTED, NAME_FLOW_MAP, NAME_FLOW_SEQ, NAME_NULLABLE_TILDE, NAME_SINGLE_QUOTED,
18    NAME_SPACE_AFTER, NAME_TUPLE_ANCHOR, NAME_TUPLE_TAGGED, NAME_TUPLE_WEAK,
19};
20
21// ------------------------------------------------------------
22// Internal wrappers -> shape the stream Serde produces so our
23// serializer can intercept them in a single pass.
24// ------------------------------------------------------------
25
26// Recursive weak payloads: defer locking/borrowing until actual value serialization.
27struct RcRecursivePayload<'a, T>(&'a Rc<RefCell<Option<T>>>);
28struct ArcRecursivePayload<'a, T>(&'a Arc<Mutex<Option<T>>>);
29
30impl<T: Serialize> Serialize for RcRecursivePayload<'_, T> {
31    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
32        let borrowed = self.0.borrow();
33        if let Some(value) = borrowed.as_ref() {
34            value.serialize(s)
35        } else {
36            s.serialize_unit()
37        }
38    }
39}
40
41impl<T: Serialize> Serialize for ArcRecursivePayload<'_, T> {
42    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
43        let guard = self
44            .0
45            .lock()
46            .map_err(|_| ser::Error::custom("recursive Arc anchor mutex poisoned"))?;
47        if let Some(value) = guard.as_ref() {
48            value.serialize(s)
49        } else {
50            s.serialize_unit()
51        }
52    }
53}
54
55// Top-level newtype wrappers for strong/weak simply wrap the real payloads.
56impl<T: Serialize> Serialize for RcAnchor<T> {
57    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
58        // delegate to tuple-struct the serializer knows how to intercept
59        let mut ts = s.serialize_tuple_struct(NAME_TUPLE_ANCHOR, 2)?;
60        let ptr = Rc::as_ptr(&self.0) as usize;
61        ts.serialize_field(&ptr)?;
62        ts.serialize_field(&*self.0)?;
63        ts.end()
64    }
65}
66impl<T: Serialize> Serialize for ArcAnchor<T> {
67    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
68        let mut ts = s.serialize_tuple_struct(NAME_TUPLE_ANCHOR, 2)?;
69        let ptr = Arc::as_ptr(&self.0) as usize;
70        ts.serialize_field(&ptr)?;
71        ts.serialize_field(&*self.0)?;
72        ts.end()
73    }
74}
75impl<T: Serialize> Serialize for RcRecursive<T> {
76    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
77        let mut ts = s.serialize_tuple_struct(NAME_TUPLE_ANCHOR, 2)?;
78        let ptr = Rc::as_ptr(&self.0) as usize;
79        ts.serialize_field(&ptr)?;
80        let borrowed = self.0.borrow();
81        let value = borrowed
82            .as_ref()
83            .ok_or_else(|| ser::Error::custom("recursive Rc anchor not initialized"))?;
84        ts.serialize_field(value)?;
85        ts.end()
86    }
87}
88impl<T: Serialize> Serialize for ArcRecursive<T> {
89    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
90        let mut ts = s.serialize_tuple_struct(NAME_TUPLE_ANCHOR, 2)?;
91        let ptr = Arc::as_ptr(&self.0) as usize;
92        ts.serialize_field(&ptr)?;
93        let guard = self
94            .0
95            .lock()
96            .map_err(|_| ser::Error::custom("recursive Arc anchor mutex poisoned"))?;
97        let value = guard
98            .as_ref()
99            .ok_or_else(|| ser::Error::custom("recursive Arc anchor not initialized"))?;
100        ts.serialize_field(value)?;
101        ts.end()
102    }
103}
104impl<T: Serialize> Serialize for RcWeakAnchor<T> {
105    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
106        let up = self.0.upgrade();
107        let mut ts = s.serialize_tuple_struct(NAME_TUPLE_WEAK, 3)?;
108        let ptr = self.0.as_ptr() as usize;
109        ts.serialize_field(&ptr)?;
110        ts.serialize_field(&up.is_some())?;
111        if let Some(rc) = up {
112            ts.serialize_field(&*rc)?;
113        } else {
114            ts.serialize_field(&())?; // ignored by our serializer
115        }
116        ts.end()
117    }
118}
119impl<T: Serialize> Serialize for ArcWeakAnchor<T> {
120    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
121        let up = self.0.upgrade();
122        let mut ts = s.serialize_tuple_struct(NAME_TUPLE_WEAK, 3)?;
123        let ptr = self.0.as_ptr() as usize;
124        ts.serialize_field(&ptr)?;
125        ts.serialize_field(&up.is_some())?;
126        if let Some(arc) = up {
127            ts.serialize_field(&*arc)?;
128        } else {
129            ts.serialize_field(&())?;
130        }
131        ts.end()
132    }
133}
134impl<T: Serialize> Serialize for RcRecursion<T> {
135    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
136        let up = self.0.upgrade();
137        let mut ts = s.serialize_tuple_struct(NAME_TUPLE_WEAK, 3)?;
138        let ptr = self.0.as_ptr() as usize;
139        ts.serialize_field(&ptr)?;
140        ts.serialize_field(&up.is_some())?;
141        if let Some(rc) = up {
142            ts.serialize_field(&RcRecursivePayload(&rc))?;
143        } else {
144            ts.serialize_field(&())?;
145        }
146        ts.end()
147    }
148}
149impl<T: Serialize> Serialize for ArcRecursion<T> {
150    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
151        let up = self.0.upgrade();
152        let mut ts = s.serialize_tuple_struct(NAME_TUPLE_WEAK, 3)?;
153        let ptr = self.0.as_ptr() as usize;
154        ts.serialize_field(&ptr)?;
155        ts.serialize_field(&up.is_some())?;
156        if let Some(arc) = up {
157            ts.serialize_field(&ArcRecursivePayload(&arc))?;
158        } else {
159            ts.serialize_field(&())?;
160        }
161        ts.end()
162    }
163}
164
165// Hints for flow / block strings.
166impl<T: Serialize> Serialize for FlowSeq<T> {
167    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
168        s.serialize_newtype_struct(NAME_FLOW_SEQ, &self.0)
169    }
170}
171impl<T: Serialize> Serialize for FlowMap<T> {
172    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
173        s.serialize_newtype_struct(NAME_FLOW_MAP, &self.0)
174    }
175}
176impl<T: Serialize> Serialize for SpaceAfter<T> {
177    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
178        s.serialize_newtype_struct(NAME_SPACE_AFTER, &self.0)
179    }
180}
181impl<T: AsRef<str>> Serialize for DoubleQuoted<T> {
182    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
183        s.serialize_newtype_struct(NAME_DOUBLE_QUOTED, self.0.as_ref())
184    }
185}
186impl<T: AsRef<str>> Serialize for SingleQuoted<T> {
187    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
188        s.serialize_newtype_struct(NAME_SINGLE_QUOTED, self.0.as_ref())
189    }
190}
191impl<T: Serialize> Serialize for NullableTilde<T> {
192    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
193        if !s.is_human_readable() {
194            return self.0.serialize(s);
195        }
196
197        match &self.0 {
198            Some(value) => s.serialize_some(value),
199            None => s.serialize_newtype_struct(NAME_NULLABLE_TILDE, &self.0),
200        }
201    }
202}
203
204#[cfg(feature = "comments")]
205impl<T: Serialize> Serialize for Commented<T> {
206    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
207        // Represent as a special tuple-struct with two fields: (comment, value)
208        // so the serializer can stage the comment before serializing the value.
209        let mut ts = s.serialize_tuple_struct(NAME_TUPLE_COMMENTED, 2)?;
210        ts.serialize_field(&self.1)?; // comment first
211        ts.serialize_field(&self.0)?; // then value
212        ts.end()
213    }
214}
215
216impl<T: Serialize> Serialize for Tagged<T> {
217    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
218        let Some(tag) = self.1.as_ref() else {
219            // No tag requested: place no requirement on the node at all, so the
220            // inner value serializes exactly as it would unwrapped.
221            return self.0.serialize(s);
222        };
223
224        // Stage the resolved tag before the value reveals whether it is a scalar
225        // or collection, just as Commented stages its presentation metadata.
226        let mut ts = s.serialize_tuple_struct(NAME_TUPLE_TAGGED, 2)?;
227        ts.serialize_field(tag)?;
228        ts.serialize_field(&self.0)?;
229        ts.end()
230    }
231}