rkyv/impls/core/
ops.rs

1use core::{
2    hint::unreachable_unchecked,
3    ops::{
4        Bound, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo,
5        RangeToInclusive,
6    },
7};
8
9use munge::munge;
10use rancor::Fallible;
11
12use crate::{
13    ops::{
14        ArchivedBound, ArchivedRange, ArchivedRangeFrom, ArchivedRangeFull,
15        ArchivedRangeInclusive, ArchivedRangeTo, ArchivedRangeToInclusive,
16    },
17    traits::{CopyOptimization, NoUndef},
18    Archive, Deserialize, Place, Serialize,
19};
20
21// RangeFull
22
23impl Archive for RangeFull {
24    const COPY_OPTIMIZATION: CopyOptimization<Self> =
25        unsafe { CopyOptimization::enable() };
26
27    type Archived = ArchivedRangeFull;
28    type Resolver = ();
29
30    #[inline]
31    fn resolve(&self, _: Self::Resolver, _: Place<Self::Archived>) {}
32}
33
34impl<S: Fallible + ?Sized> Serialize<S> for RangeFull {
35    fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
36        Ok(())
37    }
38}
39
40impl<D: Fallible + ?Sized> Deserialize<RangeFull, D> for ArchivedRangeFull {
41    fn deserialize(&self, _: &mut D) -> Result<RangeFull, D::Error> {
42        Ok(RangeFull)
43    }
44}
45
46impl PartialEq<RangeFull> for ArchivedRangeFull {
47    fn eq(&self, _: &RangeFull) -> bool {
48        true
49    }
50}
51
52// Range
53
54impl<T: Archive> Archive for Range<T> {
55    type Archived = ArchivedRange<T::Archived>;
56    type Resolver = Range<T::Resolver>;
57
58    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
59        munge!(let ArchivedRange { start, end } = out);
60        self.start.resolve(resolver.start, start);
61        self.end.resolve(resolver.end, end);
62    }
63}
64
65impl<T: Serialize<S>, S: Fallible + ?Sized> Serialize<S> for Range<T> {
66    fn serialize(
67        &self,
68        serializer: &mut S,
69    ) -> Result<Self::Resolver, S::Error> {
70        Ok(Range {
71            start: self.start.serialize(serializer)?,
72            end: self.end.serialize(serializer)?,
73        })
74    }
75}
76
77impl<T, D> Deserialize<Range<T>, D> for ArchivedRange<T::Archived>
78where
79    T: Archive,
80    T::Archived: Deserialize<T, D>,
81    D: Fallible + ?Sized,
82{
83    fn deserialize(&self, deserializer: &mut D) -> Result<Range<T>, D::Error> {
84        Ok(Range {
85            start: self.start.deserialize(deserializer)?,
86            end: self.end.deserialize(deserializer)?,
87        })
88    }
89}
90
91impl<T, U: PartialEq<T>> PartialEq<Range<T>> for ArchivedRange<U> {
92    fn eq(&self, other: &Range<T>) -> bool {
93        self.start.eq(&other.start) && self.end.eq(&other.end)
94    }
95}
96
97// RangeInclusive
98
99impl<T: Archive> Archive for RangeInclusive<T> {
100    type Archived = ArchivedRangeInclusive<T::Archived>;
101    type Resolver = Range<T::Resolver>;
102
103    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
104        munge!(let ArchivedRangeInclusive { start, end } = out);
105        self.start().resolve(resolver.start, start);
106        self.end().resolve(resolver.end, end);
107    }
108}
109
110impl<T: Serialize<S>, S: Fallible + ?Sized> Serialize<S> for RangeInclusive<T> {
111    fn serialize(
112        &self,
113        serializer: &mut S,
114    ) -> Result<Self::Resolver, S::Error> {
115        Ok(Range {
116            start: self.start().serialize(serializer)?,
117            end: self.end().serialize(serializer)?,
118        })
119    }
120}
121
122impl<T, D> Deserialize<RangeInclusive<T>, D>
123    for ArchivedRangeInclusive<T::Archived>
124where
125    T: Archive,
126    T::Archived: Deserialize<T, D>,
127    D: Fallible + ?Sized,
128{
129    fn deserialize(
130        &self,
131        deserializer: &mut D,
132    ) -> Result<RangeInclusive<T>, D::Error> {
133        Ok(RangeInclusive::new(
134            self.start.deserialize(deserializer)?,
135            self.end.deserialize(deserializer)?,
136        ))
137    }
138}
139
140impl<T, U> PartialEq<RangeInclusive<T>> for ArchivedRangeInclusive<U>
141where
142    U: PartialEq<T>,
143{
144    fn eq(&self, other: &RangeInclusive<T>) -> bool {
145        self.start.eq(other.start()) && self.end.eq(other.end())
146    }
147}
148
149// RangeFrom
150
151impl<T: Archive> Archive for RangeFrom<T> {
152    type Archived = ArchivedRangeFrom<T::Archived>;
153    type Resolver = RangeFrom<T::Resolver>;
154
155    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
156        munge!(let ArchivedRangeFrom { start } = out);
157        self.start.resolve(resolver.start, start);
158    }
159}
160
161impl<T: Serialize<S>, S: Fallible + ?Sized> Serialize<S> for RangeFrom<T> {
162    fn serialize(
163        &self,
164        serializer: &mut S,
165    ) -> Result<Self::Resolver, S::Error> {
166        Ok(RangeFrom {
167            start: self.start.serialize(serializer)?,
168        })
169    }
170}
171
172impl<T, D> Deserialize<RangeFrom<T>, D> for ArchivedRangeFrom<T::Archived>
173where
174    T: Archive,
175    D: Fallible + ?Sized,
176    T::Archived: Deserialize<T, D>,
177{
178    fn deserialize(
179        &self,
180        deserializer: &mut D,
181    ) -> Result<RangeFrom<T>, D::Error> {
182        Ok(RangeFrom {
183            start: self.start.deserialize(deserializer)?,
184        })
185    }
186}
187
188impl<T, U: PartialEq<T>> PartialEq<RangeFrom<T>> for ArchivedRangeFrom<U> {
189    fn eq(&self, other: &RangeFrom<T>) -> bool {
190        self.start.eq(&other.start)
191    }
192}
193
194// RangeTo
195
196impl<T: Archive> Archive for RangeTo<T> {
197    type Archived = ArchivedRangeTo<T::Archived>;
198    type Resolver = RangeTo<T::Resolver>;
199
200    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
201        munge!(let ArchivedRangeTo { end } = out);
202        self.end.resolve(resolver.end, end);
203    }
204}
205
206impl<T: Serialize<S>, S: Fallible + ?Sized> Serialize<S> for RangeTo<T> {
207    fn serialize(
208        &self,
209        serializer: &mut S,
210    ) -> Result<Self::Resolver, S::Error> {
211        Ok(RangeTo {
212            end: self.end.serialize(serializer)?,
213        })
214    }
215}
216
217impl<T, D> Deserialize<RangeTo<T>, D> for ArchivedRangeTo<T::Archived>
218where
219    T: Archive,
220    D: Fallible + ?Sized,
221    T::Archived: Deserialize<T, D>,
222{
223    fn deserialize(
224        &self,
225        deserializer: &mut D,
226    ) -> Result<RangeTo<T>, D::Error> {
227        Ok(RangeTo {
228            end: self.end.deserialize(deserializer)?,
229        })
230    }
231}
232
233impl<T, U: PartialEq<T>> PartialEq<RangeTo<T>> for ArchivedRangeTo<U> {
234    fn eq(&self, other: &RangeTo<T>) -> bool {
235        self.end.eq(&other.end)
236    }
237}
238
239// RangeToInclusive
240
241impl<T: Archive> Archive for RangeToInclusive<T> {
242    type Archived = ArchivedRangeToInclusive<T::Archived>;
243    type Resolver = RangeToInclusive<T::Resolver>;
244
245    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
246        munge!(let ArchivedRangeToInclusive { end } = out);
247        self.end.resolve(resolver.end, end);
248    }
249}
250
251impl<T, S> Serialize<S> for RangeToInclusive<T>
252where
253    T: Serialize<S>,
254    S: Fallible + ?Sized,
255{
256    fn serialize(
257        &self,
258        serializer: &mut S,
259    ) -> Result<Self::Resolver, S::Error> {
260        Ok(RangeToInclusive {
261            end: self.end.serialize(serializer)?,
262        })
263    }
264}
265
266impl<T, D> Deserialize<RangeToInclusive<T>, D>
267    for ArchivedRangeToInclusive<T::Archived>
268where
269    T: Archive,
270    T::Archived: Deserialize<T, D>,
271    D: Fallible + ?Sized,
272{
273    fn deserialize(
274        &self,
275        deserializer: &mut D,
276    ) -> Result<RangeToInclusive<T>, D::Error> {
277        Ok(RangeToInclusive {
278            end: self.end.deserialize(deserializer)?,
279        })
280    }
281}
282
283impl<T, U> PartialEq<RangeToInclusive<T>> for ArchivedRangeToInclusive<U>
284where
285    U: PartialEq<T>,
286{
287    fn eq(&self, other: &RangeToInclusive<T>) -> bool {
288        self.end.eq(&other.end)
289    }
290}
291
292// Bound
293
294#[allow(dead_code)]
295#[repr(u8)]
296enum ArchivedBoundTag {
297    Included,
298    Excluded,
299    Unbounded,
300}
301
302// SAFETY: `ArchivedBoundTag` is `repr(u8)` and so always consists of a single
303// well-defined byte.
304unsafe impl NoUndef for ArchivedBoundTag {}
305
306#[repr(C)]
307struct ArchivedBoundVariantIncluded<T>(ArchivedBoundTag, T);
308
309#[repr(C)]
310struct ArchivedBoundVariantExcluded<T>(ArchivedBoundTag, T);
311
312#[repr(C)]
313struct ArchivedBoundVariantUnbounded(ArchivedBoundTag);
314
315impl<T: Archive> Archive for Bound<T> {
316    type Archived = ArchivedBound<T::Archived>;
317    type Resolver = Bound<T::Resolver>;
318
319    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
320        match resolver {
321            Bound::Included(resolver) => {
322                let out = unsafe {
323                    out.cast_unchecked::<
324                    ArchivedBoundVariantIncluded<T::Archived>
325                >()
326                };
327                munge!(let ArchivedBoundVariantIncluded(tag, out_value) = out);
328                tag.write(ArchivedBoundTag::Included);
329
330                let value = if let Bound::Included(value) = self.as_ref() {
331                    value
332                } else {
333                    unsafe {
334                        unreachable_unchecked();
335                    }
336                };
337
338                value.resolve(resolver, out_value);
339            }
340            Bound::Excluded(resolver) => {
341                let out = unsafe {
342                    out.cast_unchecked::<
343                    ArchivedBoundVariantExcluded<T::Archived>
344                >()
345                };
346                munge!(let ArchivedBoundVariantExcluded(tag, out_value) = out);
347                tag.write(ArchivedBoundTag::Excluded);
348
349                let value = if let Bound::Excluded(value) = self.as_ref() {
350                    value
351                } else {
352                    unsafe {
353                        unreachable_unchecked();
354                    }
355                };
356
357                value.resolve(resolver, out_value);
358            }
359            Bound::Unbounded => {
360                let out = unsafe {
361                    out.cast_unchecked::<ArchivedBoundVariantUnbounded>()
362                };
363                munge!(let ArchivedBoundVariantUnbounded(tag) = out);
364                tag.write(ArchivedBoundTag::Unbounded);
365            }
366        }
367    }
368}
369
370impl<T: Serialize<S>, S: Fallible + ?Sized> Serialize<S> for Bound<T> {
371    fn serialize(
372        &self,
373        serializer: &mut S,
374    ) -> Result<Self::Resolver, S::Error> {
375        match self.as_ref() {
376            Bound::Included(x) => x.serialize(serializer).map(Bound::Included),
377            Bound::Excluded(x) => x.serialize(serializer).map(Bound::Excluded),
378            Bound::Unbounded => Ok(Bound::Unbounded),
379        }
380    }
381}
382
383impl<T, D> Deserialize<Bound<T>, D> for ArchivedBound<T::Archived>
384where
385    T: Archive,
386    T::Archived: Deserialize<T, D>,
387    D: Fallible + ?Sized,
388{
389    fn deserialize(
390        &self,
391        deserializer: &mut D,
392    ) -> Result<Bound<T>, <D as Fallible>::Error> {
393        Ok(match self {
394            ArchivedBound::Included(value) => {
395                Bound::Included(value.deserialize(deserializer)?)
396            }
397            ArchivedBound::Excluded(value) => {
398                Bound::Excluded(value.deserialize(deserializer)?)
399            }
400            ArchivedBound::Unbounded => Bound::Unbounded,
401        })
402    }
403}
404
405impl<T, U> PartialEq<Bound<T>> for ArchivedBound<U>
406where
407    U: PartialEq<T>,
408{
409    fn eq(&self, other: &Bound<T>) -> bool {
410        match (self, other) {
411            (ArchivedBound::Included(this), Bound::Included(other))
412            | (ArchivedBound::Excluded(this), Bound::Excluded(other)) => {
413                this.eq(other)
414            }
415            (ArchivedBound::Unbounded, Bound::Unbounded) => true,
416            _ => false,
417        }
418    }
419}
420
421#[cfg(test)]
422mod tests {
423    use core::ops::Bound;
424
425    use crate::api::test::roundtrip;
426
427    #[test]
428    fn roundtrip_ranges() {
429        roundtrip(&..);
430        roundtrip(&(0u8..100u8));
431        roundtrip(&(0u8..=100u8));
432        roundtrip(&(0u8..));
433        roundtrip(&(..100u8));
434        roundtrip(&(..=100u8));
435    }
436
437    #[test]
438    fn roundtrip_bound() {
439        roundtrip(&Bound::Included(100u8));
440        roundtrip(&Bound::Excluded(100u8));
441        roundtrip(&Bound::<u8>::Unbounded);
442    }
443}