1use std::{any::Any, sync::Arc};
7#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
11#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
12pub struct TypeId(u64);
13
14impl TypeId {
15 #[inline]
16 pub fn of<T: Any + 'static>() -> Self {
17 std::any::TypeId::of::<T>().into()
18 }
19
20 #[inline(always)]
21 pub(crate) fn value(&self) -> u64 {
22 self.0
23 }
24}
25
26impl From<std::any::TypeId> for TypeId {
27 #[inline]
28 fn from(id: std::any::TypeId) -> Self {
29 Self(epaint::util::hash(id))
30 }
31}
32
33impl nohash_hasher::IsEnabled for TypeId {}
34
35#[cfg(feature = "persistence")]
38pub trait SerializableAny:
39 'static + Any + Clone + serde::Serialize + for<'a> serde::Deserialize<'a> + Send + Sync
40{
41}
42
43#[cfg(feature = "persistence")]
44impl<T> SerializableAny for T where
45 T: 'static + Any + Clone + serde::Serialize + for<'a> serde::Deserialize<'a> + Send + Sync
46{
47}
48
49#[cfg(not(feature = "persistence"))]
50pub trait SerializableAny: 'static + Any + Clone + for<'a> Send + Sync {}
51
52#[cfg(not(feature = "persistence"))]
53impl<T> SerializableAny for T where T: 'static + Any + Clone + for<'a> Send + Sync {}
54
55#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
58#[derive(Clone, Debug)]
59struct SerializedElement {
60 type_id: TypeId,
62
63 ron: Arc<str>,
65
66 generation: usize,
72}
73
74#[cfg(feature = "persistence")]
75type Serializer = fn(&Box<dyn Any + 'static + Send + Sync>) -> Option<String>;
76
77enum Element {
78 Value {
80 value: Box<dyn Any + 'static + Send + Sync>,
82
83 clone_fn: fn(&Box<dyn Any + 'static + Send + Sync>) -> Box<dyn Any + 'static + Send + Sync>,
85
86 #[cfg(feature = "persistence")]
89 serialize_fn: Option<Serializer>,
90 },
91
92 Serialized(SerializedElement),
94}
95
96impl Clone for Element {
97 fn clone(&self) -> Self {
98 match &self {
99 Self::Value {
100 value,
101 clone_fn,
102 #[cfg(feature = "persistence")]
103 serialize_fn,
104 } => Self::Value {
105 value: clone_fn(value),
106 clone_fn: *clone_fn,
107 #[cfg(feature = "persistence")]
108 serialize_fn: *serialize_fn,
109 },
110
111 Self::Serialized(element) => Self::Serialized(element.clone()),
112 }
113 }
114}
115
116impl std::fmt::Debug for Element {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 match &self {
119 Self::Value { value, .. } => f
120 .debug_struct("Element::Value")
121 .field("type_id", &(**value).type_id())
122 .finish_non_exhaustive(),
123 Self::Serialized(SerializedElement {
124 type_id,
125 ron,
126 generation,
127 }) => f
128 .debug_struct("Element::Serialized")
129 .field("type_id", type_id)
130 .field("ron", ron)
131 .field("generation", generation)
132 .finish(),
133 }
134 }
135}
136
137impl Element {
138 #[inline]
140 pub(crate) fn new_temp<T: 'static + Any + Clone + Send + Sync>(t: T) -> Self {
141 Self::Value {
142 value: Box::new(t),
143 clone_fn: |x| {
144 #[expect(clippy::unwrap_used)]
146 let x = x.downcast_ref::<T>().unwrap();
147 Box::new(x.clone())
148 },
149 #[cfg(feature = "persistence")]
150 serialize_fn: None,
151 }
152 }
153
154 #[inline]
156 pub(crate) fn new_persisted<T: SerializableAny>(t: T) -> Self {
157 Self::Value {
158 value: Box::new(t),
159 clone_fn: |x| {
160 #[expect(clippy::unwrap_used)]
162 let x = x.downcast_ref::<T>().unwrap();
163 Box::new(x.clone())
164 },
165 #[cfg(feature = "persistence")]
166 serialize_fn: Some(|x| {
167 #[expect(clippy::unwrap_used)]
169 let x = x.downcast_ref::<T>().unwrap();
170 ron::to_string(x).ok()
171 }),
172 }
173 }
174
175 #[inline]
177 pub(crate) fn type_id(&self) -> TypeId {
178 match self {
179 Self::Value { value, .. } => (**value).type_id().into(),
180 Self::Serialized(SerializedElement { type_id, .. }) => *type_id,
181 }
182 }
183
184 pub fn is_temp(&self) -> bool {
185 match self {
186 #[cfg(feature = "persistence")]
187 Self::Value { serialize_fn, .. } => serialize_fn.is_none(),
188
189 #[cfg(not(feature = "persistence"))]
190 Self::Value { .. } => true,
191
192 Self::Serialized(_) => false,
193 }
194 }
195
196 #[inline]
197 pub(crate) fn get_temp<T: 'static>(&self) -> Option<&T> {
198 match self {
199 Self::Value { value, .. } => value.downcast_ref(),
200 Self::Serialized(_) => None,
201 }
202 }
203
204 #[inline]
205 pub(crate) fn get_mut_temp<T: 'static>(&mut self) -> Option<&mut T> {
206 match self {
207 Self::Value { value, .. } => value.downcast_mut(),
208 Self::Serialized(_) => None,
209 }
210 }
211
212 #[inline]
213 pub(crate) fn get_temp_mut_or_insert_with<T: 'static + Any + Clone + Send + Sync>(
214 &mut self,
215 insert_with: impl FnOnce() -> T,
216 ) -> &mut T {
217 match self {
218 Self::Value { value, .. } => {
219 if !value.is::<T>() {
220 *self = Self::new_temp(insert_with());
221 }
222 }
223 Self::Serialized(_) => {
224 *self = Self::new_temp(insert_with());
225 }
226 }
227
228 match self {
229 #[expect(clippy::unwrap_used)]
231 Self::Value { value, .. } => value.downcast_mut().unwrap(),
232 Self::Serialized(_) => unreachable!(),
233 }
234 }
235
236 #[inline]
237 pub(crate) fn get_persisted_mut_or_insert_with<T: SerializableAny>(
238 &mut self,
239 insert_with: impl FnOnce() -> T,
240 ) -> &mut T {
241 match self {
242 Self::Value { value, .. } => {
243 if !value.is::<T>() {
244 *self = Self::new_persisted(insert_with());
245 }
246 }
247
248 #[cfg(feature = "persistence")]
249 Self::Serialized(SerializedElement { ron, .. }) => {
250 *self = Self::new_persisted(from_ron_str::<T>(ron).unwrap_or_else(insert_with));
251 }
252
253 #[cfg(not(feature = "persistence"))]
254 Self::Serialized(_) => {
255 *self = Self::new_persisted(insert_with());
256 }
257 }
258
259 match self {
260 #[expect(clippy::unwrap_used)]
262 Self::Value { value, .. } => value.downcast_mut().unwrap(),
263 Self::Serialized(_) => unreachable!(),
264 }
265 }
266
267 pub(crate) fn get_mut_persisted<T: SerializableAny>(&mut self) -> Option<&mut T> {
268 match self {
269 Self::Value { value, .. } => value.downcast_mut(),
270
271 #[cfg(feature = "persistence")]
272 Self::Serialized(SerializedElement { ron, .. }) => {
273 *self = Self::new_persisted(from_ron_str::<T>(ron)?);
274
275 match self {
276 Self::Value { value, .. } => value.downcast_mut(),
277 Self::Serialized(_) => unreachable!(),
278 }
279 }
280
281 #[cfg(not(feature = "persistence"))]
282 Self::Serialized(_) => None,
283 }
284 }
285
286 #[cfg(feature = "persistence")]
287 fn to_serialize(&self) -> Option<SerializedElement> {
288 match self {
289 Self::Value {
290 value,
291 serialize_fn,
292 ..
293 } => {
294 if let Some(serialize_fn) = serialize_fn {
295 let ron = serialize_fn(value)?;
296 Some(SerializedElement {
297 type_id: (**value).type_id().into(),
298 ron: ron.into(),
299 generation: 1,
300 })
301 } else {
302 None
303 }
304 }
305 Self::Serialized(element) => Some(element.clone()),
306 }
307 }
308}
309
310#[cfg(feature = "persistence")]
311fn from_ron_str<T: serde::de::DeserializeOwned>(ron: &str) -> Option<T> {
312 match ron::from_str::<T>(ron) {
313 Ok(value) => Some(value),
314 Err(_err) => {
315 log::warn!(
316 "egui: Failed to deserialize {} from memory: {}, ron error: {:?}",
317 std::any::type_name::<T>(),
318 _err,
319 ron
320 );
321 None
322 }
323 }
324}
325
326use crate::Id;
329
330#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
340#[repr(transparent)]
341pub struct RawKey(u64);
342
343impl nohash_hasher::IsEnabled for RawKey {}
344
345impl RawKey {
346 #[inline(always)]
359 pub fn new<T: 'static>(id: Id) -> Self {
360 let type_id = TypeId::of::<T>();
361 Self(type_id.value() ^ id.value())
362 }
363}
364
365#[derive(Clone, Debug)]
405pub struct IdTypeMap {
407 map: nohash_hasher::IntMap<RawKey, Element>,
408
409 max_bytes_per_type: usize,
410}
411
412impl Default for IdTypeMap {
413 fn default() -> Self {
414 Self {
415 map: Default::default(),
416 max_bytes_per_type: 256 * 1024,
417 }
418 }
419}
420
421impl IdTypeMap {
422 #[inline]
424 pub fn insert_temp<T: 'static + Any + Clone + Send + Sync>(
425 &mut self,
426 id: Id,
427 value: T,
428 ) -> RawKey {
429 let key = RawKey::new::<T>(id);
430 self.map.insert(key, Element::new_temp(value));
431 key
432 }
433
434 #[inline]
436 pub fn insert_persisted<T: SerializableAny>(&mut self, id: Id, value: T) {
437 let key = RawKey::new::<T>(id);
438 self.map.insert(key, Element::new_persisted(value));
439 }
442
443 #[inline]
447 pub fn get_temp<T: 'static + Clone>(&self, id: Id) -> Option<T> {
448 let key = RawKey::new::<T>(id);
449 self.map.get(&key).and_then(|x| x.get_temp()).cloned()
450 }
451
452 pub fn get_temp_raw(&self, raw: RawKey) -> Option<&(dyn Any + Send + Sync)> {
456 match self.map.get(&raw)? {
457 Element::Value { value, .. } => Some(value.as_ref()),
458 Element::Serialized(_) => None,
459 }
460 }
461
462 pub fn get_temp_raw_mut(&mut self, raw: RawKey) -> Option<&mut (dyn Any + Send + Sync)> {
466 match self.map.get_mut(&raw)? {
467 Element::Value { value, .. } => Some(value.as_mut()),
468 Element::Serialized(_) => None,
469 }
470 }
471
472 #[inline]
479 pub fn get_persisted<T: SerializableAny>(&mut self, id: Id) -> Option<T> {
480 let key = RawKey::new::<T>(id);
481 self.map
482 .get_mut(&key)
483 .and_then(|x| x.get_mut_persisted())
484 .cloned()
485 }
486
487 #[inline]
488 pub fn get_temp_mut_or<T: 'static + Any + Clone + Send + Sync>(
489 &mut self,
490 id: Id,
491 or_insert: T,
492 ) -> &mut T {
493 self.get_temp_mut_or_insert_with(id, || or_insert)
494 }
495
496 #[inline]
497 pub fn get_persisted_mut_or<T: SerializableAny>(&mut self, id: Id, or_insert: T) -> &mut T {
498 self.get_persisted_mut_or_insert_with(id, || or_insert)
499 }
500
501 #[inline]
502 pub fn get_temp_mut_or_default<T: 'static + Any + Clone + Send + Sync + Default>(
503 &mut self,
504 id: Id,
505 ) -> &mut T {
506 self.get_temp_mut_or_insert_with(id, Default::default)
507 }
508
509 #[inline]
510 pub fn get_persisted_mut_or_default<T: SerializableAny + Default>(&mut self, id: Id) -> &mut T {
511 self.get_persisted_mut_or_insert_with(id, Default::default)
512 }
513
514 pub fn get_temp_mut_or_insert_with<T: 'static + Any + Clone + Send + Sync>(
515 &mut self,
516 id: Id,
517 insert_with: impl FnOnce() -> T,
518 ) -> &mut T {
519 let key = RawKey::new::<T>(id);
520 use std::collections::hash_map::Entry;
521 match self.map.entry(key) {
522 Entry::Vacant(vacant) => {
523 #[expect(clippy::unwrap_used)]
525 vacant
526 .insert(Element::new_temp(insert_with()))
527 .get_mut_temp()
528 .unwrap()
529 }
530 Entry::Occupied(occupied) => {
531 occupied.into_mut().get_temp_mut_or_insert_with(insert_with)
532 }
533 }
534 }
535
536 pub fn get_persisted_mut_or_insert_with<T: SerializableAny>(
537 &mut self,
538 id: Id,
539 insert_with: impl FnOnce() -> T,
540 ) -> &mut T {
541 let key = RawKey::new::<T>(id);
542 use std::collections::hash_map::Entry;
543 match self.map.entry(key) {
544 Entry::Vacant(vacant) => {
545 #[expect(clippy::unwrap_used)]
547 vacant
548 .insert(Element::new_persisted(insert_with()))
549 .get_mut_persisted()
550 .unwrap()
551 }
552 Entry::Occupied(occupied) => occupied
553 .into_mut()
554 .get_persisted_mut_or_insert_with(insert_with),
555 }
556 }
557
558 #[cfg(feature = "persistence")]
560 #[allow(clippy::allow_attributes, unused)]
561 fn get_generation<T: SerializableAny>(&self, id: Id) -> Option<usize> {
562 let element = self.map.get(&RawKey::new::<T>(id))?;
563 match element {
564 Element::Value { .. } => Some(0),
565 Element::Serialized(SerializedElement { generation, .. }) => Some(*generation),
566 }
567 }
568
569 #[inline]
571 pub fn remove<T: 'static>(&mut self, id: Id) {
572 let key = RawKey::new::<T>(id);
573 self.map.remove(&key);
574 }
575
576 #[inline]
578 pub fn remove_temp<T: 'static + Default>(&mut self, id: Id) -> Option<T> {
579 let key = RawKey::new::<T>(id);
580 let mut element = self.map.remove(&key)?;
581 Some(std::mem::take(element.get_mut_temp()?))
582 }
583
584 pub fn remove_temp_raw(&mut self, raw: RawKey) -> Option<Box<dyn Any + Send + Sync>> {
588 use std::collections::hash_map::Entry;
589 if let Entry::Occupied(e) = self.map.entry(raw)
590 && e.get().is_temp()
591 && let Element::Value { value, .. } = e.remove()
592 {
593 Some(value)
594 } else {
595 None
596 }
597 }
598
599 pub fn remove_by_type<T: 'static>(&mut self) {
601 let key = TypeId::of::<T>();
602 self.map.retain(|_, e| {
603 let e: &Element = e;
604 e.type_id() != key
605 });
606 }
607
608 #[inline]
609 pub fn clear(&mut self) {
610 self.map.clear();
611 }
612
613 #[inline]
614 pub fn is_empty(&self) -> bool {
615 self.map.is_empty()
616 }
617
618 #[inline]
619 pub fn len(&self) -> usize {
620 self.map.len()
621 }
622
623 pub fn temp_keys(&self) -> impl Iterator<Item = RawKey> {
629 self.map
630 .iter()
631 .filter(|(_, v)| v.is_temp())
632 .map(|(k, _)| *k)
633 }
634
635 #[inline]
637 pub fn count_serialized(&self) -> usize {
638 self.map
639 .values()
640 .filter(|e| matches!(e, Element::Serialized(_)))
641 .count()
642 }
643
644 pub fn count<T: 'static>(&self) -> usize {
646 let key = TypeId::of::<T>();
647 self.map
648 .iter()
649 .filter(|(_, e)| {
650 let e: &Element = e;
651 e.type_id() == key
652 })
653 .count()
654 }
655
656 pub fn max_bytes_per_type(&self) -> usize {
670 self.max_bytes_per_type
671 }
672
673 pub fn set_max_bytes_per_type(&mut self, max_bytes_per_type: usize) {
675 self.max_bytes_per_type = max_bytes_per_type;
676 }
677}
678
679#[cfg(feature = "persistence")]
683#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
684struct PersistedMap(Vec<(u64, SerializedElement)>);
685
686#[cfg(feature = "persistence")]
687impl PersistedMap {
688 fn from_map(map: &IdTypeMap) -> Self {
689 #![expect(clippy::iter_over_hash_type)] profiling::function_scope!();
692
693 use std::collections::BTreeMap;
694
695 let mut types_map: nohash_hasher::IntMap<TypeId, TypeStats> = Default::default();
696 #[derive(Default)]
697 struct TypeStats {
698 num_bytes: usize,
699 generations: BTreeMap<usize, GenerationStats>,
700 }
701 #[derive(Default)]
702 struct GenerationStats {
703 num_bytes: usize,
704 elements: Vec<(u64, SerializedElement)>,
705 }
706
707 let max_bytes_per_type = map.max_bytes_per_type;
708
709 {
710 profiling::scope!("gather");
711 for (key, element) in &map.map {
712 if let Some(element) = element.to_serialize() {
713 let stats = types_map.entry(element.type_id).or_default();
714 stats.num_bytes += element.ron.len();
715 let generation_stats = stats.generations.entry(element.generation).or_default();
716 generation_stats.num_bytes += element.ron.len();
717 generation_stats.elements.push((key.0, element));
718 } else {
719 }
721 }
722 }
723
724 let mut persisted = vec![];
725
726 {
727 profiling::scope!("gc");
728 for stats in types_map.values() {
729 let mut bytes_written = 0;
730
731 for generation in stats.generations.values() {
734 if bytes_written == 0
735 || bytes_written + generation.num_bytes <= max_bytes_per_type
736 {
737 persisted.append(&mut generation.elements.clone());
738 bytes_written += generation.num_bytes;
739 } else {
740 break;
742 }
743 }
744 }
745 }
746
747 Self(persisted)
748 }
749
750 fn into_map(self) -> IdTypeMap {
751 profiling::function_scope!();
752 let map = self
753 .0
754 .into_iter()
755 .map(
756 |(
757 raw,
758 SerializedElement {
759 type_id,
760 ron,
761 generation,
762 },
763 )| {
764 (
765 RawKey(raw),
766 Element::Serialized(SerializedElement {
767 type_id,
768 ron,
769 generation: generation + 1, }),
771 )
772 },
773 )
774 .collect();
775 IdTypeMap {
776 map,
777 ..Default::default()
778 }
779 }
780}
781
782#[cfg(feature = "persistence")]
783impl serde::Serialize for IdTypeMap {
784 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
785 where
786 S: serde::Serializer,
787 {
788 profiling::scope!("IdTypeMap::serialize");
789 PersistedMap::from_map(self).serialize(serializer)
790 }
791}
792
793#[cfg(feature = "persistence")]
794impl<'de> serde::Deserialize<'de> for IdTypeMap {
795 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
796 where
797 D: serde::Deserializer<'de>,
798 {
799 profiling::scope!("IdTypeMap::deserialize");
800 <PersistedMap>::deserialize(deserializer).map(PersistedMap::into_map)
801 }
802}
803
804#[test]
807fn test_two_id_two_type() {
808 let a = Id::new("a");
809 let b = Id::new("b");
810
811 let mut map: IdTypeMap = Default::default();
812 map.insert_persisted(a, 13.37);
813 map.insert_temp(b, 42);
814 assert_eq!(map.get_persisted::<f64>(a), Some(13.37));
815 assert_eq!(map.get_persisted::<i32>(b), Some(42));
816 assert_eq!(map.get_temp::<f64>(a), Some(13.37));
817 assert_eq!(map.get_temp::<i32>(b), Some(42));
818}
819
820#[test]
821fn test_two_id_x_two_types() {
822 #![expect(clippy::approx_constant)]
823
824 let a = Id::new("a");
825 let b = Id::new("b");
826 let mut map: IdTypeMap = Default::default();
827
828 map.insert_persisted(a, 3.14);
830 map.insert_temp(a, 42);
831
832 map.insert_persisted(b, 13.37);
834 map.insert_temp(b, "Hello World".to_owned());
835
836 assert_eq!(map.get_temp::<f64>(a), Some(3.14));
838 assert_eq!(map.get_temp::<i32>(a), Some(42));
839 assert_eq!(map.get_temp::<f64>(b), Some(13.37));
840 assert_eq!(map.get_temp::<String>(b), Some("Hello World".to_owned()));
841
842 assert_eq!(map.get_persisted::<f64>(a), Some(3.14));
844 assert_eq!(map.get_persisted::<i32>(a), Some(42));
845 assert_eq!(map.get_persisted::<f64>(b), Some(13.37));
846 assert_eq!(map.get_temp::<String>(b), Some("Hello World".to_owned()));
847}
848
849#[test]
850fn test_one_id_two_types() {
851 let id = Id::new("a");
852
853 let mut map: IdTypeMap = Default::default();
854 map.insert_persisted(id, 13.37);
855 map.insert_temp(id, 42);
856
857 assert_eq!(map.get_temp::<f64>(id), Some(13.37));
858 assert_eq!(map.get_persisted::<f64>(id), Some(13.37));
859 assert_eq!(map.get_temp::<i32>(id), Some(42));
860
861 map.remove::<i32>(id);
866 assert_eq!(map.get_temp::<i32>(id), None);
867
868 assert_eq!(map.get_temp::<f64>(id), Some(13.37));
870 assert_eq!(map.get_persisted::<f64>(id), Some(13.37));
871
872 map.remove::<f64>(id);
874 assert_eq!(map.get_temp::<f64>(id), None);
875 assert_eq!(map.get_persisted::<f64>(id), None);
876}
877
878#[test]
879fn test_mix() {
880 #[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
881 #[derive(Clone, Debug, PartialEq)]
882 struct Foo(i32);
883
884 #[derive(Clone, Debug, PartialEq)]
885 struct Bar(f32);
886
887 let id = Id::new("a");
888
889 let mut map: IdTypeMap = Default::default();
890 map.insert_persisted(id, Foo(555));
891 map.insert_temp(id, Bar(1.0));
892
893 assert_eq!(map.get_temp::<Foo>(id), Some(Foo(555)));
894 assert_eq!(map.get_persisted::<Foo>(id), Some(Foo(555)));
895 assert_eq!(map.get_temp::<Bar>(id), Some(Bar(1.0)));
896
897 map.remove::<Bar>(id);
902 assert_eq!(map.get_temp::<Bar>(id), None);
903
904 assert_eq!(map.get_temp::<Foo>(id), Some(Foo(555)));
906 assert_eq!(map.get_persisted::<Foo>(id), Some(Foo(555)));
907
908 map.remove::<Foo>(id);
910 assert_eq!(map.get_temp::<Foo>(id), None);
911 assert_eq!(map.get_persisted::<Foo>(id), None);
912}
913
914#[cfg(feature = "persistence")]
915#[test]
916fn test_mix_serialize() {
917 use serde::{Deserialize, Serialize};
918
919 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
920 struct Serializable(i32);
921
922 #[derive(Clone, Debug, PartialEq)]
923 struct NonSerializable(f32);
924
925 let id = Id::new("a");
926
927 let mut map: IdTypeMap = Default::default();
928 map.insert_persisted(id, Serializable(555));
929 map.insert_temp(id, NonSerializable(1.0));
930
931 assert_eq!(map.get_temp::<Serializable>(id), Some(Serializable(555)));
932 assert_eq!(
933 map.get_persisted::<Serializable>(id),
934 Some(Serializable(555))
935 );
936 assert_eq!(
937 map.get_temp::<NonSerializable>(id),
938 Some(NonSerializable(1.0))
939 );
940
941 let serialized = ron::to_string(&map).unwrap();
944
945 map.remove::<NonSerializable>(id);
950 assert_eq!(map.get_temp::<NonSerializable>(id), None);
951
952 assert_eq!(map.get_temp::<Serializable>(id), Some(Serializable(555)));
954 assert_eq!(
955 map.get_persisted::<Serializable>(id),
956 Some(Serializable(555))
957 );
958
959 map.remove::<Serializable>(id);
961 assert_eq!(map.get_temp::<Serializable>(id), None);
962 assert_eq!(map.get_persisted::<Serializable>(id), None);
963
964 let mut map: IdTypeMap = ron::from_str(&serialized).unwrap();
968 assert_eq!(map.get_temp::<Serializable>(id), None);
969 assert_eq!(
970 map.get_persisted::<Serializable>(id),
971 Some(Serializable(555))
972 );
973 assert_eq!(map.get_temp::<Serializable>(id), Some(Serializable(555)));
974}
975
976#[cfg(feature = "persistence")]
977#[test]
978fn test_serialize_generations() {
979 use serde::{Deserialize, Serialize};
980
981 fn serialize_and_deserialize(map: &IdTypeMap) -> IdTypeMap {
982 let serialized = ron::to_string(map).unwrap();
983 ron::from_str(&serialized).unwrap()
984 }
985
986 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
987 struct A(i32);
988
989 let mut map: IdTypeMap = Default::default();
990 for i in 0..3 {
991 map.insert_persisted(Id::new(i), A(i));
992 }
993 for i in 0..3 {
994 assert_eq!(map.get_generation::<A>(Id::new(i)), Some(0));
995 }
996
997 map = serialize_and_deserialize(&map);
998
999 for i in 0..3 {
1004 assert_eq!(map.get_generation::<A>(Id::new(i)), Some(2));
1005 }
1006
1007 assert_eq!(map.get_persisted::<A>(Id::new(0)), Some(A(0)));
1009 assert_eq!(map.get_generation::<A>(Id::new(0)), Some(0));
1010
1011 map = serialize_and_deserialize(&map);
1013 assert_eq!(map.get_generation::<A>(Id::new(0)), Some(2));
1014 assert_eq!(map.get_generation::<A>(Id::new(1)), Some(3));
1015}
1016
1017#[cfg(feature = "persistence")]
1018#[test]
1019fn test_serialize_gc() {
1020 use serde::{Deserialize, Serialize};
1021
1022 fn serialize_and_deserialize(mut map: IdTypeMap, max_bytes_per_type: usize) -> IdTypeMap {
1023 map.set_max_bytes_per_type(max_bytes_per_type);
1024 let serialized = ron::to_string(&map).unwrap();
1025 ron::from_str(&serialized).unwrap()
1026 }
1027
1028 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1029 struct A(usize);
1030
1031 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1032 struct B(usize);
1033
1034 let mut map: IdTypeMap = Default::default();
1035
1036 let num_a = 1_000;
1037 let num_b = 10;
1038
1039 for i in 0..num_a {
1040 map.insert_persisted(Id::new(i), A(i));
1041 }
1042 for i in 0..num_b {
1043 map.insert_persisted(Id::new(i), B(i));
1044 }
1045
1046 map = serialize_and_deserialize(map, 100);
1047
1048 assert_eq!(map.count::<A>(), num_a);
1050 assert_eq!(map.count::<B>(), num_b);
1051
1052 map.insert_persisted(Id::new(1_000_000), A(1_000_000));
1054 map.insert_persisted(Id::new(1_000_000), B(1_000_000));
1055
1056 assert_eq!(map.count::<A>(), num_a + 1);
1057 assert_eq!(map.count::<B>(), num_b + 1);
1058
1059 assert_eq!(map.get_persisted::<A>(Id::new(0)), Some(A(0)));
1061 assert_eq!(map.get_persisted::<B>(Id::new(0)), Some(B(0)));
1062
1063 map = serialize_and_deserialize(map, 100);
1064
1065 assert_eq!(
1066 map.count::<A>(),
1067 2,
1068 "We should have dropped the oldest generation, but kept the new value and the read value"
1069 );
1070 assert_eq!(
1071 map.count::<B>(),
1072 num_b + 1,
1073 "B should fit under the byte limit"
1074 );
1075
1076 map.insert_persisted(Id::new(2_000_000), A(2_000_000));
1078 map.insert_persisted(Id::new(2_000_000), B(2_000_000));
1079
1080 map = serialize_and_deserialize(map, 100);
1081
1082 assert_eq!(map.count::<A>(), 3); assert_eq!(map.count::<B>(), num_b + 2); map = serialize_and_deserialize(map, 1);
1088
1089 assert_eq!(map.count::<A>(), 1);
1090 assert_eq!(map.count::<B>(), 1);
1091
1092 assert_eq!(
1093 map.get_persisted::<A>(Id::new(2_000_000)),
1094 Some(A(2_000_000))
1095 );
1096 assert_eq!(
1097 map.get_persisted::<B>(Id::new(2_000_000)),
1098 Some(B(2_000_000))
1099 );
1100}