1use std::{any::Any, sync::Arc};
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
12#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
13pub struct TypeId(u64);
14
15impl TypeId {
16 #[inline]
17 pub fn of<T: Any + 'static>() -> Self {
18 std::any::TypeId::of::<T>().into()
19 }
20
21 #[inline(always)]
22 pub(crate) fn value(&self) -> u64 {
23 self.0
24 }
25}
26
27impl From<std::any::TypeId> for TypeId {
28 #[inline]
29 fn from(id: std::any::TypeId) -> Self {
30 Self(epaint::util::hash(id))
31 }
32}
33
34impl nohash_hasher::IsEnabled for TypeId {}
35
36#[cfg(feature = "persistence")]
39pub trait SerializableAny:
40 'static + Any + Clone + serde::Serialize + for<'a> serde::Deserialize<'a> + Send + Sync
41{
42}
43
44#[cfg(feature = "persistence")]
45impl<T> SerializableAny for T where
46 T: 'static + Any + Clone + serde::Serialize + for<'a> serde::Deserialize<'a> + Send + Sync
47{
48}
49
50#[cfg(not(feature = "persistence"))]
51pub trait SerializableAny: 'static + Any + Clone + for<'a> Send + Sync {}
52
53#[cfg(not(feature = "persistence"))]
54impl<T> SerializableAny for T where T: 'static + Any + Clone + for<'a> Send + Sync {}
55
56#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
59#[derive(Clone, Debug)]
60struct SerializedElement {
61 type_id: TypeId,
63
64 ron: Arc<str>,
66
67 generation: usize,
73}
74
75#[cfg(feature = "persistence")]
76type Serializer = fn(&Box<dyn Any + 'static + Send + Sync>) -> Option<String>;
77
78enum Element {
79 Value {
81 value: Box<dyn Any + 'static + Send + Sync>,
83
84 clone_fn: fn(&Box<dyn Any + 'static + Send + Sync>) -> Box<dyn Any + 'static + Send + Sync>,
86
87 #[cfg(feature = "persistence")]
90 serialize_fn: Option<Serializer>,
91 },
92
93 Serialized(SerializedElement),
95}
96
97impl Clone for Element {
98 fn clone(&self) -> Self {
99 match &self {
100 Self::Value {
101 value,
102 clone_fn,
103 #[cfg(feature = "persistence")]
104 serialize_fn,
105 } => Self::Value {
106 value: clone_fn(value),
107 clone_fn: *clone_fn,
108 #[cfg(feature = "persistence")]
109 serialize_fn: *serialize_fn,
110 },
111
112 Self::Serialized(element) => Self::Serialized(element.clone()),
113 }
114 }
115}
116
117impl std::fmt::Debug for Element {
118 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 match &self {
120 Self::Value { value, .. } => f
121 .debug_struct("Element::Value")
122 .field("type_id", &(**value).type_id())
123 .finish_non_exhaustive(),
124 Self::Serialized(SerializedElement {
125 type_id,
126 ron,
127 generation,
128 }) => f
129 .debug_struct("Element::Serialized")
130 .field("type_id", type_id)
131 .field("ron", ron)
132 .field("generation", generation)
133 .finish(),
134 }
135 }
136}
137
138impl Element {
139 #[inline]
141 pub(crate) fn new_temp<T: 'static + Any + Clone + Send + Sync>(t: T) -> Self {
142 Self::Value {
143 value: Box::new(t),
144 clone_fn: |x| {
145 let x = x.downcast_ref::<T>().unwrap(); Box::new(x.clone())
147 },
148 #[cfg(feature = "persistence")]
149 serialize_fn: None,
150 }
151 }
152
153 #[inline]
155 pub(crate) fn new_persisted<T: SerializableAny>(t: T) -> Self {
156 Self::Value {
157 value: Box::new(t),
158 clone_fn: |x| {
159 let x = x.downcast_ref::<T>().unwrap(); Box::new(x.clone())
161 },
162 #[cfg(feature = "persistence")]
163 serialize_fn: Some(|x| {
164 let x = x.downcast_ref::<T>().unwrap(); ron::to_string(x).ok()
166 }),
167 }
168 }
169
170 #[inline]
172 pub(crate) fn type_id(&self) -> TypeId {
173 match self {
174 Self::Value { value, .. } => (**value).type_id().into(),
175 Self::Serialized(SerializedElement { type_id, .. }) => *type_id,
176 }
177 }
178
179 #[inline]
180 pub(crate) fn get_temp<T: 'static>(&self) -> Option<&T> {
181 match self {
182 Self::Value { value, .. } => value.downcast_ref(),
183 Self::Serialized(_) => None,
184 }
185 }
186
187 #[inline]
188 pub(crate) fn get_mut_temp<T: 'static>(&mut self) -> Option<&mut T> {
189 match self {
190 Self::Value { value, .. } => value.downcast_mut(),
191 Self::Serialized(_) => None,
192 }
193 }
194
195 #[inline]
196 pub(crate) fn get_temp_mut_or_insert_with<T: 'static + Any + Clone + Send + Sync>(
197 &mut self,
198 insert_with: impl FnOnce() -> T,
199 ) -> &mut T {
200 match self {
201 Self::Value { value, .. } => {
202 if !value.is::<T>() {
203 *self = Self::new_temp(insert_with());
204 }
205 }
206 Self::Serialized(_) => {
207 *self = Self::new_temp(insert_with());
208 }
209 }
210
211 match self {
212 Self::Value { value, .. } => value.downcast_mut().unwrap(), Self::Serialized(_) => unreachable!(),
214 }
215 }
216
217 #[inline]
218 pub(crate) fn get_persisted_mut_or_insert_with<T: SerializableAny>(
219 &mut self,
220 insert_with: impl FnOnce() -> T,
221 ) -> &mut T {
222 match self {
223 Self::Value { value, .. } => {
224 if !value.is::<T>() {
225 *self = Self::new_persisted(insert_with());
226 }
227 }
228
229 #[cfg(feature = "persistence")]
230 Self::Serialized(SerializedElement { ron, .. }) => {
231 *self = Self::new_persisted(from_ron_str::<T>(ron).unwrap_or_else(insert_with));
232 }
233
234 #[cfg(not(feature = "persistence"))]
235 Self::Serialized(_) => {
236 *self = Self::new_persisted(insert_with());
237 }
238 }
239
240 match self {
241 Self::Value { value, .. } => value.downcast_mut().unwrap(), Self::Serialized(_) => unreachable!(),
243 }
244 }
245
246 pub(crate) fn get_mut_persisted<T: SerializableAny>(&mut self) -> Option<&mut T> {
247 match self {
248 Self::Value { value, .. } => value.downcast_mut(),
249
250 #[cfg(feature = "persistence")]
251 Self::Serialized(SerializedElement { ron, .. }) => {
252 *self = Self::new_persisted(from_ron_str::<T>(ron)?);
253
254 match self {
255 Self::Value { value, .. } => value.downcast_mut(),
256 Self::Serialized(_) => unreachable!(),
257 }
258 }
259
260 #[cfg(not(feature = "persistence"))]
261 Self::Serialized(_) => None,
262 }
263 }
264
265 #[cfg(feature = "persistence")]
266 fn to_serialize(&self) -> Option<SerializedElement> {
267 match self {
268 Self::Value {
269 value,
270 serialize_fn,
271 ..
272 } => {
273 if let Some(serialize_fn) = serialize_fn {
274 let ron = serialize_fn(value)?;
275 Some(SerializedElement {
276 type_id: (**value).type_id().into(),
277 ron: ron.into(),
278 generation: 1,
279 })
280 } else {
281 None
282 }
283 }
284 Self::Serialized(element) => Some(element.clone()),
285 }
286 }
287}
288
289#[cfg(feature = "persistence")]
290fn from_ron_str<T: serde::de::DeserializeOwned>(ron: &str) -> Option<T> {
291 match ron::from_str::<T>(ron) {
292 Ok(value) => Some(value),
293 Err(_err) => {
294 log::warn!(
295 "egui: Failed to deserialize {} from memory: {}, ron error: {:?}",
296 std::any::type_name::<T>(),
297 _err,
298 ron
299 );
300 None
301 }
302 }
303}
304
305use crate::Id;
308
309#[derive(Clone, Debug)]
349pub struct IdTypeMap {
351 map: nohash_hasher::IntMap<u64, Element>,
352
353 max_bytes_per_type: usize,
354}
355
356impl Default for IdTypeMap {
357 fn default() -> Self {
358 Self {
359 map: Default::default(),
360 max_bytes_per_type: 256 * 1024,
361 }
362 }
363}
364
365impl IdTypeMap {
366 #[inline]
368 pub fn insert_temp<T: 'static + Any + Clone + Send + Sync>(&mut self, id: Id, value: T) {
369 let hash = hash(TypeId::of::<T>(), id);
370 self.map.insert(hash, Element::new_temp(value));
371 }
372
373 #[inline]
375 pub fn insert_persisted<T: SerializableAny>(&mut self, id: Id, value: T) {
376 let hash = hash(TypeId::of::<T>(), id);
377 self.map.insert(hash, Element::new_persisted(value));
378 }
379
380 #[inline]
384 pub fn get_temp<T: 'static + Clone>(&self, id: Id) -> Option<T> {
385 let hash = hash(TypeId::of::<T>(), id);
386 self.map.get(&hash).and_then(|x| x.get_temp()).cloned()
387 }
388
389 #[inline]
396 pub fn get_persisted<T: SerializableAny>(&mut self, id: Id) -> Option<T> {
397 let hash = hash(TypeId::of::<T>(), id);
398 self.map
399 .get_mut(&hash)
400 .and_then(|x| x.get_mut_persisted())
401 .cloned()
402 }
403
404 #[inline]
405 pub fn get_temp_mut_or<T: 'static + Any + Clone + Send + Sync>(
406 &mut self,
407 id: Id,
408 or_insert: T,
409 ) -> &mut T {
410 self.get_temp_mut_or_insert_with(id, || or_insert)
411 }
412
413 #[inline]
414 pub fn get_persisted_mut_or<T: SerializableAny>(&mut self, id: Id, or_insert: T) -> &mut T {
415 self.get_persisted_mut_or_insert_with(id, || or_insert)
416 }
417
418 #[inline]
419 pub fn get_temp_mut_or_default<T: 'static + Any + Clone + Send + Sync + Default>(
420 &mut self,
421 id: Id,
422 ) -> &mut T {
423 self.get_temp_mut_or_insert_with(id, Default::default)
424 }
425
426 #[inline]
427 pub fn get_persisted_mut_or_default<T: SerializableAny + Default>(&mut self, id: Id) -> &mut T {
428 self.get_persisted_mut_or_insert_with(id, Default::default)
429 }
430
431 pub fn get_temp_mut_or_insert_with<T: 'static + Any + Clone + Send + Sync>(
432 &mut self,
433 id: Id,
434 insert_with: impl FnOnce() -> T,
435 ) -> &mut T {
436 let hash = hash(TypeId::of::<T>(), id);
437 use std::collections::hash_map::Entry;
438 match self.map.entry(hash) {
439 Entry::Vacant(vacant) => vacant
440 .insert(Element::new_temp(insert_with()))
441 .get_mut_temp()
442 .unwrap(), Entry::Occupied(occupied) => {
444 occupied.into_mut().get_temp_mut_or_insert_with(insert_with)
445 }
446 }
447 }
448
449 pub fn get_persisted_mut_or_insert_with<T: SerializableAny>(
450 &mut self,
451 id: Id,
452 insert_with: impl FnOnce() -> T,
453 ) -> &mut T {
454 let hash = hash(TypeId::of::<T>(), id);
455 use std::collections::hash_map::Entry;
456 match self.map.entry(hash) {
457 Entry::Vacant(vacant) => vacant
458 .insert(Element::new_persisted(insert_with()))
459 .get_mut_persisted()
460 .unwrap(), Entry::Occupied(occupied) => occupied
462 .into_mut()
463 .get_persisted_mut_or_insert_with(insert_with),
464 }
465 }
466
467 #[cfg(feature = "persistence")]
469 #[allow(unused, clippy::allow_attributes)]
470 fn get_generation<T: SerializableAny>(&self, id: Id) -> Option<usize> {
471 let element = self.map.get(&hash(TypeId::of::<T>(), id))?;
472 match element {
473 Element::Value { .. } => Some(0),
474 Element::Serialized(SerializedElement { generation, .. }) => Some(*generation),
475 }
476 }
477
478 #[inline]
480 pub fn remove<T: 'static>(&mut self, id: Id) {
481 let hash = hash(TypeId::of::<T>(), id);
482 self.map.remove(&hash);
483 }
484
485 #[inline]
487 pub fn remove_temp<T: 'static + Default>(&mut self, id: Id) -> Option<T> {
488 let hash = hash(TypeId::of::<T>(), id);
489 let mut element = self.map.remove(&hash)?;
490 Some(std::mem::take(element.get_mut_temp()?))
491 }
492
493 pub fn remove_by_type<T: 'static>(&mut self) {
495 let key = TypeId::of::<T>();
496 self.map.retain(|_, e| {
497 let e: &Element = e;
498 e.type_id() != key
499 });
500 }
501
502 #[inline]
503 pub fn clear(&mut self) {
504 self.map.clear();
505 }
506
507 #[inline]
508 pub fn is_empty(&self) -> bool {
509 self.map.is_empty()
510 }
511
512 #[inline]
513 pub fn len(&self) -> usize {
514 self.map.len()
515 }
516
517 #[inline]
519 pub fn count_serialized(&self) -> usize {
520 self.map
521 .values()
522 .filter(|e| matches!(e, Element::Serialized(_)))
523 .count()
524 }
525
526 pub fn count<T: 'static>(&self) -> usize {
528 let key = TypeId::of::<T>();
529 self.map
530 .iter()
531 .filter(|(_, e)| {
532 let e: &Element = e;
533 e.type_id() == key
534 })
535 .count()
536 }
537
538 pub fn max_bytes_per_type(&self) -> usize {
552 self.max_bytes_per_type
553 }
554
555 pub fn set_max_bytes_per_type(&mut self, max_bytes_per_type: usize) {
557 self.max_bytes_per_type = max_bytes_per_type;
558 }
559}
560
561#[inline(always)]
562fn hash(type_id: TypeId, id: Id) -> u64 {
563 type_id.value() ^ id.value()
564}
565
566#[cfg(feature = "persistence")]
570#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
571struct PersistedMap(Vec<(u64, SerializedElement)>);
572
573#[cfg(feature = "persistence")]
574impl PersistedMap {
575 fn from_map(map: &IdTypeMap) -> Self {
576 #![expect(clippy::iter_over_hash_type)] profiling::function_scope!();
579
580 use std::collections::BTreeMap;
581
582 let mut types_map: nohash_hasher::IntMap<TypeId, TypeStats> = Default::default();
583 #[derive(Default)]
584 struct TypeStats {
585 num_bytes: usize,
586 generations: BTreeMap<usize, GenerationStats>,
587 }
588 #[derive(Default)]
589 struct GenerationStats {
590 num_bytes: usize,
591 elements: Vec<(u64, SerializedElement)>,
592 }
593
594 let max_bytes_per_type = map.max_bytes_per_type;
595
596 {
597 profiling::scope!("gather");
598 for (hash, element) in &map.map {
599 if let Some(element) = element.to_serialize() {
600 let stats = types_map.entry(element.type_id).or_default();
601 stats.num_bytes += element.ron.len();
602 let generation_stats = stats.generations.entry(element.generation).or_default();
603 generation_stats.num_bytes += element.ron.len();
604 generation_stats.elements.push((*hash, element));
605 } else {
606 }
608 }
609 }
610
611 let mut persisted = vec![];
612
613 {
614 profiling::scope!("gc");
615 for stats in types_map.values() {
616 let mut bytes_written = 0;
617
618 for generation in stats.generations.values() {
621 if bytes_written == 0
622 || bytes_written + generation.num_bytes <= max_bytes_per_type
623 {
624 persisted.append(&mut generation.elements.clone());
625 bytes_written += generation.num_bytes;
626 } else {
627 break;
629 }
630 }
631 }
632 }
633
634 Self(persisted)
635 }
636
637 fn into_map(self) -> IdTypeMap {
638 profiling::function_scope!();
639 let map = self
640 .0
641 .into_iter()
642 .map(
643 |(
644 hash,
645 SerializedElement {
646 type_id,
647 ron,
648 generation,
649 },
650 )| {
651 (
652 hash,
653 Element::Serialized(SerializedElement {
654 type_id,
655 ron,
656 generation: generation + 1, }),
658 )
659 },
660 )
661 .collect();
662 IdTypeMap {
663 map,
664 ..Default::default()
665 }
666 }
667}
668
669#[cfg(feature = "persistence")]
670impl serde::Serialize for IdTypeMap {
671 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
672 where
673 S: serde::Serializer,
674 {
675 profiling::scope!("IdTypeMap::serialize");
676 PersistedMap::from_map(self).serialize(serializer)
677 }
678}
679
680#[cfg(feature = "persistence")]
681impl<'de> serde::Deserialize<'de> for IdTypeMap {
682 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
683 where
684 D: serde::Deserializer<'de>,
685 {
686 profiling::scope!("IdTypeMap::deserialize");
687 <PersistedMap>::deserialize(deserializer).map(PersistedMap::into_map)
688 }
689}
690
691#[test]
694fn test_two_id_two_type() {
695 let a = Id::new("a");
696 let b = Id::new("b");
697
698 let mut map: IdTypeMap = Default::default();
699 map.insert_persisted(a, 13.37);
700 map.insert_temp(b, 42);
701 assert_eq!(map.get_persisted::<f64>(a), Some(13.37));
702 assert_eq!(map.get_persisted::<i32>(b), Some(42));
703 assert_eq!(map.get_temp::<f64>(a), Some(13.37));
704 assert_eq!(map.get_temp::<i32>(b), Some(42));
705}
706
707#[test]
708fn test_two_id_x_two_types() {
709 #![allow(clippy::approx_constant)]
710
711 let a = Id::new("a");
712 let b = Id::new("b");
713 let mut map: IdTypeMap = Default::default();
714
715 map.insert_persisted(a, 3.14);
717 map.insert_temp(a, 42);
718
719 map.insert_persisted(b, 13.37);
721 map.insert_temp(b, "Hello World".to_owned());
722
723 assert_eq!(map.get_temp::<f64>(a), Some(3.14));
725 assert_eq!(map.get_temp::<i32>(a), Some(42));
726 assert_eq!(map.get_temp::<f64>(b), Some(13.37));
727 assert_eq!(map.get_temp::<String>(b), Some("Hello World".to_owned()));
728
729 assert_eq!(map.get_persisted::<f64>(a), Some(3.14));
731 assert_eq!(map.get_persisted::<i32>(a), Some(42));
732 assert_eq!(map.get_persisted::<f64>(b), Some(13.37));
733 assert_eq!(map.get_temp::<String>(b), Some("Hello World".to_owned()));
734}
735
736#[test]
737fn test_one_id_two_types() {
738 let id = Id::new("a");
739
740 let mut map: IdTypeMap = Default::default();
741 map.insert_persisted(id, 13.37);
742 map.insert_temp(id, 42);
743
744 assert_eq!(map.get_temp::<f64>(id), Some(13.37));
745 assert_eq!(map.get_persisted::<f64>(id), Some(13.37));
746 assert_eq!(map.get_temp::<i32>(id), Some(42));
747
748 map.remove::<i32>(id);
753 assert_eq!(map.get_temp::<i32>(id), None);
754
755 assert_eq!(map.get_temp::<f64>(id), Some(13.37));
757 assert_eq!(map.get_persisted::<f64>(id), Some(13.37));
758
759 map.remove::<f64>(id);
761 assert_eq!(map.get_temp::<f64>(id), None);
762 assert_eq!(map.get_persisted::<f64>(id), None);
763}
764
765#[test]
766fn test_mix() {
767 #[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
768 #[derive(Clone, Debug, PartialEq)]
769 struct Foo(i32);
770
771 #[derive(Clone, Debug, PartialEq)]
772 struct Bar(f32);
773
774 let id = Id::new("a");
775
776 let mut map: IdTypeMap = Default::default();
777 map.insert_persisted(id, Foo(555));
778 map.insert_temp(id, Bar(1.0));
779
780 assert_eq!(map.get_temp::<Foo>(id), Some(Foo(555)));
781 assert_eq!(map.get_persisted::<Foo>(id), Some(Foo(555)));
782 assert_eq!(map.get_temp::<Bar>(id), Some(Bar(1.0)));
783
784 map.remove::<Bar>(id);
789 assert_eq!(map.get_temp::<Bar>(id), None);
790
791 assert_eq!(map.get_temp::<Foo>(id), Some(Foo(555)));
793 assert_eq!(map.get_persisted::<Foo>(id), Some(Foo(555)));
794
795 map.remove::<Foo>(id);
797 assert_eq!(map.get_temp::<Foo>(id), None);
798 assert_eq!(map.get_persisted::<Foo>(id), None);
799}
800
801#[cfg(feature = "persistence")]
802#[test]
803fn test_mix_serialize() {
804 use serde::{Deserialize, Serialize};
805
806 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
807 struct Serializable(i32);
808
809 #[derive(Clone, Debug, PartialEq)]
810 struct NonSerializable(f32);
811
812 let id = Id::new("a");
813
814 let mut map: IdTypeMap = Default::default();
815 map.insert_persisted(id, Serializable(555));
816 map.insert_temp(id, NonSerializable(1.0));
817
818 assert_eq!(map.get_temp::<Serializable>(id), Some(Serializable(555)));
819 assert_eq!(
820 map.get_persisted::<Serializable>(id),
821 Some(Serializable(555))
822 );
823 assert_eq!(
824 map.get_temp::<NonSerializable>(id),
825 Some(NonSerializable(1.0))
826 );
827
828 let serialized = ron::to_string(&map).unwrap();
831
832 map.remove::<NonSerializable>(id);
837 assert_eq!(map.get_temp::<NonSerializable>(id), None);
838
839 assert_eq!(map.get_temp::<Serializable>(id), Some(Serializable(555)));
841 assert_eq!(
842 map.get_persisted::<Serializable>(id),
843 Some(Serializable(555))
844 );
845
846 map.remove::<Serializable>(id);
848 assert_eq!(map.get_temp::<Serializable>(id), None);
849 assert_eq!(map.get_persisted::<Serializable>(id), None);
850
851 let mut map: IdTypeMap = ron::from_str(&serialized).unwrap();
855 assert_eq!(map.get_temp::<Serializable>(id), None);
856 assert_eq!(
857 map.get_persisted::<Serializable>(id),
858 Some(Serializable(555))
859 );
860 assert_eq!(map.get_temp::<Serializable>(id), Some(Serializable(555)));
861}
862
863#[cfg(feature = "persistence")]
864#[test]
865fn test_serialize_generations() {
866 use serde::{Deserialize, Serialize};
867
868 fn serialize_and_deserialize(map: &IdTypeMap) -> IdTypeMap {
869 let serialized = ron::to_string(map).unwrap();
870 ron::from_str(&serialized).unwrap()
871 }
872
873 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
874 struct A(i32);
875
876 let mut map: IdTypeMap = Default::default();
877 for i in 0..3 {
878 map.insert_persisted(Id::new(i), A(i));
879 }
880 for i in 0..3 {
881 assert_eq!(map.get_generation::<A>(Id::new(i)), Some(0));
882 }
883
884 map = serialize_and_deserialize(&map);
885
886 for i in 0..3 {
891 assert_eq!(map.get_generation::<A>(Id::new(i)), Some(2));
892 }
893
894 assert_eq!(map.get_persisted::<A>(Id::new(0)), Some(A(0)));
896 assert_eq!(map.get_generation::<A>(Id::new(0)), Some(0));
897
898 map = serialize_and_deserialize(&map);
900 assert_eq!(map.get_generation::<A>(Id::new(0)), Some(2));
901 assert_eq!(map.get_generation::<A>(Id::new(1)), Some(3));
902}
903
904#[cfg(feature = "persistence")]
905#[test]
906fn test_serialize_gc() {
907 use serde::{Deserialize, Serialize};
908
909 fn serialize_and_deserialize(mut map: IdTypeMap, max_bytes_per_type: usize) -> IdTypeMap {
910 map.set_max_bytes_per_type(max_bytes_per_type);
911 let serialized = ron::to_string(&map).unwrap();
912 ron::from_str(&serialized).unwrap()
913 }
914
915 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
916 struct A(usize);
917
918 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
919 struct B(usize);
920
921 let mut map: IdTypeMap = Default::default();
922
923 let num_a = 1_000;
924 let num_b = 10;
925
926 for i in 0..num_a {
927 map.insert_persisted(Id::new(i), A(i));
928 }
929 for i in 0..num_b {
930 map.insert_persisted(Id::new(i), B(i));
931 }
932
933 map = serialize_and_deserialize(map, 100);
934
935 assert_eq!(map.count::<A>(), num_a);
937 assert_eq!(map.count::<B>(), num_b);
938
939 map.insert_persisted(Id::new(1_000_000), A(1_000_000));
941 map.insert_persisted(Id::new(1_000_000), B(1_000_000));
942
943 assert_eq!(map.count::<A>(), num_a + 1);
944 assert_eq!(map.count::<B>(), num_b + 1);
945
946 assert_eq!(map.get_persisted::<A>(Id::new(0)), Some(A(0)));
948 assert_eq!(map.get_persisted::<B>(Id::new(0)), Some(B(0)));
949
950 map = serialize_and_deserialize(map, 100);
951
952 assert_eq!(
953 map.count::<A>(),
954 2,
955 "We should have dropped the oldest generation, but kept the new value and the read value"
956 );
957 assert_eq!(
958 map.count::<B>(),
959 num_b + 1,
960 "B should fit under the byte limit"
961 );
962
963 map.insert_persisted(Id::new(2_000_000), A(2_000_000));
965 map.insert_persisted(Id::new(2_000_000), B(2_000_000));
966
967 map = serialize_and_deserialize(map, 100);
968
969 assert_eq!(map.count::<A>(), 3); assert_eq!(map.count::<B>(), num_b + 2); map = serialize_and_deserialize(map, 1);
975
976 assert_eq!(map.count::<A>(), 1);
977 assert_eq!(map.count::<B>(), 1);
978
979 assert_eq!(
980 map.get_persisted::<A>(Id::new(2_000_000)),
981 Some(A(2_000_000))
982 );
983 assert_eq!(
984 map.get_persisted::<B>(Id::new(2_000_000)),
985 Some(B(2_000_000))
986 );
987}