Skip to content

Commit 1c3b1ee

Browse files
committed
Clean up the IdAnyMap code
1 parent 4e7e28c commit 1c3b1ee

File tree

2 files changed

+47
-15
lines changed

2 files changed

+47
-15
lines changed

egui/src/context.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,13 @@ impl Context {
868868
*self.memory() = Default::default();
869869
}
870870

871+
let num_state = self.memory().data.len();
872+
let num_serialized = self.memory().data.count_serialized();
873+
ui.label(format!(
874+
"{} widget states stored (of which {} are serialized).",
875+
num_state, num_serialized
876+
));
877+
871878
ui.horizontal(|ui| {
872879
ui.label(format!(
873880
"{} areas (panels, windows, popups, …)",

egui/src/util/id_any_map.rs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
// TODO: it is possible we can simplify `Element` further by
2-
// assuming everything is "faalible" serializable, and by supplying serialize/deserialize functions for them.
2+
// assuming everything is possibly serializable, and by supplying serialize/deserialize functions for them.
33
// For non-serializable types, these simply return `None`.
44
// This will also allow users to pick their own serialization format per type.
55

66
use std::any::Any;
77

88
// -----------------------------------------------------------------------------------------------
99

10-
/// We need this because `TypeId` can't be deserialized or serialized directly, but this can be done using hashing. However, there is a small possibility that different types will have intersection by hashes of their type ids.
11-
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
10+
/// Like [`std::any::TypeId`], but can be serialized and deserialized.
11+
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
1212
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
1313
pub struct TypeId(u64);
1414

@@ -64,21 +64,22 @@ struct SerializedElement {
6464
type Serializer = fn(&Box<dyn Any + 'static + Send + Sync>) -> Option<String>;
6565

6666
enum Element {
67-
/// A value, possibly serializable
67+
/// A value, maybe serializable.
6868
Value {
6969
/// The actual value.
7070
value: Box<dyn Any + 'static + Send + Sync>,
7171

7272
/// How to clone the value.
7373
clone_fn: fn(&Box<dyn Any + 'static + Send + Sync>) -> Box<dyn Any + 'static + Send + Sync>,
7474

75-
/// How to serialize the vlaue.
75+
/// How to serialize the value.
7676
/// None if non-serializable type.
7777
#[cfg(feature = "persistence")]
7878
serialize_fn: Option<Serializer>,
7979
},
80+
/// A serialized value
8081
Serialized {
81-
/// The type stored.
82+
/// The type of value we are storing.
8283
type_id: TypeId,
8384
/// The ron data we can deserialize.
8485
ron: String,
@@ -125,6 +126,7 @@ impl std::fmt::Debug for Element {
125126
}
126127

127128
impl Element {
129+
/// Create a value that won't be persisted.
128130
#[inline]
129131
pub(crate) fn new_temp<T: 'static + Any + Clone + Send + Sync>(t: T) -> Self {
130132
Self::Value {
@@ -138,6 +140,7 @@ impl Element {
138140
}
139141
}
140142

143+
/// Create a value that will be persisted.
141144
#[inline]
142145
pub(crate) fn new_persisted<T: SerializableAny>(t: T) -> Self {
143146
Self::Value {
@@ -154,6 +157,7 @@ impl Element {
154157
}
155158
}
156159

160+
/// The type of the stored value.
157161
#[inline]
158162
pub(crate) fn type_id(&self) -> TypeId {
159163
match self {
@@ -272,7 +276,7 @@ fn from_ron_str<T: serde::de::DeserializeOwned>(ron: &str) -> Option<T> {
272276
Ok(value) => Some(value),
273277
Err(err) => {
274278
eprintln!(
275-
"egui: Failed to deserialize {} from memory: {}, ron: {:?}",
279+
"egui: Failed to deserialize {} from memory: {}, ron error: {:?}",
276280
std::any::type_name::<T>(),
277281
err,
278282
ron
@@ -290,7 +294,10 @@ use crate::Id;
290294
/// Stores any value identified by their type and a given [`Id`].
291295
///
292296
/// Values can either be "persisted" (serializable) or "temporary" (cleared when egui is shut down).
297+
///
298+
/// You can store state using the key [`Id::null`]. The state will then only be identified by its type.
293299
#[derive(Clone, Debug, Default)]
300+
// We store use `id XOR typeid` as a key, so we don't need to hash again!
294301
pub struct IdAnyMap(nohash_hasher::IntMap<u64, Element>);
295302

296303
impl IdAnyMap {
@@ -308,7 +315,7 @@ impl IdAnyMap {
308315
self.0.insert(hash, Element::new_persisted(value));
309316
}
310317

311-
/// Read a value without trying to deserialize a persited value.
318+
/// Read a value without trying to deserialize a persisted value.
312319
#[inline]
313320
pub fn get_temp<T: 'static + Clone>(&mut self, id: Id) -> Option<T> {
314321
let hash = hash(TypeId::of::<T>(), id);
@@ -391,13 +398,14 @@ impl IdAnyMap {
391398
}
392399
}
393400

401+
/// Remove the state of this type an id.
394402
#[inline]
395403
pub fn remove<T: 'static>(&mut self, id: Id) {
396404
let hash = hash(TypeId::of::<T>(), id);
397405
self.0.remove(&hash);
398406
}
399407

400-
/// Note that this function could not remove all needed types between runs because if you upgraded the Rust version or for other reasons.
408+
/// Note all state of the given type.
401409
pub fn remove_by_type<T: 'static>(&mut self) {
402410
let key = TypeId::of::<T>();
403411
self.0.retain(|_, e| {
@@ -411,7 +419,26 @@ impl IdAnyMap {
411419
self.0.clear();
412420
}
413421

414-
/// You could use this function to find is there some leak or misusage. Note, that result of this function could break between runs, if you upgraded the Rust version or for other reasons.
422+
#[inline]
423+
pub fn is_empty(&mut self) -> bool {
424+
self.0.is_empty()
425+
}
426+
427+
#[inline]
428+
pub fn len(&mut self) -> usize {
429+
self.0.len()
430+
}
431+
432+
/// Count how many values are stored but not yet deserialized.
433+
#[inline]
434+
pub fn count_serialized(&mut self) -> usize {
435+
self.0
436+
.values()
437+
.filter(|e| matches!(e, Element::Serialized { .. }))
438+
.count()
439+
}
440+
441+
/// Count the number of values are stored with the given type.
415442
pub fn count<T: 'static>(&mut self) -> usize {
416443
let key = TypeId::of::<T>();
417444
self.0
@@ -422,10 +449,6 @@ impl IdAnyMap {
422449
})
423450
.count()
424451
}
425-
426-
pub fn count_all(&mut self) -> usize {
427-
self.0.len()
428-
}
429452
}
430453

431454
#[inline(always)]
@@ -435,13 +458,15 @@ fn hash(type_id: TypeId, id: Id) -> u64 {
435458

436459
// ----------------------------------------------------------------------------
437460

461+
/// How [`IdAnyMap`] is persisted.
438462
#[cfg(feature = "persistence")]
439463
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
440-
pub struct PersistedMap(Vec<(u64, SerializedElement)>);
464+
struct PersistedMap(Vec<(u64, SerializedElement)>);
441465

442466
#[cfg(feature = "persistence")]
443467
impl PersistedMap {
444468
fn from_map(map: &IdAnyMap) -> Self {
469+
// filter out the elements which cannot be serialized:
445470
Self(
446471
map.0
447472
.iter()

0 commit comments

Comments
 (0)