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}