rkyv/with/
std.rs

1use crate::{
2    collections::util::Entry,
3    ser::{ScratchSpace, Serializer},
4    string::{ArchivedString, StringResolver},
5    time::ArchivedDuration,
6    vec::{ArchivedVec, VecResolver},
7    with::{
8        ArchiveWith, AsString, AsStringError, AsVec, DeserializeWith, Immutable, Lock, LockError,
9        SerializeWith, UnixTimestamp, UnixTimestampError,
10    },
11    Archive, Deserialize, Fallible, Serialize, SerializeUnsized,
12};
13use core::{hash::Hash, str::FromStr};
14use std::{
15    collections::{HashMap, HashSet},
16    ffi::OsString,
17    path::PathBuf,
18    sync::{Mutex, RwLock},
19    time::{SystemTime, UNIX_EPOCH},
20};
21
22// AsString
23
24impl ArchiveWith<OsString> for AsString {
25    type Archived = ArchivedString;
26    type Resolver = StringResolver;
27
28    #[inline]
29    unsafe fn resolve_with(
30        field: &OsString,
31        pos: usize,
32        resolver: Self::Resolver,
33        out: *mut Self::Archived,
34    ) {
35        // It's safe to unwrap here because if the OsString wasn't valid UTF-8 it would have failed
36        // to serialize
37        ArchivedString::resolve_from_str(field.to_str().unwrap(), pos, resolver, out);
38    }
39}
40
41impl<S: Fallible + ?Sized> SerializeWith<OsString, S> for AsString
42where
43    S::Error: From<AsStringError>,
44    str: SerializeUnsized<S>,
45{
46    #[inline]
47    fn serialize_with(field: &OsString, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
48        ArchivedString::serialize_from_str(
49            field.to_str().ok_or(AsStringError::InvalidUTF8)?,
50            serializer,
51        )
52    }
53}
54
55impl<D: Fallible + ?Sized> DeserializeWith<ArchivedString, OsString, D> for AsString {
56    #[inline]
57    fn deserialize_with(field: &ArchivedString, _: &mut D) -> Result<OsString, D::Error> {
58        Ok(OsString::from_str(field.as_str()).unwrap())
59    }
60}
61
62impl ArchiveWith<PathBuf> for AsString {
63    type Archived = ArchivedString;
64    type Resolver = StringResolver;
65
66    #[inline]
67    unsafe fn resolve_with(
68        field: &PathBuf,
69        pos: usize,
70        resolver: Self::Resolver,
71        out: *mut Self::Archived,
72    ) {
73        // It's safe to unwrap here because if the OsString wasn't valid UTF-8 it would have failed
74        // to serialize
75        ArchivedString::resolve_from_str(field.to_str().unwrap(), pos, resolver, out);
76    }
77}
78
79impl<S: Fallible + ?Sized> SerializeWith<PathBuf, S> for AsString
80where
81    S::Error: From<AsStringError>,
82    str: SerializeUnsized<S>,
83{
84    #[inline]
85    fn serialize_with(field: &PathBuf, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
86        ArchivedString::serialize_from_str(
87            field.to_str().ok_or(AsStringError::InvalidUTF8)?,
88            serializer,
89        )
90    }
91}
92
93impl<D: Fallible + ?Sized> DeserializeWith<ArchivedString, PathBuf, D> for AsString {
94    #[inline]
95    fn deserialize_with(field: &ArchivedString, _: &mut D) -> Result<PathBuf, D::Error> {
96        Ok(PathBuf::from_str(field.as_str()).unwrap())
97    }
98}
99
100// Lock
101
102impl<F: Archive> ArchiveWith<Mutex<F>> for Lock {
103    type Archived = Immutable<F::Archived>;
104    type Resolver = F::Resolver;
105
106    #[inline]
107    unsafe fn resolve_with(
108        field: &Mutex<F>,
109        pos: usize,
110        resolver: Self::Resolver,
111        out: *mut Self::Archived,
112    ) {
113        // Unfortunately, we have to unwrap here because resolve must be infallible
114        //
115        // An alternative would be to only implement ArchiveWith for Arc<Mutex<F>>, copy an Arc into
116        // the resolver, and hold the guard in there as well (as a reference to the internal mutex).
117        // This unfortunately will cause a deadlock if two Arcs to the same Mutex are serialized
118        // before the first is resolved. The compromise is, unfortunately, to just unwrap poison
119        // errors here and document it.
120        field.lock().unwrap().resolve(pos, resolver, out.cast());
121    }
122}
123
124impl<F: Serialize<S>, S: Fallible + ?Sized> SerializeWith<Mutex<F>, S> for Lock
125where
126    S::Error: From<LockError>,
127{
128    #[inline]
129    fn serialize_with(field: &Mutex<F>, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
130        field
131            .lock()
132            .map_err(|_| LockError::Poisoned)?
133            .serialize(serializer)
134    }
135}
136
137impl<F, T, D> DeserializeWith<Immutable<F>, Mutex<T>, D> for Lock
138where
139    F: Deserialize<T, D>,
140    D: Fallible + ?Sized,
141{
142    #[inline]
143    fn deserialize_with(field: &Immutable<F>, deserializer: &mut D) -> Result<Mutex<T>, D::Error> {
144        Ok(Mutex::new(field.value().deserialize(deserializer)?))
145    }
146}
147
148impl<F: Archive> ArchiveWith<RwLock<F>> for Lock {
149    type Archived = Immutable<F::Archived>;
150    type Resolver = F::Resolver;
151
152    #[inline]
153    unsafe fn resolve_with(
154        field: &RwLock<F>,
155        pos: usize,
156        resolver: Self::Resolver,
157        out: *mut Self::Archived,
158    ) {
159        // Unfortunately, we have to unwrap here because resolve must be infallible
160        //
161        // An alternative would be to only implement ArchiveWith for Arc<Mutex<F>>, copy a an Arc
162        // into the resolver, and hold the guard in there as well (as a reference to the internal
163        // mutex). This unfortunately will cause a deadlock if two Arcs to the same Mutex are
164        // serialized before the first is resolved. The compromise is, unfortunately, to just
165        // unwrap poison errors here and document it.
166        field.read().unwrap().resolve(pos, resolver, out.cast());
167    }
168}
169
170impl<F: Serialize<S>, S: Fallible + ?Sized> SerializeWith<RwLock<F>, S> for Lock
171where
172    S::Error: From<LockError>,
173{
174    #[inline]
175    fn serialize_with(field: &RwLock<F>, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
176        field
177            .read()
178            .map_err(|_| LockError::Poisoned)?
179            .serialize(serializer)
180    }
181}
182
183impl<F, T, D> DeserializeWith<Immutable<F>, RwLock<T>, D> for Lock
184where
185    F: Deserialize<T, D>,
186    D: Fallible + ?Sized,
187{
188    #[inline]
189    fn deserialize_with(field: &Immutable<F>, deserializer: &mut D) -> Result<RwLock<T>, D::Error> {
190        Ok(RwLock::new(field.value().deserialize(deserializer)?))
191    }
192}
193
194// AsVec
195
196impl<K: Archive, V: Archive> ArchiveWith<HashMap<K, V>> for AsVec {
197    type Archived = ArchivedVec<Entry<K::Archived, V::Archived>>;
198    type Resolver = VecResolver;
199
200    unsafe fn resolve_with(
201        field: &HashMap<K, V>,
202        pos: usize,
203        resolver: Self::Resolver,
204        out: *mut Self::Archived,
205    ) {
206        ArchivedVec::resolve_from_len(field.len(), pos, resolver, out);
207    }
208}
209
210impl<K, V, S> SerializeWith<HashMap<K, V>, S> for AsVec
211where
212    K: Serialize<S>,
213    V: Serialize<S>,
214    S: ScratchSpace + Serializer + ?Sized,
215{
216    fn serialize_with(
217        field: &HashMap<K, V>,
218        serializer: &mut S,
219    ) -> Result<Self::Resolver, S::Error> {
220        ArchivedVec::serialize_from_iter(
221            field.iter().map(|(key, value)| Entry { key, value }),
222            serializer,
223        )
224    }
225}
226
227impl<K, V, D> DeserializeWith<ArchivedVec<Entry<K::Archived, V::Archived>>, HashMap<K, V>, D>
228    for AsVec
229where
230    K: Archive + Hash + Eq,
231    V: Archive,
232    K::Archived: Deserialize<K, D>,
233    V::Archived: Deserialize<V, D>,
234    D: Fallible + ?Sized,
235{
236    fn deserialize_with(
237        field: &ArchivedVec<Entry<K::Archived, V::Archived>>,
238        deserializer: &mut D,
239    ) -> Result<HashMap<K, V>, D::Error> {
240        let mut result = HashMap::with_capacity(field.len());
241        for entry in field.iter() {
242            result.insert(
243                entry.key.deserialize(deserializer)?,
244                entry.value.deserialize(deserializer)?,
245            );
246        }
247        Ok(result)
248    }
249}
250
251impl<T: Archive> ArchiveWith<HashSet<T>> for AsVec {
252    type Archived = ArchivedVec<T::Archived>;
253    type Resolver = VecResolver;
254
255    unsafe fn resolve_with(
256        field: &HashSet<T>,
257        pos: usize,
258        resolver: Self::Resolver,
259        out: *mut Self::Archived,
260    ) {
261        ArchivedVec::resolve_from_len(field.len(), pos, resolver, out);
262    }
263}
264
265impl<T, S> SerializeWith<HashSet<T>, S> for AsVec
266where
267    T: Serialize<S>,
268    S: ScratchSpace + Serializer + ?Sized,
269{
270    fn serialize_with(field: &HashSet<T>, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
271        ArchivedVec::<T::Archived>::serialize_from_iter::<T, _, _, _>(field.iter(), serializer)
272    }
273}
274
275impl<T, D> DeserializeWith<ArchivedVec<T::Archived>, HashSet<T>, D> for AsVec
276where
277    T: Archive + Hash + Eq,
278    T::Archived: Deserialize<T, D>,
279    D: Fallible + ?Sized,
280{
281    fn deserialize_with(
282        field: &ArchivedVec<T::Archived>,
283        deserializer: &mut D,
284    ) -> Result<HashSet<T>, D::Error> {
285        let mut result = HashSet::with_capacity(field.len());
286        for key in field.iter() {
287            result.insert(key.deserialize(deserializer)?);
288        }
289        Ok(result)
290    }
291}
292
293// UnixTimestamp
294
295impl ArchiveWith<SystemTime> for UnixTimestamp {
296    type Archived = ArchivedDuration;
297    type Resolver = ();
298
299    #[inline]
300    unsafe fn resolve_with(
301        field: &SystemTime,
302        pos: usize,
303        resolver: Self::Resolver,
304        out: *mut Self::Archived,
305    ) {
306        // We already checked the duration during serialize_with
307        let duration = field.duration_since(UNIX_EPOCH).unwrap();
308        Archive::resolve(&duration, pos, resolver, out);
309    }
310}
311
312impl<S: Fallible + ?Sized> SerializeWith<SystemTime, S> for UnixTimestamp
313where
314    S::Error: From<UnixTimestampError>,
315{
316    fn serialize_with(field: &SystemTime, _: &mut S) -> Result<Self::Resolver, S::Error> {
317        field
318            .duration_since(UNIX_EPOCH)
319            .map_err(|_| UnixTimestampError::TimeBeforeUnixEpoch)?;
320        Ok(())
321    }
322}
323
324impl<D: Fallible + ?Sized> DeserializeWith<ArchivedDuration, SystemTime, D> for UnixTimestamp {
325    fn deserialize_with(field: &ArchivedDuration, _: &mut D) -> Result<SystemTime, D::Error> {
326        Ok(UNIX_EPOCH + (*field).into())
327    }
328}