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