anymap_serde/lib.rs
1//! A serializable AnyMap-like container keyed by `type_name::<T>()`.
2//!
3//! This crate provides `SerializableAnyMap`, an AnyMap-compatible container that
4//! stores values in a serializable form (`serde_value::Value`) and optionally
5//! caches a deserialized `Box<dyn Any>` for fast access. Keys are the stable
6//! string returned by `key_for_type::<T>()`, not `TypeId`, which makes
7//! the map suitable for sending over the network and reconstructing on another
8//! process / compilation unit.
9//!
10//! Key properties:
11//! - The on-disk / on-wire representation is a `HashMap<String, serde_value::Value>`.
12//! - Deserialized values are stored in-memory only and are not serialized.
13//! - Inserting a value serializes it immediately and stores the value in both forms.
14//! - Deserialization reconstructs only the serialized representation; the cache is empty
15//! until a lazy access triggers deserialization, since we don't have access to type information
16//! at collection deserialization time
17//!
18//! # Motivation
19//!
20//! This is useful for extension holders (for example request extensions) where
21//! heterogeneous typed data must be transported and reconstructed remotely.
22//!
23//! Example (illustrative):
24//! ```rust
25//! # use serde::{Serialize, Deserialize};
26//! # use serde_json;
27//! # use anymap_serde::SerializableAnyMap;
28//! #[derive(Serialize, Deserialize, Debug, PartialEq)]
29//! struct Ext { a: u32 }
30//!
31//! let mut map = SerializableAnyMap::new();
32//! map.insert(Ext { a: 10 });
33//!
34//! // Serialize to JSON
35//! let json = serde_json::to_string(&map).unwrap();
36//!
37//! // On the other side, deserialize and access the stored type by `type_name::<T>()`
38//! let mut map2: SerializableAnyMap = serde_json::from_str(&json).unwrap();
39//! let value: &Ext = map2.get::<Ext>().unwrap().unwrap();
40//! assert_eq!(value.a, 10);
41//! ```
42
43#![deny(missing_docs, unused, warnings)]
44
45mod entry;
46mod write_guard;
47
48use crate::entry::{Entry, OccupiedEntry, OccupiedError, VacantEntry};
49use crate::write_guard::WriteGuard;
50use serde::{Deserialize, Serialize};
51use serde_value::{Value, to_value};
52use std::collections::hash_map;
53use std::{any::Any, collections::HashMap};
54
55/// A serializable heterogeneous-map keyed by the stable `type_name::<T>()`.
56///
57/// `SerializableAnyMap` behaves like `anymap3` for most basic use-cases but
58/// stores values in serialized form so the entire map can be serialized and
59/// sent across process boundaries. The map implements `Serialize` and
60/// `Deserialize` where only the serialized form is persisted; the cached
61/// deserialized values are not persisted.
62///
63/// Inserted types must implement `Serialize + Deserialize<'de> + 'static`.
64///
65/// See method docs for usage patterns (`insert`, `get`, `get_mut`, `entry`, …).
66///
67/// Safety notes:
68/// - Some escape hatches (`as_raw_mut`, `from_raw`) are `unsafe` — the caller
69/// must ensure the key string matches the type stored under it.
70///
71/// A stored entry containing the serialized representation and an optional
72/// cached runtime value.
73///
74#[derive(Default, Serialize, Deserialize, Debug, Clone)]
75#[serde(transparent)]
76pub struct SerializableAnyMap {
77 raw: HashMap<String, Wrapper>,
78}
79
80impl SerializableAnyMap {
81 /// Create a new empty `SerializableAnyMap`.
82 #[inline]
83 pub fn new() -> Self {
84 Self {
85 raw: HashMap::new(),
86 }
87 }
88
89 /// Create a new `SerializableAnyMap` with the specified capacity.
90 #[inline]
91 pub fn with_capacity(capacity: usize) -> Self {
92 Self {
93 raw: HashMap::with_capacity(capacity),
94 }
95 }
96
97 /// Returns the number of elements the map can hold without reallocating.
98 #[inline]
99 pub fn capacity(&self) -> usize {
100 self.raw.capacity()
101 }
102
103 /// Reserves capacity for at least `additional` more elements to be inserted.
104 /// The collection may reserve more space to avoid frequent reallocations.
105 ///
106 /// # Panics
107 ///
108 /// Panics if the new capacity overflows `usize`.
109 #[inline]
110 pub fn reserve(&mut self, additional: usize) {
111 self.raw.reserve(additional);
112 }
113
114 /// Shrinks the capacity of the collection as much as possible. It will drop
115 /// down as much as possible while maintaining the internal rules
116 /// and possibly leaving some space in accordance with the resize policy.
117 #[inline]
118 pub fn shrink_to_fit(&mut self) {
119 self.raw.shrink_to_fit()
120 }
121
122 // Additional stable methods (as of 1.60.0-nightly) that could be added:
123 // try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> (1.57.0)
124 // shrink_to(&mut self, min_capacity: usize) (1.56.0)
125
126 /// Returns the number of items in the collection.
127 #[inline]
128 pub fn len(&self) -> usize {
129 self.raw.len()
130 }
131
132 /// Returns true if there are no items in the collection.
133 #[inline]
134 pub fn is_empty(&self) -> bool {
135 self.raw.is_empty()
136 }
137
138 /// Removes all items from the collection. Keeps the allocated memory for reuse.
139 #[inline]
140 pub fn clear(&mut self) {
141 self.raw.clear()
142 }
143
144 /// Get an immutable reference to a cached value of type `T` if it exists AND was deserialized.
145 ///
146 /// # Notes
147 ///
148 /// This does NOT lazily deserialize, use [`Self::get`] if you want lazy deserialization.
149 /// This may return None even if the type is present in the map, but not deserialized.
150 ///
151 #[inline]
152 pub fn try_get<T>(&self) -> Option<&T>
153 where
154 T: for<'de> Deserialize<'de> + Any + 'static,
155 {
156 let key = key_for_type::<T>().to_string();
157 self.raw.get(&key)?.try_get()
158 }
159
160 /// Get an immutable reference to a value of type `T`, lazily deserializing if necessary.
161 ///
162 /// # Notes
163 ///
164 /// This requires a `&mut self` since it may need to deserialize and modify the entry.
165 #[inline]
166 pub fn get<T>(&mut self) -> Option<Result<&T, serde_value::DeserializerError>>
167 where
168 T: Serialize + for<'de> Deserialize<'de> + 'static,
169 {
170 Self::get_mut(self).map(|r| r.map(|v: WriteGuard<T>| v.into_ref()))
171 }
172
173 /// Gets a copy value of type `T`, by deserializing the value in the map.
174 ///
175 /// # Warning
176 ///
177 /// This always runs deserialization, and may return an instance that is not equivalent to the one
178 /// in the map if any fields are marked `#[serde(skip)]` for example.
179 ///
180 #[inline]
181 pub fn get_deserialized_copy<T>(&self) -> Option<T>
182 where
183 T: for<'de> Deserialize<'de> + Any + 'static,
184 {
185 self.get_serialized_value::<T>()
186 .and_then(|v| T::deserialize(v.clone()).ok())
187 }
188
189 /// Get a mutable reference to a value of type `T`, lazily deserializing into the cache if necessary.
190 pub fn get_mut<T>(
191 &mut self,
192 ) -> Option<Result<WriteGuard<'_, T>, serde_value::DeserializerError>>
193 where
194 T: Serialize + for<'de> Deserialize<'de> + Any + 'static,
195 {
196 let key = key_for_type::<T>().to_string();
197 Some(self.raw.get_mut(&key)?.get_mut())
198 }
199
200 /// Get the serialized `serde_value::Value` for type `T` if present.
201 #[inline]
202 pub fn get_serialized_value<T>(&self) -> Option<&Value>
203 where
204 T: 'static,
205 {
206 let key = key_for_type::<T>().to_string();
207 self.raw.get(&key).map(|e| &e.serialized)
208 }
209
210 /// Insert by type name key.
211 ///
212 /// This is lower-level and useful if you already have a Value.
213 ///
214 /// # Safety
215 /// The provided Value needs to match the given matches the type name.
216 #[inline]
217 pub unsafe fn insert_value_by_name(
218 &mut self,
219 type_name: String,
220 value: Value,
221 ) -> Option<Value> {
222 let e = Wrapper {
223 serialized: value,
224 value: None,
225 };
226 self.raw.insert(type_name, e).map(|e| e.serialized)
227 }
228
229 /// Insert a value of type `T`. Returns the previous value of that type if present.
230 #[inline]
231 pub fn insert<T>(&mut self, value: T) -> Option<Result<T, serde_value::DeserializerError>>
232 where
233 T: Serialize + for<'de> Deserialize<'de> + Any + 'static,
234 {
235 let key = key_for_type::<T>().to_string();
236 let serialized = to_value(&value).expect("serialization failed");
237
238 let new_entry = Wrapper {
239 serialized,
240 value: Some(Box::new(value)),
241 };
242 self.raw
243 .insert(key, new_entry)
244 .map(|old| old.into_inner::<T>())
245 }
246
247 /// Tries to insert a value into the map, and returns
248 /// a mutable reference to the value if successful.
249 ///
250 /// If the map already had this type of value present, nothing is updated, and
251 /// an error containing the occupied entry and the value is returned.
252 pub fn try_insert<'a, T>(
253 &'a mut self,
254 value: T,
255 ) -> Result<WriteGuard<'a, T>, OccupiedError<'a, T>>
256 where
257 T: Serialize + for<'de> Deserialize<'de> + Any + 'static,
258 {
259 match self.entry::<T>() {
260 Entry::Occupied(entry) => Err(OccupiedError { entry, value }),
261 Entry::Vacant(entry) => Ok(entry.insert(value)),
262 }
263 }
264
265 /// Remove the stored value of type `T`, returning it if was present, or None if it was not.
266 #[inline]
267 pub fn remove<T>(&mut self) -> Option<T>
268 where
269 T: Serialize + for<'de> Deserialize<'de> + Any + 'static,
270 {
271 let key = key_for_type::<T>().to_string();
272 self.raw
273 .remove(&key)
274 .and_then(|entry| entry.into_inner::<T>().ok())
275 }
276
277 /// Returns true if a value of type `T` exists in the map (regardless whether already deserialized or not).
278 #[inline]
279 pub fn contains<T>(&self) -> bool
280 where
281 T: 'static,
282 {
283 let key = key_for_type::<T>().to_string();
284 self.raw.contains_key(&key)
285 }
286
287 /// Returns true if a value of type `T` exists in the map and has already been deserialized
288 #[inline]
289 pub fn contains_deserialized<T>(&self) -> bool
290 where
291 T: 'static,
292 {
293 let key = key_for_type::<T>().to_string();
294 self.raw.contains_key(&key)
295 }
296
297 /// Entry API similar to `HashMap::entry` / `anymap3::entry::<T>()`.
298 #[inline]
299 pub fn entry<T>(&mut self) -> Entry<'_, T>
300 where
301 T: Serialize + for<'de> Deserialize<'de> + Any + 'static,
302 {
303 let key = key_for_type::<T>().to_string();
304
305 let should_remove = match self.raw.entry(key.clone()) {
306 hash_map::Entry::Occupied(mut inner) => inner.get_mut().get_mut::<T>().is_err(),
307 _ => false,
308 };
309
310 if should_remove {
311 self.raw.remove(&key);
312 }
313
314 match self.raw.entry(key) {
315 hash_map::Entry::Occupied(inner) => Entry::Occupied(OccupiedEntry::new(inner)),
316 hash_map::Entry::Vacant(inner) => Entry::Vacant(VacantEntry::new(inner)),
317 }
318 }
319
320 /// Return an iterator over type-name keys.
321 pub fn keys(&self) -> impl Iterator<Item = &String> {
322 self.raw.keys()
323 }
324
325 /// Get access to the raw hash map that backs this.
326 ///
327 /// This will seldom be useful, but it’s conceivable that you could wish to iterate
328 /// over all the items in the collection, and this lets you do that.
329 #[inline]
330 pub fn as_raw(&self) -> &HashMap<String, Wrapper> {
331 &self.raw
332 }
333
334 /// Get mutable access to the raw hash map that backs this.
335 ///
336 /// This will seldom be useful, but it’s conceivable that you could wish to iterate
337 /// over all the items in the collection mutably, or drain or something, or *possibly*
338 /// even batch insert, and this lets you do that.
339 ///
340 /// # Safety
341 ///
342 /// If you insert any values to the raw map, the key (a `String`) must match the
343 /// value’s type name as returned by any::type_name(), or *undefined behaviour* will occur when you access those values.
344 ///
345 /// (*Removing* entries is perfectly safe.)
346 #[inline]
347 pub unsafe fn as_raw_mut(&mut self) -> &mut HashMap<String, Wrapper> {
348 &mut self.raw
349 }
350
351 /// Convert this into the raw hash map that backs this.
352 ///
353 /// This will seldom be useful, but it’s conceivable that you could wish to consume all
354 /// the items in the collection and do *something* with some or all of them, and this
355 /// lets you do that, without the `unsafe` that `.as_raw_mut().drain()` would require.
356 #[inline]
357 pub fn into_raw(self) -> HashMap<String, Wrapper> {
358 self.raw
359 }
360
361 /// Construct a map from a collection of raw values.
362 ///
363 /// You know what? I can’t immediately think of any legitimate use for this.
364 ///
365 /// Perhaps this will be most practical as `unsafe { SerializableAnyMap::from_raw(iter.collect()) }`,
366 /// `iter` being an iterator over `(String, Box<dyn Any + Serialize + Deserialize + 'static>)` pairs.
367 /// Eh, this method provides symmetry with `into_raw`, so I don’t care if literally no one ever uses it. I’m not
368 /// even going to write a test for it, it’s so trivial.
369 ///
370 /// # Safety
371 ///
372 /// For all entries in the raw map, the key (a `String`) must match the value’s type as returned by any::type_name(),
373 /// or *undefined behaviour* will occur when you access that entry.
374 #[inline]
375 pub unsafe fn from_raw(raw: HashMap<String, Wrapper>) -> SerializableAnyMap {
376 Self { raw }
377 }
378}
379
380impl<A: Any + Serialize + for<'de> Deserialize<'de>> Extend<Box<A>> for SerializableAnyMap {
381 #[inline]
382 fn extend<T: IntoIterator<Item = Box<A>>>(&mut self, iter: T) {
383 for item in iter {
384 let serialized = to_value(&*item).expect("serialization failed");
385 let _ = self.raw.insert(
386 key_for_type::<T>().to_string(),
387 Wrapper {
388 serialized,
389 value: Some(item),
390 },
391 );
392 }
393 }
394}
395
396/// A stored entry containing the serialized representation and an optional
397/// cached runtime value.
398///
399/// - `serialized`: the `serde_value::Value` used for Serialize/Deserialize of the map.
400/// - `value`: an optional `Box<dyn Any>` holding the deserialized value. This field is not
401/// serialized and is cleared on `Clone` and `Deserialize`.
402///
403/// Semantics:
404/// - On `insert`, both `serialized` and `value` are populated.
405/// - On access (`get`/`get_mut`), the entry will lazily deserialize `serialized` into
406/// `value` if the cache is empty.
407/// - `into_inner` attempts to extract the concrete type from the cache or by deserializing.
408///
409/// Notes:
410/// - The cloning, serialization and deserialization happens based on the serialized `serde_value::Value`, so
411/// any modifications to fields that are marked `#[serde(skip)]` will not be lost after a serialization
412/// round-trip, or after cloning the map.
413/// - Currently any modifications to the cached `value` are not reflected back into the `serialized` form, so
414/// serialization WILL reflect the original value only. This is a known limitation and is planned to be
415/// addressed in a future version by returning a Guard object that will update the serialized value on Drop.
416#[derive(Serialize, Deserialize, Debug)]
417#[serde(transparent)]
418pub struct Wrapper {
419 serialized: Value,
420
421 /// value runtime representation; skipped during (de)serialization.
422 #[serde(skip)]
423 #[serde(default)]
424 value: Option<Box<dyn Any>>,
425}
426
427impl Clone for Wrapper {
428 fn clone(&self) -> Self {
429 Wrapper {
430 serialized: self.serialized.clone(),
431 value: None, // do not clone cached value
432 }
433 }
434}
435
436impl Wrapper {
437 /// Attempt to get an immutable reference to the deserialized value of type `T`. Will return None
438 /// if the value has not yet been deserialized, as we need a mutable reference to mutate the
439 /// entry to save the deserialized value.
440 pub fn try_get<T>(&self) -> Option<&T>
441 where
442 T: for<'de> Deserialize<'de> + 'static,
443 {
444 self.value.as_ref()?.downcast_ref::<T>()
445 }
446
447 /// Attempt to get an immutable reference to the deserialized value of type `T`,
448 /// lazily deserializing if necessary. We need a mutable reference in order to save the
449 /// deserialized value to the entry
450 pub fn get<T>(&mut self) -> Result<&T, serde_value::DeserializerError>
451 where
452 T: Serialize + for<'de> Deserialize<'de> + 'static,
453 {
454 self.get_mut().map(|x: WriteGuard<T>| x.into_ref())
455 }
456
457 /// Attempt to an mutable reference to the deserialized value of type `T`,
458 /// lazily deserializing if necessary.
459 pub fn get_mut<'a, T>(&'a mut self) -> Result<WriteGuard<'a, T>, serde_value::DeserializerError>
460 where
461 T: for<'de> Deserialize<'de> + Serialize + 'static,
462 {
463 if self.value.is_none() {
464 let deserialized = T::deserialize(self.serialized.clone())?;
465 self.value = Some(Box::new(deserialized));
466 }
467
468 Ok(WriteGuard::new(self))
469 }
470
471 /// Attempt to extract the inner value by deserializing if necessary.
472 pub fn into_inner<T>(mut self) -> Result<T, serde_value::DeserializerError>
473 where
474 T: for<'de> Deserialize<'de> + 'static,
475 {
476 self.value
477 .take()
478 .map(|a| Ok(*a.downcast::<T>().unwrap()))
479 .unwrap_or_else(|| T::deserialize(self.serialized))
480 }
481}
482
483/// Get the stable string key for type `T`. Implementation may only change across major versions.
484fn key_for_type<T: ?Sized>() -> String {
485 std::any::type_name::<T>().to_string()
486}