1use core::{marker::PhantomData, ops::ControlFlow};
2
3use ptr_meta::Pointee;
4use rancor::{Fallible, Source};
5
6use crate::{
7 alloc::{
8 borrow::Cow,
9 boxed::Box,
10 collections::{BTreeMap, BTreeSet},
11 rc::Rc,
12 vec::Vec,
13 },
14 collections::{
15 btree_map::{ArchivedBTreeMap, BTreeMapResolver},
16 util::{Entry, EntryAdapter},
17 },
18 impls::core::with::RefWrapper,
19 niche::option_box::{ArchivedOptionBox, OptionBoxResolver},
20 ser::{Allocator, Writer},
21 string::{ArchivedString, StringResolver},
22 traits::LayoutRaw,
23 vec::{ArchivedVec, VecResolver},
24 with::{
25 ArchiveWith, AsOwned, AsVec, DeserializeWith, Map, MapKV, Niche,
26 SerializeWith, Unshare,
27 },
28 Archive, ArchiveUnsized, ArchivedMetadata, Deserialize, DeserializeUnsized,
29 Place, Serialize, SerializeUnsized,
30};
31
32impl<A, B, K, V> ArchiveWith<BTreeMap<K, V>> for MapKV<A, B>
35where
36 A: ArchiveWith<K>,
37 B: ArchiveWith<V>,
38{
39 type Archived = ArchivedBTreeMap<
40 <A as ArchiveWith<K>>::Archived,
41 <B as ArchiveWith<V>>::Archived,
42 >;
43 type Resolver = BTreeMapResolver;
44
45 fn resolve_with(
46 field: &BTreeMap<K, V>,
47 resolver: Self::Resolver,
48 out: Place<Self::Archived>,
49 ) {
50 ArchivedBTreeMap::resolve_from_len(field.len(), resolver, out)
51 }
52}
53
54impl<A, B, K, V, S> SerializeWith<BTreeMap<K, V>, S> for MapKV<A, B>
55where
56 A: ArchiveWith<K> + SerializeWith<K, S>,
57 B: ArchiveWith<V> + SerializeWith<V, S>,
58 <A as ArchiveWith<K>>::Archived: Ord,
59 S: Fallible + Allocator + Writer + ?Sized,
60 S::Error: Source,
61{
62 fn serialize_with(
63 field: &BTreeMap<K, V>,
64 serializer: &mut S,
65 ) -> Result<Self::Resolver, <S as Fallible>::Error> {
66 ArchivedBTreeMap::<_, _, 5>::serialize_from_ordered_iter(
67 field.iter().map(|(k, v)| {
68 (
69 RefWrapper::<'_, A, K>(k, PhantomData::<A>),
70 RefWrapper::<'_, B, V>(v, PhantomData::<B>),
71 )
72 }),
73 serializer,
74 )
75 }
76}
77
78impl<A, B, K, V, D>
79 DeserializeWith<
80 ArchivedBTreeMap<
81 <A as ArchiveWith<K>>::Archived,
82 <B as ArchiveWith<V>>::Archived,
83 >,
84 BTreeMap<K, V>,
85 D,
86 > for MapKV<A, B>
87where
88 A: ArchiveWith<K> + DeserializeWith<<A as ArchiveWith<K>>::Archived, K, D>,
89 B: ArchiveWith<V> + DeserializeWith<<B as ArchiveWith<V>>::Archived, V, D>,
90 K: Ord,
91 D: Fallible + ?Sized,
92{
93 fn deserialize_with(
94 field: &ArchivedBTreeMap<
95 <A as ArchiveWith<K>>::Archived,
96 <B as ArchiveWith<V>>::Archived,
97 >,
98 deserializer: &mut D,
99 ) -> Result<BTreeMap<K, V>, <D as Fallible>::Error> {
100 let mut result = BTreeMap::new();
101 let r = field.visit(|ak, av| {
102 let k = match A::deserialize_with(ak, deserializer) {
103 Ok(k) => k,
104 Err(e) => return ControlFlow::Break(e),
105 };
106 let v = match B::deserialize_with(av, deserializer) {
107 Ok(v) => v,
108 Err(e) => return ControlFlow::Break(e),
109 };
110 result.insert(k, v);
111 ControlFlow::Continue(())
112 });
113 match r {
114 Some(e) => Err(e),
115 None => Ok(result),
116 }
117 }
118}
119
120impl<A, O> ArchiveWith<Vec<O>> for Map<A>
122where
123 A: ArchiveWith<O>,
124{
125 type Archived = ArchivedVec<<A as ArchiveWith<O>>::Archived>;
126 type Resolver = VecResolver;
127
128 fn resolve_with(
129 field: &Vec<O>,
130 resolver: Self::Resolver,
131 out: Place<Self::Archived>,
132 ) {
133 ArchivedVec::resolve_from_len(field.len(), resolver, out)
134 }
135}
136
137impl<A, O, S> SerializeWith<Vec<O>, S> for Map<A>
138where
139 S: Fallible + Allocator + Writer + ?Sized,
140 A: ArchiveWith<O> + SerializeWith<O, S>,
141{
142 fn serialize_with(
143 field: &Vec<O>,
144 s: &mut S,
145 ) -> Result<Self::Resolver, S::Error> {
146 struct RefWrapper<'o, A, O>(&'o O, PhantomData<A>);
150
151 impl<A: ArchiveWith<O>, O> Archive for RefWrapper<'_, A, O> {
152 type Archived = <A as ArchiveWith<O>>::Archived;
153 type Resolver = <A as ArchiveWith<O>>::Resolver;
154
155 fn resolve(
156 &self,
157 resolver: Self::Resolver,
158 out: Place<Self::Archived>,
159 ) {
160 A::resolve_with(self.0, resolver, out)
161 }
162 }
163
164 impl<A, O, S> Serialize<S> for RefWrapper<'_, A, O>
165 where
166 A: ArchiveWith<O> + SerializeWith<O, S>,
167 S: Fallible + Writer + ?Sized,
168 {
169 fn serialize(&self, s: &mut S) -> Result<Self::Resolver, S::Error> {
170 A::serialize_with(self.0, s)
171 }
172 }
173
174 let iter = field
175 .iter()
176 .map(|value| RefWrapper::<'_, A, O>(value, PhantomData));
177
178 ArchivedVec::serialize_from_iter(iter, s)
179 }
180}
181
182impl<A, O, D>
183 DeserializeWith<ArchivedVec<<A as ArchiveWith<O>>::Archived>, Vec<O>, D>
184 for Map<A>
185where
186 A: ArchiveWith<O> + DeserializeWith<<A as ArchiveWith<O>>::Archived, O, D>,
187 D: Fallible + ?Sized,
188{
189 fn deserialize_with(
190 field: &ArchivedVec<<A as ArchiveWith<O>>::Archived>,
191 d: &mut D,
192 ) -> Result<Vec<O>, D::Error> {
193 field
194 .iter()
195 .map(|value| A::deserialize_with(value, d))
196 .collect()
197 }
198}
199
200impl<'a, F: Archive + Clone> ArchiveWith<Cow<'a, F>> for AsOwned {
203 type Archived = F::Archived;
204 type Resolver = F::Resolver;
205
206 fn resolve_with(
207 field: &Cow<'a, F>,
208 resolver: Self::Resolver,
209 out: Place<Self::Archived>,
210 ) {
211 field.resolve(resolver, out);
212 }
213}
214
215impl<'a, F, S> SerializeWith<Cow<'a, F>, S> for AsOwned
216where
217 F: Serialize<S> + Clone,
218 S: Fallible + ?Sized,
219{
220 fn serialize_with(
221 field: &Cow<'a, F>,
222 serializer: &mut S,
223 ) -> Result<Self::Resolver, S::Error> {
224 field.serialize(serializer)
225 }
226}
227
228impl<T, D> DeserializeWith<T::Archived, T, D> for AsOwned
229where
230 T: Archive + Clone,
231 T::Archived: Deserialize<T, D>,
232 D: Fallible + ?Sized,
233{
234 fn deserialize_with(
235 field: &T::Archived,
236 deserializer: &mut D,
237 ) -> Result<T, D::Error> {
238 field.deserialize(deserializer)
239 }
240}
241
242impl<'a, T: Archive + Clone> ArchiveWith<Cow<'a, [T]>> for AsOwned {
243 type Archived = ArchivedVec<T::Archived>;
244 type Resolver = VecResolver;
245
246 fn resolve_with(
247 field: &Cow<'a, [T]>,
248 resolver: Self::Resolver,
249 out: Place<Self::Archived>,
250 ) {
251 ArchivedVec::resolve_from_slice(field, resolver, out);
252 }
253}
254
255impl<'a, T, S> SerializeWith<Cow<'a, [T]>, S> for AsOwned
256where
257 T: Serialize<S> + Clone,
258 S: Fallible + Allocator + Writer + ?Sized,
259{
260 fn serialize_with(
261 field: &Cow<'a, [T]>,
262 serializer: &mut S,
263 ) -> Result<Self::Resolver, S::Error> {
264 ArchivedVec::serialize_from_slice(field, serializer)
265 }
266}
267
268impl<'a, T, D> DeserializeWith<ArchivedVec<T::Archived>, Cow<'a, [T]>, D>
269 for AsOwned
270where
271 T: Archive + Clone,
272 T::Archived: Deserialize<T, D>,
273 D: Fallible + ?Sized,
274 D::Error: Source,
275{
276 fn deserialize_with(
277 field: &ArchivedVec<T::Archived>,
278 deserializer: &mut D,
279 ) -> Result<Cow<'a, [T]>, D::Error> {
280 Ok(Cow::Owned(field.deserialize(deserializer)?))
281 }
282}
283
284impl<'a> ArchiveWith<Cow<'a, str>> for AsOwned {
285 type Archived = ArchivedString;
286 type Resolver = StringResolver;
287
288 fn resolve_with(
289 field: &Cow<'a, str>,
290 resolver: Self::Resolver,
291 out: Place<Self::Archived>,
292 ) {
293 ArchivedString::resolve_from_str(field, resolver, out);
294 }
295}
296
297impl<'a, S> SerializeWith<Cow<'a, str>, S> for AsOwned
298where
299 S: Fallible + Writer + ?Sized,
300 S::Error: Source,
301{
302 fn serialize_with(
303 field: &Cow<'a, str>,
304 serializer: &mut S,
305 ) -> Result<Self::Resolver, S::Error> {
306 ArchivedString::serialize_from_str(field, serializer)
307 }
308}
309
310impl<'a, D> DeserializeWith<ArchivedString, Cow<'a, str>, D> for AsOwned
311where
312 D: Fallible + ?Sized,
313{
314 fn deserialize_with(
315 field: &ArchivedString,
316 deserializer: &mut D,
317 ) -> Result<Cow<'a, str>, D::Error> {
318 Ok(Cow::Owned(field.deserialize(deserializer)?))
319 }
320}
321
322impl<K: Archive, V: Archive> ArchiveWith<BTreeMap<K, V>> for AsVec {
325 type Archived = ArchivedVec<Entry<K::Archived, V::Archived>>;
326 type Resolver = VecResolver;
327
328 fn resolve_with(
329 field: &BTreeMap<K, V>,
330 resolver: Self::Resolver,
331 out: Place<Self::Archived>,
332 ) {
333 ArchivedVec::resolve_from_len(field.len(), resolver, out);
334 }
335}
336
337impl<K, V, S> SerializeWith<BTreeMap<K, V>, S> for AsVec
338where
339 K: Serialize<S>,
340 V: Serialize<S>,
341 S: Fallible + Allocator + Writer + ?Sized,
342{
343 fn serialize_with(
344 field: &BTreeMap<K, V>,
345 serializer: &mut S,
346 ) -> Result<Self::Resolver, S::Error> {
347 ArchivedVec::serialize_from_iter(
348 field.iter().map(|(key, value)| {
349 EntryAdapter::<_, _, K, V>::new(key, value)
350 }),
351 serializer,
352 )
353 }
354}
355
356impl<K, V, D>
357 DeserializeWith<
358 ArchivedVec<Entry<K::Archived, V::Archived>>,
359 BTreeMap<K, V>,
360 D,
361 > for AsVec
362where
363 K: Archive + Ord,
364 V: Archive,
365 K::Archived: Deserialize<K, D>,
366 V::Archived: Deserialize<V, D>,
367 D: Fallible + ?Sized,
368{
369 fn deserialize_with(
370 field: &ArchivedVec<Entry<K::Archived, V::Archived>>,
371 deserializer: &mut D,
372 ) -> Result<BTreeMap<K, V>, D::Error> {
373 let mut result = BTreeMap::new();
374 for entry in field.iter() {
375 result.insert(
376 entry.key.deserialize(deserializer)?,
377 entry.value.deserialize(deserializer)?,
378 );
379 }
380 Ok(result)
381 }
382}
383
384impl<T: Archive> ArchiveWith<BTreeSet<T>> for AsVec {
385 type Archived = ArchivedVec<T::Archived>;
386 type Resolver = VecResolver;
387
388 fn resolve_with(
389 field: &BTreeSet<T>,
390 resolver: Self::Resolver,
391 out: Place<Self::Archived>,
392 ) {
393 ArchivedVec::resolve_from_len(field.len(), resolver, out);
394 }
395}
396
397impl<T, S> SerializeWith<BTreeSet<T>, S> for AsVec
398where
399 T: Serialize<S>,
400 S: Fallible + Allocator + Writer + ?Sized,
401{
402 fn serialize_with(
403 field: &BTreeSet<T>,
404 serializer: &mut S,
405 ) -> Result<Self::Resolver, S::Error> {
406 ArchivedVec::<T::Archived>::serialize_from_iter::<T, _, _>(
407 field.iter(),
408 serializer,
409 )
410 }
411}
412
413impl<T, D> DeserializeWith<ArchivedVec<T::Archived>, BTreeSet<T>, D> for AsVec
414where
415 T: Archive + Ord,
416 T::Archived: Deserialize<T, D>,
417 D: Fallible + ?Sized,
418{
419 fn deserialize_with(
420 field: &ArchivedVec<T::Archived>,
421 deserializer: &mut D,
422 ) -> Result<BTreeSet<T>, D::Error> {
423 let mut result = BTreeSet::new();
424 for key in field.iter() {
425 result.insert(key.deserialize(deserializer)?);
426 }
427 Ok(result)
428 }
429}
430
431impl<T> ArchiveWith<Option<Box<T>>> for Niche
434where
435 T: ArchiveUnsized + ?Sized,
436 ArchivedMetadata<T>: Default,
437{
438 type Archived = ArchivedOptionBox<T::Archived>;
439 type Resolver = OptionBoxResolver;
440
441 fn resolve_with(
442 field: &Option<Box<T>>,
443 resolver: Self::Resolver,
444 out: Place<Self::Archived>,
445 ) {
446 ArchivedOptionBox::resolve_from_option(field.as_deref(), resolver, out);
447 }
448}
449
450impl<T, S> SerializeWith<Option<Box<T>>, S> for Niche
451where
452 T: SerializeUnsized<S> + ?Sized,
453 S: Fallible + Writer + ?Sized,
454 ArchivedMetadata<T>: Default,
455{
456 fn serialize_with(
457 field: &Option<Box<T>>,
458 serializer: &mut S,
459 ) -> Result<Self::Resolver, S::Error> {
460 ArchivedOptionBox::serialize_from_option(field.as_deref(), serializer)
461 }
462}
463
464impl<T, D> DeserializeWith<ArchivedOptionBox<T::Archived>, Option<Box<T>>, D>
465 for Niche
466where
467 T: ArchiveUnsized + LayoutRaw + Pointee + ?Sized,
468 T::Archived: DeserializeUnsized<T, D>,
469 D: Fallible + ?Sized,
470 D::Error: Source,
471{
472 fn deserialize_with(
473 field: &ArchivedOptionBox<T::Archived>,
474 deserializer: &mut D,
475 ) -> Result<Option<Box<T>>, D::Error> {
476 if let Some(value) = field.as_ref() {
477 Ok(Some(value.deserialize(deserializer)?))
478 } else {
479 Ok(None)
480 }
481 }
482}
483
484#[cfg(target_has_atomic = "ptr")]
487impl<T: Archive> ArchiveWith<crate::alloc::sync::Arc<T>> for Unshare {
488 type Archived = T::Archived;
489 type Resolver = T::Resolver;
490
491 fn resolve_with(
492 x: &crate::alloc::sync::Arc<T>,
493 resolver: Self::Resolver,
494 out: Place<Self::Archived>,
495 ) {
496 x.as_ref().resolve(resolver, out)
497 }
498}
499
500#[cfg(target_has_atomic = "ptr")]
501impl<T, S> SerializeWith<crate::alloc::sync::Arc<T>, S> for Unshare
502where
503 T: Serialize<S>,
504 S: Fallible + ?Sized,
505{
506 fn serialize_with(
507 x: &crate::alloc::sync::Arc<T>,
508 s: &mut S,
509 ) -> Result<Self::Resolver, S::Error> {
510 x.as_ref().serialize(s)
511 }
512}
513
514#[cfg(target_has_atomic = "ptr")]
515impl<A, T, D> DeserializeWith<A, crate::alloc::sync::Arc<T>, D> for Unshare
516where
517 A: Deserialize<T, D>,
518 D: Fallible + ?Sized,
519{
520 fn deserialize_with(
521 x: &A,
522 d: &mut D,
523 ) -> Result<crate::alloc::sync::Arc<T>, D::Error> {
524 Ok(crate::alloc::sync::Arc::new(A::deserialize(x, d)?))
525 }
526}
527
528impl<T: Archive> ArchiveWith<Rc<T>> for Unshare {
529 type Archived = T::Archived;
530 type Resolver = T::Resolver;
531
532 fn resolve_with(
533 x: &Rc<T>,
534 resolver: Self::Resolver,
535 out: Place<Self::Archived>,
536 ) {
537 x.as_ref().resolve(resolver, out)
538 }
539}
540
541impl<T: Serialize<S>, S: Fallible + ?Sized> SerializeWith<Rc<T>, S>
542 for Unshare
543{
544 fn serialize_with(
545 x: &Rc<T>,
546 s: &mut S,
547 ) -> Result<Self::Resolver, S::Error> {
548 x.as_ref().serialize(s)
549 }
550}
551
552impl<A, T, D> DeserializeWith<A, Rc<T>, D> for Unshare
553where
554 A: Deserialize<T, D>,
555 D: Fallible + ?Sized,
556{
557 fn deserialize_with(x: &A, d: &mut D) -> Result<Rc<T>, D::Error> {
558 Ok(Rc::new(A::deserialize(x, d)?))
559 }
560}
561
562#[cfg(test)]
563mod tests {
564 use core::mem::size_of;
565
566 use crate::{
567 alloc::{
568 borrow::Cow,
569 boxed::Box,
570 collections::{BTreeMap, BTreeSet},
571 string::{String, ToString},
572 },
573 api::test::{roundtrip, roundtrip_with, to_archived},
574 niche::niching::Null,
575 with::{
576 AsOwned, AsVec, DefaultNiche, InlineAsBox, Map, MapKV, Niche,
577 NicheInto,
578 },
579 Archive, Deserialize, Serialize,
580 };
581
582 #[derive(Debug, Archive, Deserialize, Serialize, PartialEq)]
583 #[rkyv(crate, compare(PartialEq), derive(Debug))]
584 struct Test {
585 value: Option<Box<u128>>,
586 }
587
588 #[test]
589 fn roundtrip_niche_none() {
590 roundtrip(&Test { value: None });
591 }
592
593 #[test]
594 fn roundtrip_niche_some() {
595 roundtrip(&Test {
596 value: Some(Box::new(128)),
597 });
598 }
599
600 #[test]
601 fn ambiguous_niched_archived_box() {
602 #[derive(Archive, Deserialize, Serialize, Debug, PartialEq)]
603 #[rkyv(crate, compare(PartialEq), derive(Debug))]
604 struct HasNiche {
605 #[rkyv(with = Niche)]
606 inner: Option<Box<[u32]>>,
607 }
608
609 roundtrip(&HasNiche {
610 inner: Some(Box::<[u32]>::from([])),
611 });
612 roundtrip(&HasNiche { inner: None });
613 }
614
615 #[test]
616 fn with_as_owned() {
617 #[derive(Archive, Serialize, Deserialize)]
618 #[rkyv(crate)]
619 struct Test<'a> {
620 #[rkyv(with = AsOwned)]
621 a: Cow<'a, u32>,
622 #[rkyv(with = AsOwned)]
623 b: Cow<'a, [u32]>,
624 #[rkyv(with = AsOwned)]
625 c: Cow<'a, str>,
626 }
627
628 let value = Test {
629 a: Cow::Borrowed(&100),
630 b: Cow::Borrowed(&[1, 2, 3, 4, 5, 6]),
631 c: Cow::Borrowed("hello world"),
632 };
633 to_archived(&value, |archived| {
634 assert_eq!(archived.a, 100);
635 assert_eq!(archived.b, [1, 2, 3, 4, 5, 6]);
636 assert_eq!(archived.c, "hello world");
637 });
638 }
639
640 #[test]
641 fn with_as_map() {
642 #[derive(Archive, Serialize, Deserialize)]
643 #[rkyv(crate)]
644 struct Test<'a> {
645 #[rkyv(with = Map<InlineAsBox>)]
646 a: Option<&'a str>,
647 #[rkyv(with = Map<InlineAsBox>)]
648 b: Option<&'a str>,
649 }
650
651 let value = Test {
652 a: Some("foo"),
653 b: None,
654 };
655
656 to_archived(&value, |archived| {
657 assert!(archived.a.is_some());
658 assert!(archived.b.is_none());
659 });
660 }
661
662 #[test]
663 fn with_as_mapkv() {
664 #[derive(Archive, Serialize, Deserialize)]
665 #[rkyv(crate)]
666 struct Test<'a> {
667 #[rkyv(with = MapKV<InlineAsBox, InlineAsBox>)]
668 a: BTreeMap<&'a str, &'a str>,
669 }
670
671 let mut a = BTreeMap::new();
672 a.insert("foo", "bar");
673 a.insert("woo", "roo");
674
675 let value = Test { a };
676
677 to_archived(&value, |archived| {
678 assert_eq!(archived.a.len(), 2);
679 assert!(archived.a.contains_key("foo"));
680 assert_eq!(**archived.a.get("woo").unwrap(), *"roo");
681 });
682 }
683
684 #[test]
685 fn with_as_vec() {
686 #[derive(Archive, Serialize, Deserialize)]
687 #[rkyv(crate)]
688 struct Test {
689 #[rkyv(with = AsVec)]
690 a: BTreeMap<String, String>,
691 #[rkyv(with = AsVec)]
692 b: BTreeSet<String>,
693 #[rkyv(with = AsVec)]
694 c: BTreeMap<String, String>,
695 }
696
697 let mut a = BTreeMap::new();
698 a.insert("foo".to_string(), "hello".to_string());
699 a.insert("bar".to_string(), "world".to_string());
700 a.insert("baz".to_string(), "bat".to_string());
701
702 let mut b = BTreeSet::new();
703 b.insert("foo".to_string());
704 b.insert("hello world!".to_string());
705 b.insert("bar".to_string());
706 b.insert("fizzbuzz".to_string());
707
708 let c = BTreeMap::new();
709
710 let value = Test { a, b, c };
711
712 to_archived(&value, |archived| {
713 assert_eq!(archived.a.len(), 3);
714 assert!(archived
715 .a
716 .iter()
717 .find(|&e| e.key == "foo" && e.value == "hello")
718 .is_some());
719 assert!(archived
720 .a
721 .iter()
722 .find(|&e| e.key == "bar" && e.value == "world")
723 .is_some());
724 assert!(archived
725 .a
726 .iter()
727 .find(|&e| e.key == "baz" && e.value == "bat")
728 .is_some());
729
730 assert_eq!(archived.b.len(), 4);
731 assert!(archived.b.iter().find(|&e| e == "foo").is_some());
732 assert!(archived.b.iter().find(|&e| e == "hello world!").is_some());
733 assert!(archived.b.iter().find(|&e| e == "bar").is_some());
734 assert!(archived.b.iter().find(|&e| e == "fizzbuzz").is_some());
735 });
736 }
737
738 #[cfg(feature = "alloc")]
739 #[test]
740 fn with_niche_box() {
741 #[derive(Archive, Serialize, Deserialize)]
742 #[rkyv(crate)]
743 struct TestNiche {
744 #[rkyv(with = Niche)]
745 inner: Option<Box<String>>,
746 }
747
748 #[derive(Archive, Serialize, Deserialize)]
749 #[rkyv(crate)]
750 struct TestNullNiche {
751 #[rkyv(with = NicheInto<Null>)]
752 inner: Option<Box<String>>,
753 }
754
755 #[derive(Archive, Serialize, Deserialize)]
756 #[rkyv(crate)]
757 struct TestNoNiching {
758 inner: Option<Box<String>>,
759 }
760
761 let value = TestNiche {
762 inner: Some(Box::new("hello world".to_string())),
763 };
764 to_archived(&value, |archived| {
765 assert!(archived.inner.is_some());
766 assert_eq!(&**archived.inner.as_ref().unwrap(), "hello world");
767 assert_eq!(archived.inner, value.inner);
768 });
769
770 let value = TestNiche { inner: None };
771 to_archived(&value, |archived| {
772 assert!(archived.inner.is_none());
773 assert_eq!(archived.inner, value.inner);
774 });
775 assert!(
776 size_of::<ArchivedTestNiche>() < size_of::<ArchivedTestNoNiching>()
777 );
778
779 let value = TestNullNiche {
780 inner: Some(Box::new("hello world".to_string())),
781 };
782 to_archived(&value, |archived| {
783 assert!(archived.inner.is_some());
784 assert_eq!(&**archived.inner.as_ref().unwrap(), "hello world");
785 assert_eq!(archived.inner, value.inner);
786 });
787
788 let value = TestNullNiche { inner: None };
789 to_archived(&value, |archived| {
790 assert!(archived.inner.is_none());
791 assert_eq!(archived.inner, value.inner);
792 });
793 assert!(
794 size_of::<ArchivedTestNullNiche>()
795 < size_of::<ArchivedTestNoNiching>()
796 );
797 }
798
799 #[test]
800 fn with_null_niching() {
801 #[derive(Archive, Serialize, Deserialize, Debug, PartialEq)]
802 #[rkyv(crate, derive(Debug))]
803 struct Nichable {
804 #[rkyv(niche)] boxed: Box<i32>,
806 }
807
808 #[derive(Archive, Serialize, Deserialize, Debug, PartialEq)]
809 #[rkyv(crate, derive(Debug))]
810 struct Outer {
811 #[rkyv(with = DefaultNiche)]
812 field: Option<Nichable>,
813 }
814
815 assert_eq!(size_of::<ArchivedNichable>(), size_of::<ArchivedOuter>());
816
817 let values = [
818 Outer { field: None },
819 Outer {
820 field: Some(Nichable {
821 boxed: Box::new(727),
822 }),
823 },
824 ];
825
826 roundtrip_with(&values[0], |_, archived| {
827 assert!(archived.field.is_none());
828 });
829 roundtrip_with(&values[1], |_, archived| {
830 let nichable = archived.field.as_ref().unwrap();
831 assert_eq!(nichable.boxed.as_ref().to_native(), 727);
832 });
833 }
834}