anymap_serde/
stable_type_id.rs

1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4/// An opaque holder for a stable, deterministic identifier for a Rust type.
5#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
6#[serde(transparent)]
7pub struct StableTypeId(String);
8
9impl fmt::Display for StableTypeId {
10    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11        self.0.fmt(f)
12    }
13}
14
15impl StableTypeId {
16    /// Returns the **stable string key** associated with type `T`.
17    ///
18    /// # Overview
19    ///
20    /// This function produces a deterministic, globally stable identifier for a
21    /// Rust type by returning the fully-qualified name produced by
22    /// [`core::any::type_name`].
23    ///
24    /// The resulting key is:
25    ///
26    /// - **Bijective** – each distinct type maps to a distinct string key.
27    /// - **Deterministic** – the same type always produces the same key within a
28    ///   given version of this crate.
29    /// - **Pure** – no side effects; does not depend on runtime state.
30    /// - **Compilation-unit stable** – the returned value does not depend on memory
31    ///   layout, type IDs, or other non-portable properties.
32    ///
33    /// This key is used internally by the serializable anymap to index entries by
34    /// their type. Because `TypeId` is not stable across compilation units or
35    /// compiler versions, string keys offer a portable alternative suitable for
36    /// serialization.
37    ///
38    /// # Stability Guarantees
39    ///
40    /// Changing the **implementation of this function is to be considered a breaking change**
41    ///
42    /// Consumers relying on serialized output can therefore depend on this value
43    /// as a long-term stable identifier for the type.
44    ///
45    /// # Caveats
46    ///
47    /// The current implementatino relies on std::any::type_name, which is *NOT* guaranteed to be
48    /// stable across rustc versions, although change is unlikely.
49    ///
50    /// # Examples
51    ///
52    /// ```
53    /// use anymap_serde::StableTypeId;
54    ///
55    /// let k1 = StableTypeId::for_type::<i32>();
56    /// let k2 = StableTypeId::for_type::<Option<String>>();
57    ///
58    /// assert_eq!(format!("{}", k1), "i32");
59    /// assert_eq!(format!("{}", k2), "core::option::Option<alloc::string::String>");
60    /// ```
61    ///
62    /// # Notes
63    ///
64    /// - The function returns an owned `String` rather than a `&'static str`,
65    ///   because the underlying representation from `type_name` is returned as a
66    ///   borrowed string and needs to be materialized for storage.
67    /// - For generic types, the key includes full type parameters in a canonical
68    ///   format.
69    ///
70    /// # See Also
71    ///
72    /// - [`core::any::type_name`] – the underlying mechanism used to generate the key.
73    ///
74    /// # Returns
75    ///
76    /// A stable, deterministic string key uniquely identifying the type `T`.
77    pub fn for_type<T>() -> StableTypeId {
78        StableTypeId(std::any::type_name::<T>().to_string())
79    }
80}