Skip to main content

deser_core/
std_only_impls.rs

1//! `Serialize` and `Deserialize` for leaf types that are only in `std`.
2//!
3//! The ones that are in `core` and `alloc` are in `std_impls`.
4use std::ffi::{OsStr, OsString};
5use std::path::{Path, PathBuf};
6use std::sync::{Mutex, OnceLock, RwLock};
7
8use alloc::borrow::Cow;
9use alloc::boxed::Box;
10use alloc::string::String;
11
12use crate::adapters::Same;
13use crate::de::impls::{Via, deserialize_via, via_handle};
14use crate::de::{Deserialize, Sink, SinkHandle};
15use crate::error::{Error, ErrorKind};
16use crate::event::Atom;
17use crate::ser::{Chunk, Describe, Serialize};
18use crate::{State, Text};
19
20make_slot_wrapper!(SlotWrapper);
21
22// OnceLock
23
24/// Serializes like an `Option`: as the value if it's set, as null if not.
25impl<T: Serialize + Send> Serialize for OnceLock<T> {
26    fn serialize(&self, state: &mut State) -> Result<Chunk<'_>, Error> {
27        match self.get() {
28            Some(value) => value.serialize(state),
29            None => Ok(Chunk::Atom(Atom::Null)),
30        }
31    }
32
33    fn finish(&self, state: &mut State) -> Result<(), Error> {
34        match self.get() {
35            Some(value) => value.finish(state),
36            None => Ok(()),
37        }
38    }
39
40    fn is_optional(&self) -> bool {
41        self.get().is_none()
42    }
43
44    fn container_shape(&self) -> crate::ContainerShape {
45        match self.get() {
46            Some(value) => value.container_shape(),
47            None => crate::ContainerShape::new(),
48        }
49    }
50
51    fn describe(&self, d: &mut dyn Describe) {
52        match self.get() {
53            Some(value) => {
54                d.some();
55                value.describe(d);
56            }
57            None => d.none(),
58        }
59    }
60}
61
62impl<T: Send> Via<Option<T>> for OnceLock<T> {
63    #[inline]
64    fn convert(value: Option<T>) -> Result<Self, Error> {
65        Ok(match value {
66            Some(value) => OnceLock::from(value),
67            None => OnceLock::new(),
68        })
69    }
70}
71
72/// Deserializes like an `Option`: null and missing values are not set.
73impl<'de, T: Deserialize<'de>> Deserialize<'de> for OnceLock<T> {
74    fn deserialize_into<'out>(
75        out: &'out mut Option<Self>,
76        state: &mut State,
77    ) -> SinkHandle<'out, 'de> {
78        via_handle::<Option<T>, Self, Same>(out, state)
79    }
80
81    fn initial_value() -> Option<Self> {
82        Some(OnceLock::new())
83    }
84}
85
86// Paths
87
88/// Serializes as a string.  Paths which are not valid UTF-8 fail to
89/// serialize.
90impl Serialize for Path {
91    begin_without_finish!();
92
93    fn serialize(&self, _state: &mut State) -> Result<Chunk<'_>, Error> {
94        match self.to_str() {
95            Some(value) => Ok(Chunk::Atom(Atom::Str(Text::borrowed(value)))),
96            None => Err(Error::new(
97                ErrorKind::Unexpected,
98                "path contains invalid UTF-8 characters",
99            )),
100        }
101    }
102}
103
104impl Serialize for PathBuf {
105    begin_without_finish!();
106
107    fn serialize(&self, state: &mut State) -> Result<Chunk<'_>, Error> {
108        self.as_path().serialize(state)
109    }
110}
111
112impl<'de> Sink<'de> for SlotWrapper<PathBuf> {
113    fn expecting(&self) -> Cow<'_, str> {
114        Cow::Borrowed("path")
115    }
116
117    fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
118        match atom {
119            Atom::Str(value) => {
120                **self = Some(PathBuf::from(value.into_owned()));
121                Ok(())
122            }
123            other => self.unexpected_atom(other, state),
124        }
125    }
126}
127
128impl<'de> Deserialize<'de> for PathBuf {
129    fn deserialize_into<'out>(
130        out: &'out mut Option<Self>,
131        _state: &mut State,
132    ) -> SinkHandle<'out, 'de> {
133        SlotWrapper::make_handle(out)
134    }
135
136    #[inline]
137    fn __private_atom_into(
138        out: &mut Option<Self>,
139        atom: Atom,
140        state: &mut State,
141    ) -> Result<(), Error> {
142        let sink = SlotWrapper::wrap(out);
143        sink.atom(atom, state)?;
144        sink.finish(state)
145    }
146
147    #[inline]
148    fn __private_borrowed_atom_into(
149        out: &mut Option<Self>,
150        atom: Atom<'de>,
151        state: &mut State,
152    ) -> Result<(), Error> {
153        Self::__private_atom_into(out, atom, state)
154    }
155}
156
157impl Via<PathBuf> for Box<Path> {
158    #[inline]
159    fn convert(value: PathBuf) -> Result<Self, Error> {
160        Ok(value.into_boxed_path())
161    }
162}
163
164deserialize_via! {
165    [] Box<Path> => PathBuf;
166}
167
168// OS strings
169
170/// Serializes as a string like [`Path`].  OS strings which are not valid
171/// UTF-8 fail to serialize.
172impl Serialize for OsStr {
173    begin_without_finish!();
174
175    fn serialize(&self, _state: &mut State) -> Result<Chunk<'_>, Error> {
176        match self.to_str() {
177            Some(value) => Ok(Chunk::Atom(Atom::Str(Text::borrowed(value)))),
178            None => Err(Error::new(
179                ErrorKind::Unexpected,
180                "OS string contains invalid UTF-8 characters",
181            )),
182        }
183    }
184}
185
186impl Serialize for OsString {
187    begin_without_finish!();
188
189    fn serialize(&self, state: &mut State) -> Result<Chunk<'_>, Error> {
190        self.as_os_str().serialize(state)
191    }
192}
193
194impl Via<String> for OsString {
195    #[inline]
196    fn convert(value: String) -> Result<Self, Error> {
197        Ok(OsString::from(value))
198    }
199}
200
201impl Via<OsString> for Box<OsStr> {
202    #[inline]
203    fn convert(value: OsString) -> Result<Self, Error> {
204        Ok(value.into_boxed_os_str())
205    }
206}
207
208deserialize_via! {
209    [] OsString => String;
210    [] Box<OsStr> => OsString;
211}
212
213// Locks
214
215// `Mutex` and `RwLock` are only deserialized: serializing would have to hold
216// the lock guard until the value is serialized, but serializations can move
217// between threads which guards must not.
218
219impl<T: Send> Via<T> for Mutex<T> {
220    #[inline]
221    fn convert(value: T) -> Result<Self, Error> {
222        Ok(Mutex::new(value))
223    }
224}
225
226impl<T: Send> Via<T> for RwLock<T> {
227    #[inline]
228    fn convert(value: T) -> Result<Self, Error> {
229        Ok(RwLock::new(value))
230    }
231}
232
233deserialize_via! {
234    [T: Deserialize<'de>] Mutex<T> => T;
235    [T: Deserialize<'de>] RwLock<T> => T;
236}