egui/util/
id_type_map.rs

1// TODO(emilk): it is possible we can simplify `Element` further by
2// assuming everything is possibly serializable, and by supplying serialize/deserialize functions for them.
3// For non-serializable types, these simply return `None`.
4// This will also allow users to pick their own serialization format per type.
5
6use std::{any::Any, sync::Arc};
7
8// -----------------------------------------------------------------------------------------------
9
10/// Like [`std::any::TypeId`], but can be serialized and deserialized.
11#[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// -----------------------------------------------------------------------------------------------
37
38#[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// -----------------------------------------------------------------------------------------------
57
58#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
59#[derive(Clone, Debug)]
60struct SerializedElement {
61    /// The type of value we are storing.
62    type_id: TypeId,
63
64    /// The ron data we can deserialize.
65    ron: Arc<str>,
66
67    /// Increased by one each time we re-serialize an element that was never deserialized.
68    ///
69    /// Large value = old value that hasn't been read in a while.
70    ///
71    /// Used to garbage collect old values that hasn't been read in a while.
72    generation: usize,
73}
74
75#[cfg(feature = "persistence")]
76type Serializer = fn(&Box<dyn Any + 'static + Send + Sync>) -> Option<String>;
77
78enum Element {
79    /// A value, maybe serializable.
80    Value {
81        /// The actual value.
82        value: Box<dyn Any + 'static + Send + Sync>,
83
84        /// How to clone the value.
85        clone_fn: fn(&Box<dyn Any + 'static + Send + Sync>) -> Box<dyn Any + 'static + Send + Sync>,
86
87        /// How to serialize the value.
88        /// None if non-serializable type.
89        #[cfg(feature = "persistence")]
90        serialize_fn: Option<Serializer>,
91    },
92
93    /// A serialized value
94    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    /// Create a value that won't be persisted.
140    #[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(); // This unwrap will never panic, because we always construct this type using this `new` function and because we return &mut reference only with this type `T`, so type cannot change.
146                Box::new(x.clone())
147            },
148            #[cfg(feature = "persistence")]
149            serialize_fn: None,
150        }
151    }
152
153    /// Create a value that will be persisted.
154    #[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(); // This unwrap will never panic, because we always construct this type using this `new` function and because we return &mut reference only with this type `T`, so type cannot change.
160                Box::new(x.clone())
161            },
162            #[cfg(feature = "persistence")]
163            serialize_fn: Some(|x| {
164                let x = x.downcast_ref::<T>().unwrap(); // This will never panic too, for same reason.
165                ron::to_string(x).ok()
166            }),
167        }
168    }
169
170    /// The type of the stored value.
171    #[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(), // This unwrap will never panic because we already converted object to required type
213            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(), // This unwrap will never panic because we already converted object to required type
242            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            #[cfg(feature = "log")]
295            log::warn!(
296                "egui: Failed to deserialize {} from memory: {}, ron error: {:?}",
297                std::any::type_name::<T>(),
298                _err,
299                ron
300            );
301            None
302        }
303    }
304}
305
306// -----------------------------------------------------------------------------------------------
307
308use crate::Id;
309
310// TODO(emilk): make IdTypeMap generic over the key (`Id`), and make a library of IdTypeMap.
311/// Stores values identified by an [`Id`] AND the [`std::any::TypeId`] of the value.
312///
313/// In other words, it maps `(Id, TypeId)` to any value you want.
314///
315/// Values are cloned when read, so keep them small and light.
316/// If you want to store something bigger, wrap them in `Arc<Mutex<…>>`.
317/// Also try `Arc<ArcSwap<…>>`.
318///
319/// Values can either be "persisted" (serializable) or "temporary" (cleared when egui is shut down).
320///
321/// You can store state using the key [`Id::NULL`]. The state will then only be identified by its type.
322///
323/// ```
324/// # use egui::{Id, util::IdTypeMap};
325/// let a = Id::new("a");
326/// let b = Id::new("b");
327/// let mut map: IdTypeMap = Default::default();
328///
329/// // `a` associated with an f64 and an i32
330/// map.insert_persisted(a, 3.14);
331/// map.insert_temp(a, 42);
332///
333/// // `b` associated with an f64 and a `&'static str`
334/// map.insert_persisted(b, 13.37);
335/// map.insert_temp(b, "Hello World".to_owned());
336///
337/// // we can retrieve all four values:
338/// assert_eq!(map.get_temp::<f64>(a), Some(3.14));
339/// assert_eq!(map.get_temp::<i32>(a), Some(42));
340/// assert_eq!(map.get_temp::<f64>(b), Some(13.37));
341/// assert_eq!(map.get_temp::<String>(b), Some("Hello World".to_owned()));
342///
343/// // we can retrieve them like so also:
344/// assert_eq!(map.get_persisted::<f64>(a), Some(3.14));
345/// assert_eq!(map.get_persisted::<i32>(a), Some(42));
346/// assert_eq!(map.get_persisted::<f64>(b), Some(13.37));
347/// assert_eq!(map.get_temp::<String>(b), Some("Hello World".to_owned()));
348/// ```
349#[derive(Clone, Debug)]
350// We use `id XOR typeid` as a key, so we don't need to hash again!
351pub struct IdTypeMap {
352    map: nohash_hasher::IntMap<u64, Element>,
353
354    max_bytes_per_type: usize,
355}
356
357impl Default for IdTypeMap {
358    fn default() -> Self {
359        Self {
360            map: Default::default(),
361            max_bytes_per_type: 256 * 1024,
362        }
363    }
364}
365
366impl IdTypeMap {
367    /// Insert a value that will not be persisted.
368    #[inline]
369    pub fn insert_temp<T: 'static + Any + Clone + Send + Sync>(&mut self, id: Id, value: T) {
370        let hash = hash(TypeId::of::<T>(), id);
371        self.map.insert(hash, Element::new_temp(value));
372    }
373
374    /// Insert a value that will be persisted next time you start the app.
375    #[inline]
376    pub fn insert_persisted<T: SerializableAny>(&mut self, id: Id, value: T) {
377        let hash = hash(TypeId::of::<T>(), id);
378        self.map.insert(hash, Element::new_persisted(value));
379    }
380
381    /// Read a value without trying to deserialize a persisted value.
382    ///
383    /// The call clones the value (if found), so make sure it is cheap to clone!
384    #[inline]
385    pub fn get_temp<T: 'static + Clone>(&self, id: Id) -> Option<T> {
386        let hash = hash(TypeId::of::<T>(), id);
387        self.map.get(&hash).and_then(|x| x.get_temp()).cloned()
388    }
389
390    /// Read a value, optionally deserializing it if available.
391    ///
392    /// NOTE: A mutable `self` is needed because internally this deserializes on first call
393    /// and caches the result (caching requires self-mutability).
394    ///
395    /// The call clones the value (if found), so make sure it is cheap to clone!
396    #[inline]
397    pub fn get_persisted<T: SerializableAny>(&mut self, id: Id) -> Option<T> {
398        let hash = hash(TypeId::of::<T>(), id);
399        self.map
400            .get_mut(&hash)
401            .and_then(|x| x.get_mut_persisted())
402            .cloned()
403    }
404
405    #[inline]
406    pub fn get_temp_mut_or<T: 'static + Any + Clone + Send + Sync>(
407        &mut self,
408        id: Id,
409        or_insert: T,
410    ) -> &mut T {
411        self.get_temp_mut_or_insert_with(id, || or_insert)
412    }
413
414    #[inline]
415    pub fn get_persisted_mut_or<T: SerializableAny>(&mut self, id: Id, or_insert: T) -> &mut T {
416        self.get_persisted_mut_or_insert_with(id, || or_insert)
417    }
418
419    #[inline]
420    pub fn get_temp_mut_or_default<T: 'static + Any + Clone + Send + Sync + Default>(
421        &mut self,
422        id: Id,
423    ) -> &mut T {
424        self.get_temp_mut_or_insert_with(id, Default::default)
425    }
426
427    #[inline]
428    pub fn get_persisted_mut_or_default<T: SerializableAny + Default>(&mut self, id: Id) -> &mut T {
429        self.get_persisted_mut_or_insert_with(id, Default::default)
430    }
431
432    pub fn get_temp_mut_or_insert_with<T: 'static + Any + Clone + Send + Sync>(
433        &mut self,
434        id: Id,
435        insert_with: impl FnOnce() -> T,
436    ) -> &mut T {
437        let hash = hash(TypeId::of::<T>(), id);
438        use std::collections::hash_map::Entry;
439        match self.map.entry(hash) {
440            Entry::Vacant(vacant) => vacant
441                .insert(Element::new_temp(insert_with()))
442                .get_mut_temp()
443                .unwrap(), // this unwrap will never panic, because we insert correct type right now
444            Entry::Occupied(occupied) => {
445                occupied.into_mut().get_temp_mut_or_insert_with(insert_with)
446            }
447        }
448    }
449
450    pub fn get_persisted_mut_or_insert_with<T: SerializableAny>(
451        &mut self,
452        id: Id,
453        insert_with: impl FnOnce() -> T,
454    ) -> &mut T {
455        let hash = hash(TypeId::of::<T>(), id);
456        use std::collections::hash_map::Entry;
457        match self.map.entry(hash) {
458            Entry::Vacant(vacant) => vacant
459                .insert(Element::new_persisted(insert_with()))
460                .get_mut_persisted()
461                .unwrap(), // this unwrap will never panic, because we insert correct type right now
462            Entry::Occupied(occupied) => occupied
463                .into_mut()
464                .get_persisted_mut_or_insert_with(insert_with),
465        }
466    }
467
468    /// For tests
469    #[cfg(feature = "persistence")]
470    #[allow(unused)]
471    fn get_generation<T: SerializableAny>(&self, id: Id) -> Option<usize> {
472        let element = self.map.get(&hash(TypeId::of::<T>(), id))?;
473        match element {
474            Element::Value { .. } => Some(0),
475            Element::Serialized(SerializedElement { generation, .. }) => Some(*generation),
476        }
477    }
478
479    /// Remove the state of this type and id.
480    #[inline]
481    pub fn remove<T: 'static>(&mut self, id: Id) {
482        let hash = hash(TypeId::of::<T>(), id);
483        self.map.remove(&hash);
484    }
485
486    /// Remove and fetch the state of this type and id.
487    #[inline]
488    pub fn remove_temp<T: 'static + Default>(&mut self, id: Id) -> Option<T> {
489        let hash = hash(TypeId::of::<T>(), id);
490        let mut element = self.map.remove(&hash)?;
491        Some(std::mem::take(element.get_mut_temp()?))
492    }
493
494    /// Note all state of the given type.
495    pub fn remove_by_type<T: 'static>(&mut self) {
496        let key = TypeId::of::<T>();
497        self.map.retain(|_, e| {
498            let e: &Element = e;
499            e.type_id() != key
500        });
501    }
502
503    #[inline]
504    pub fn clear(&mut self) {
505        self.map.clear();
506    }
507
508    #[inline]
509    pub fn is_empty(&self) -> bool {
510        self.map.is_empty()
511    }
512
513    #[inline]
514    pub fn len(&self) -> usize {
515        self.map.len()
516    }
517
518    /// Count how many values are stored but not yet deserialized.
519    #[inline]
520    pub fn count_serialized(&self) -> usize {
521        self.map
522            .values()
523            .filter(|e| matches!(e, Element::Serialized(_)))
524            .count()
525    }
526
527    /// Count the number of values are stored with the given type.
528    pub fn count<T: 'static>(&self) -> usize {
529        let key = TypeId::of::<T>();
530        self.map
531            .iter()
532            .filter(|(_, e)| {
533                let e: &Element = e;
534                e.type_id() == key
535            })
536            .count()
537    }
538
539    /// The maximum number of bytes that will be used to
540    /// store the persisted state of a single widget type.
541    ///
542    /// Some egui widgets store persisted state that is
543    /// serialized to disk by some backends (e.g. `eframe`).
544    ///
545    /// Example of such widgets is `CollapsingHeader` and `Window`.
546    /// If you keep creating widgets with unique ids (e.g. `Windows` with many different names),
547    /// egui will use up more and more space for these widgets, until this limit is reached.
548    ///
549    /// Once this limit is reached, the state that was read the longest time ago will be dropped first.
550    ///
551    /// This value in itself will not be serialized.
552    pub fn max_bytes_per_type(&self) -> usize {
553        self.max_bytes_per_type
554    }
555
556    /// See [`Self::max_bytes_per_type`].
557    pub fn set_max_bytes_per_type(&mut self, max_bytes_per_type: usize) {
558        self.max_bytes_per_type = max_bytes_per_type;
559    }
560}
561
562#[inline(always)]
563fn hash(type_id: TypeId, id: Id) -> u64 {
564    type_id.value() ^ id.value()
565}
566
567// ----------------------------------------------------------------------------
568
569/// How [`IdTypeMap`] is persisted.
570#[cfg(feature = "persistence")]
571#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
572struct PersistedMap(Vec<(u64, SerializedElement)>);
573
574#[cfg(feature = "persistence")]
575impl PersistedMap {
576    fn from_map(map: &IdTypeMap) -> Self {
577        profiling::function_scope!();
578
579        use std::collections::BTreeMap;
580
581        let mut types_map: nohash_hasher::IntMap<TypeId, TypeStats> = Default::default();
582        #[derive(Default)]
583        struct TypeStats {
584            num_bytes: usize,
585            generations: BTreeMap<usize, GenerationStats>,
586        }
587        #[derive(Default)]
588        struct GenerationStats {
589            num_bytes: usize,
590            elements: Vec<(u64, SerializedElement)>,
591        }
592
593        let max_bytes_per_type = map.max_bytes_per_type;
594
595        {
596            profiling::scope!("gather");
597            for (hash, element) in &map.map {
598                if let Some(element) = element.to_serialize() {
599                    let stats = types_map.entry(element.type_id).or_default();
600                    stats.num_bytes += element.ron.len();
601                    let generation_stats = stats.generations.entry(element.generation).or_default();
602                    generation_stats.num_bytes += element.ron.len();
603                    generation_stats.elements.push((*hash, element));
604                } else {
605                    // temporary value that shouldn't be serialized
606                }
607            }
608        }
609
610        let mut persisted = vec![];
611
612        {
613            profiling::scope!("gc");
614            for stats in types_map.values() {
615                let mut bytes_written = 0;
616
617                // Start with the most recently read values, and then go as far as we are allowed.
618                // Always include at least one generation.
619                for generation in stats.generations.values() {
620                    if bytes_written == 0
621                        || bytes_written + generation.num_bytes <= max_bytes_per_type
622                    {
623                        persisted.append(&mut generation.elements.clone());
624                        bytes_written += generation.num_bytes;
625                    } else {
626                        // Omit the rest. The user hasn't read the values in a while.
627                        break;
628                    }
629                }
630            }
631        }
632
633        Self(persisted)
634    }
635
636    fn into_map(self) -> IdTypeMap {
637        profiling::function_scope!();
638        let map = self
639            .0
640            .into_iter()
641            .map(
642                |(
643                    hash,
644                    SerializedElement {
645                        type_id,
646                        ron,
647                        generation,
648                    },
649                )| {
650                    (
651                        hash,
652                        Element::Serialized(SerializedElement {
653                            type_id,
654                            ron,
655                            generation: generation + 1, // This is where we increment the generation!
656                        }),
657                    )
658                },
659            )
660            .collect();
661        IdTypeMap {
662            map,
663            ..Default::default()
664        }
665    }
666}
667
668#[cfg(feature = "persistence")]
669impl serde::Serialize for IdTypeMap {
670    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
671    where
672        S: serde::Serializer,
673    {
674        profiling::scope!("IdTypeMap::serialize");
675        PersistedMap::from_map(self).serialize(serializer)
676    }
677}
678
679#[cfg(feature = "persistence")]
680impl<'de> serde::Deserialize<'de> for IdTypeMap {
681    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
682    where
683        D: serde::Deserializer<'de>,
684    {
685        profiling::scope!("IdTypeMap::deserialize");
686        <PersistedMap>::deserialize(deserializer).map(PersistedMap::into_map)
687    }
688}
689
690// ----------------------------------------------------------------------------
691
692#[test]
693fn test_two_id_two_type() {
694    let a = Id::new("a");
695    let b = Id::new("b");
696
697    let mut map: IdTypeMap = Default::default();
698    map.insert_persisted(a, 13.37);
699    map.insert_temp(b, 42);
700    assert_eq!(map.get_persisted::<f64>(a), Some(13.37));
701    assert_eq!(map.get_persisted::<i32>(b), Some(42));
702    assert_eq!(map.get_temp::<f64>(a), Some(13.37));
703    assert_eq!(map.get_temp::<i32>(b), Some(42));
704}
705
706#[test]
707fn test_two_id_x_two_types() {
708    #![allow(clippy::approx_constant)]
709
710    let a = Id::new("a");
711    let b = Id::new("b");
712    let mut map: IdTypeMap = Default::default();
713
714    // `a` associated with an f64 and an i32
715    map.insert_persisted(a, 3.14);
716    map.insert_temp(a, 42);
717
718    // `b` associated with an f64 and a `&'static str`
719    map.insert_persisted(b, 13.37);
720    map.insert_temp(b, "Hello World".to_owned());
721
722    // we can retrieve all four values:
723    assert_eq!(map.get_temp::<f64>(a), Some(3.14));
724    assert_eq!(map.get_temp::<i32>(a), Some(42));
725    assert_eq!(map.get_temp::<f64>(b), Some(13.37));
726    assert_eq!(map.get_temp::<String>(b), Some("Hello World".to_owned()));
727
728    // we can retrieve them like so also:
729    assert_eq!(map.get_persisted::<f64>(a), Some(3.14));
730    assert_eq!(map.get_persisted::<i32>(a), Some(42));
731    assert_eq!(map.get_persisted::<f64>(b), Some(13.37));
732    assert_eq!(map.get_temp::<String>(b), Some("Hello World".to_owned()));
733}
734
735#[test]
736fn test_one_id_two_types() {
737    let id = Id::new("a");
738
739    let mut map: IdTypeMap = Default::default();
740    map.insert_persisted(id, 13.37);
741    map.insert_temp(id, 42);
742
743    assert_eq!(map.get_temp::<f64>(id), Some(13.37));
744    assert_eq!(map.get_persisted::<f64>(id), Some(13.37));
745    assert_eq!(map.get_temp::<i32>(id), Some(42));
746
747    // ------------
748    // Test removal:
749
750    // We can remove:
751    map.remove::<i32>(id);
752    assert_eq!(map.get_temp::<i32>(id), None);
753
754    // Other type is still there, even though it is the same if:
755    assert_eq!(map.get_temp::<f64>(id), Some(13.37));
756    assert_eq!(map.get_persisted::<f64>(id), Some(13.37));
757
758    // But we can still remove the last:
759    map.remove::<f64>(id);
760    assert_eq!(map.get_temp::<f64>(id), None);
761    assert_eq!(map.get_persisted::<f64>(id), None);
762}
763
764#[test]
765fn test_mix() {
766    #[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
767    #[derive(Clone, Debug, PartialEq)]
768    struct Foo(i32);
769
770    #[derive(Clone, Debug, PartialEq)]
771    struct Bar(f32);
772
773    let id = Id::new("a");
774
775    let mut map: IdTypeMap = Default::default();
776    map.insert_persisted(id, Foo(555));
777    map.insert_temp(id, Bar(1.0));
778
779    assert_eq!(map.get_temp::<Foo>(id), Some(Foo(555)));
780    assert_eq!(map.get_persisted::<Foo>(id), Some(Foo(555)));
781    assert_eq!(map.get_temp::<Bar>(id), Some(Bar(1.0)));
782
783    // ------------
784    // Test removal:
785
786    // We can remove:
787    map.remove::<Bar>(id);
788    assert_eq!(map.get_temp::<Bar>(id), None);
789
790    // Other type is still there, even though it is the same if:
791    assert_eq!(map.get_temp::<Foo>(id), Some(Foo(555)));
792    assert_eq!(map.get_persisted::<Foo>(id), Some(Foo(555)));
793
794    // But we can still remove the last:
795    map.remove::<Foo>(id);
796    assert_eq!(map.get_temp::<Foo>(id), None);
797    assert_eq!(map.get_persisted::<Foo>(id), None);
798}
799
800#[cfg(feature = "persistence")]
801#[test]
802fn test_mix_serialize() {
803    use serde::{Deserialize, Serialize};
804
805    #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
806    struct Serializable(i32);
807
808    #[derive(Clone, Debug, PartialEq)]
809    struct NonSerializable(f32);
810
811    let id = Id::new("a");
812
813    let mut map: IdTypeMap = Default::default();
814    map.insert_persisted(id, Serializable(555));
815    map.insert_temp(id, NonSerializable(1.0));
816
817    assert_eq!(map.get_temp::<Serializable>(id), Some(Serializable(555)));
818    assert_eq!(
819        map.get_persisted::<Serializable>(id),
820        Some(Serializable(555))
821    );
822    assert_eq!(
823        map.get_temp::<NonSerializable>(id),
824        Some(NonSerializable(1.0))
825    );
826
827    // -----------
828
829    let serialized = ron::to_string(&map).unwrap();
830
831    // ------------
832    // Test removal:
833
834    // We can remove:
835    map.remove::<NonSerializable>(id);
836    assert_eq!(map.get_temp::<NonSerializable>(id), None);
837
838    // Other type is still there, even though it is the same if:
839    assert_eq!(map.get_temp::<Serializable>(id), Some(Serializable(555)));
840    assert_eq!(
841        map.get_persisted::<Serializable>(id),
842        Some(Serializable(555))
843    );
844
845    // But we can still remove the last:
846    map.remove::<Serializable>(id);
847    assert_eq!(map.get_temp::<Serializable>(id), None);
848    assert_eq!(map.get_persisted::<Serializable>(id), None);
849
850    // --------------------
851    // Test deserialization:
852
853    let mut map: IdTypeMap = ron::from_str(&serialized).unwrap();
854    assert_eq!(map.get_temp::<Serializable>(id), None);
855    assert_eq!(
856        map.get_persisted::<Serializable>(id),
857        Some(Serializable(555))
858    );
859    assert_eq!(map.get_temp::<Serializable>(id), Some(Serializable(555)));
860}
861
862#[cfg(feature = "persistence")]
863#[test]
864fn test_serialize_generations() {
865    use serde::{Deserialize, Serialize};
866
867    fn serialize_and_deserialize(map: &IdTypeMap) -> IdTypeMap {
868        let serialized = ron::to_string(map).unwrap();
869        ron::from_str(&serialized).unwrap()
870    }
871
872    #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
873    struct A(i32);
874
875    let mut map: IdTypeMap = Default::default();
876    for i in 0..3 {
877        map.insert_persisted(Id::new(i), A(i));
878    }
879    for i in 0..3 {
880        assert_eq!(map.get_generation::<A>(Id::new(i)), Some(0));
881    }
882
883    map = serialize_and_deserialize(&map);
884
885    // We use generation 0 for non-serilized,
886    // 1 for things that have been serialized but never deserialized,
887    // and then we increment with 1 on each deserialize.
888    // So we should have generation 2 now:
889    for i in 0..3 {
890        assert_eq!(map.get_generation::<A>(Id::new(i)), Some(2));
891    }
892
893    // Reading should reset:
894    assert_eq!(map.get_persisted::<A>(Id::new(0)), Some(A(0)));
895    assert_eq!(map.get_generation::<A>(Id::new(0)), Some(0));
896
897    // Generations should increment:
898    map = serialize_and_deserialize(&map);
899    assert_eq!(map.get_generation::<A>(Id::new(0)), Some(2));
900    assert_eq!(map.get_generation::<A>(Id::new(1)), Some(3));
901}
902
903#[cfg(feature = "persistence")]
904#[test]
905fn test_serialize_gc() {
906    use serde::{Deserialize, Serialize};
907
908    fn serialize_and_deserialize(mut map: IdTypeMap, max_bytes_per_type: usize) -> IdTypeMap {
909        map.set_max_bytes_per_type(max_bytes_per_type);
910        let serialized = ron::to_string(&map).unwrap();
911        ron::from_str(&serialized).unwrap()
912    }
913
914    #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
915    struct A(usize);
916
917    #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
918    struct B(usize);
919
920    let mut map: IdTypeMap = Default::default();
921
922    let num_a = 1_000;
923    let num_b = 10;
924
925    for i in 0..num_a {
926        map.insert_persisted(Id::new(i), A(i));
927    }
928    for i in 0..num_b {
929        map.insert_persisted(Id::new(i), B(i));
930    }
931
932    map = serialize_and_deserialize(map, 100);
933
934    // We always serialize at least one generation:
935    assert_eq!(map.count::<A>(), num_a);
936    assert_eq!(map.count::<B>(), num_b);
937
938    // Create a new small generation:
939    map.insert_persisted(Id::new(1_000_000), A(1_000_000));
940    map.insert_persisted(Id::new(1_000_000), B(1_000_000));
941
942    assert_eq!(map.count::<A>(), num_a + 1);
943    assert_eq!(map.count::<B>(), num_b + 1);
944
945    // And read a value:
946    assert_eq!(map.get_persisted::<A>(Id::new(0)), Some(A(0)));
947    assert_eq!(map.get_persisted::<B>(Id::new(0)), Some(B(0)));
948
949    map = serialize_and_deserialize(map, 100);
950
951    assert_eq!(
952        map.count::<A>(),
953        2,
954        "We should have dropped the oldest generation, but kept the new value and the read value"
955    );
956    assert_eq!(
957        map.count::<B>(),
958        num_b + 1,
959        "B should fit under the byte limit"
960    );
961
962    // Create another small generation:
963    map.insert_persisted(Id::new(2_000_000), A(2_000_000));
964    map.insert_persisted(Id::new(2_000_000), B(2_000_000));
965
966    map = serialize_and_deserialize(map, 100);
967
968    assert_eq!(map.count::<A>(), 3); // The read value, plus the two new ones
969    assert_eq!(map.count::<B>(), num_b + 2); // all the old ones, plus two new ones
970
971    // Lower the limit, and we should only have the latest generation:
972
973    map = serialize_and_deserialize(map, 1);
974
975    assert_eq!(map.count::<A>(), 1);
976    assert_eq!(map.count::<B>(), 1);
977
978    assert_eq!(
979        map.get_persisted::<A>(Id::new(2_000_000)),
980        Some(A(2_000_000))
981    );
982    assert_eq!(
983        map.get_persisted::<B>(Id::new(2_000_000)),
984        Some(B(2_000_000))
985    );
986}