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