SerdeAnyMap: add unsafe_stable_anymap
feature that uses type_name
instead of TypeId::of
(#1952)
* Test: Use type_name instead of type_id in AnyMap * Hide behind 'unsafe_stable_anymap' feature * nostd? * rename fn * cleanup a bit
This commit is contained in:
parent
5eab4fb78b
commit
2efa747292
@ -63,6 +63,13 @@ xxh3 = ["xxhash-rust"]
|
|||||||
|
|
||||||
#! ### SerdeAny features
|
#! ### SerdeAny features
|
||||||
|
|
||||||
|
## With this feature, the AnyMap uses [`type_name`](https://doc.rust-lang.org/std/any/fn.type_name.html)
|
||||||
|
## instead of [`TypeId::of`](https://doc.rust-lang.org/std/any/struct.TypeId.html#method.of) for deserialization.
|
||||||
|
## With this feature, stored state may remain deserializable across multiple compilations of LibAFL.
|
||||||
|
## This is **unsafe** and may lead to type confusions. Only use when you know what you are doing/ you have tests in place.
|
||||||
|
## The rust doc specifically states that "multiple types may map to the same type name"!
|
||||||
|
unsafe_stable_anymap = []
|
||||||
|
|
||||||
## Automatically register all `#[derive(SerdeAny)]` types at startup.
|
## Automatically register all `#[derive(SerdeAny)]` types at startup.
|
||||||
serdeany_autoreg = ["ctor"]
|
serdeany_autoreg = ["ctor"]
|
||||||
|
|
||||||
|
@ -1,11 +1,54 @@
|
|||||||
//! Poor-rust-man's downcasts for stuff we send over the wire (or shared maps)
|
//! Poor-rust-man's downcasts for stuff we send over the wire (or shared maps)
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
#[cfg(feature = "unsafe_stable_anymap")]
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
|
#[cfg(feature = "unsafe_stable_anymap")]
|
||||||
|
use core::any::type_name;
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
use core::any::TypeId;
|
||||||
use core::{any::Any, fmt::Debug};
|
use core::{any::Any, fmt::Debug};
|
||||||
|
|
||||||
use serde::{de::DeserializeSeed, Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{de::DeserializeSeed, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
pub use serdeany_registry::*;
|
pub use serdeany_registry::*;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
use crate::anymap::unpack_type_id;
|
||||||
|
|
||||||
|
/// The type of a stored type in this anymap (`u128`)
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
pub type TypeRepr = u128;
|
||||||
|
|
||||||
|
/// The type of a stored type in this anymap (`String`)
|
||||||
|
#[cfg(feature = "unsafe_stable_anymap")]
|
||||||
|
pub type TypeRepr = String;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
fn type_repr<T>() -> TypeRepr
|
||||||
|
where
|
||||||
|
T: 'static,
|
||||||
|
{
|
||||||
|
unpack_type_id(TypeId::of::<T>())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
fn type_repr_owned<T>() -> TypeRepr
|
||||||
|
where
|
||||||
|
T: 'static,
|
||||||
|
{
|
||||||
|
unpack_type_id(TypeId::of::<T>())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unsafe_stable_anymap")]
|
||||||
|
fn type_repr_owned<T>() -> TypeRepr {
|
||||||
|
type_name::<T>().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unsafe_stable_anymap")]
|
||||||
|
fn type_repr<T>() -> &'static str {
|
||||||
|
type_name::<T>()
|
||||||
|
}
|
||||||
|
|
||||||
/// A (de)serializable Any trait
|
/// A (de)serializable Any trait
|
||||||
pub trait SerdeAny: Any + erased_serde::Serialize + Debug {
|
pub trait SerdeAny: Any + erased_serde::Serialize + Debug {
|
||||||
/// returns this as Any trait
|
/// returns this as Any trait
|
||||||
@ -67,19 +110,18 @@ where
|
|||||||
pub mod serdeany_registry {
|
pub mod serdeany_registry {
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use core::{any::TypeId, fmt, hash::BuildHasherDefault};
|
use core::{fmt, hash::BuildHasherDefault};
|
||||||
|
|
||||||
use hashbrown::{
|
use hashbrown::{
|
||||||
hash_map::{Keys, Values, ValuesMut},
|
hash_map::{Values, ValuesMut},
|
||||||
HashMap,
|
HashMap,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::SerdeAny;
|
use super::{SerdeAny, TypeRepr};
|
||||||
use crate::{
|
use crate::{
|
||||||
anymap::{pack_type_id, unpack_type_id},
|
|
||||||
hash_std,
|
hash_std,
|
||||||
serdeany::{DeserializeCallback, DeserializeCallbackSeed},
|
serdeany::{type_repr, type_repr_owned, DeserializeCallback, DeserializeCallbackSeed},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -98,7 +140,7 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
V: serde::de::SeqAccess<'de>,
|
V: serde::de::SeqAccess<'de>,
|
||||||
{
|
{
|
||||||
let id: u128 = visitor.next_element()?.unwrap();
|
let id: TypeRepr = visitor.next_element()?.unwrap();
|
||||||
let cb = unsafe {
|
let cb = unsafe {
|
||||||
*REGISTRY
|
*REGISTRY
|
||||||
.deserializers
|
.deserializers
|
||||||
@ -115,7 +157,8 @@ pub mod serdeany_registry {
|
|||||||
|
|
||||||
#[allow(unused_qualifications)]
|
#[allow(unused_qualifications)]
|
||||||
struct Registry {
|
struct Registry {
|
||||||
deserializers: Option<HashMap<u128, DeserializeCallback<dyn crate::serdeany::SerdeAny>>>,
|
deserializers:
|
||||||
|
Option<HashMap<TypeRepr, DeserializeCallback<dyn crate::serdeany::SerdeAny>>>,
|
||||||
finalized: bool,
|
finalized: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +171,7 @@ pub mod serdeany_registry {
|
|||||||
assert!(!self.finalized, "Registry is already finalized!");
|
assert!(!self.finalized, "Registry is already finalized!");
|
||||||
|
|
||||||
let deserializers = self.deserializers.get_or_insert_with(HashMap::default);
|
let deserializers = self.deserializers.get_or_insert_with(HashMap::default);
|
||||||
deserializers.insert(unpack_type_id(TypeId::of::<T>()), |de| {
|
deserializers.insert(type_repr_owned::<T>(), |de| {
|
||||||
Ok(Box::new(erased_serde::deserialize::<T>(de)?))
|
Ok(Box::new(erased_serde::deserialize::<T>(de)?))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -181,7 +224,7 @@ pub mod serdeany_registry {
|
|||||||
#[allow(clippy::unsafe_derive_deserialize)]
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct SerdeAnyMap {
|
pub struct SerdeAnyMap {
|
||||||
map: HashMap<u128, Box<dyn SerdeAny>>,
|
map: HashMap<TypeRepr, Box<dyn SerdeAny>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cloning by serializing and deserializing. It ain't fast, but it's honest work.
|
// Cloning by serializing and deserializing. It ain't fast, but it's honest work.
|
||||||
@ -218,8 +261,12 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
|
let type_repr = type_repr::<T>();
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
let type_repr = &type_repr;
|
||||||
|
|
||||||
self.map
|
self.map
|
||||||
.get(&unpack_type_id(TypeId::of::<T>()))
|
.get(type_repr)
|
||||||
.map(|x| x.as_ref().as_any().downcast_ref::<T>().unwrap())
|
.map(|x| x.as_ref().as_any().downcast_ref::<T>().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,8 +277,12 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
|
let type_repr = type_repr::<T>();
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
let type_repr = &type_repr;
|
||||||
|
|
||||||
self.map
|
self.map
|
||||||
.get_mut(&unpack_type_id(TypeId::of::<T>()))
|
.get_mut(type_repr)
|
||||||
.map(|x| x.as_mut().as_any_mut().downcast_mut::<T>().unwrap())
|
.map(|x| x.as_mut().as_any_mut().downcast_mut::<T>().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,8 +293,12 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
|
let type_repr = type_repr::<T>();
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
let type_repr = &type_repr;
|
||||||
|
|
||||||
self.map
|
self.map
|
||||||
.remove(&unpack_type_id(TypeId::of::<T>()))
|
.remove(type_repr)
|
||||||
.map(|x| x.as_any_boxed().downcast::<T>().unwrap())
|
.map(|x| x.as_any_boxed().downcast::<T>().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,38 +317,42 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
self.entry::<T>().insert(value);
|
self.raw_entry_mut::<T>()
|
||||||
|
.insert(type_repr_owned::<T>(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an entry to an element in this map.
|
/// Get an entry to an element in this map.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_qualifications)]
|
#[allow(unused_qualifications)]
|
||||||
pub fn entry<T>(
|
pub fn raw_entry_mut<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> hashbrown::hash_map::Entry<
|
) -> hashbrown::hash_map::RawEntryMut<
|
||||||
'_,
|
'_,
|
||||||
u128,
|
TypeRepr,
|
||||||
Box<dyn SerdeAny + 'static>,
|
Box<dyn SerdeAny + 'static>,
|
||||||
BuildHasherDefault<ahash::AHasher>,
|
BuildHasherDefault<ahash::AHasher>,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
let id = unpack_type_id(TypeId::of::<T>());
|
let type_repr = type_repr::<T>();
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
let type_repr = &type_repr;
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
unsafe {
|
unsafe {
|
||||||
REGISTRY
|
REGISTRY
|
||||||
.deserializers
|
.deserializers
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("Empty types registry")
|
.expect("Empty types registry")
|
||||||
.get(&id)
|
.get(type_repr)
|
||||||
.is_some()
|
.is_some()
|
||||||
},
|
},
|
||||||
"Type {} was inserted without registration! Call RegistryBuilder::register::<{}>() or use serde_autoreg.",
|
"Type {} was inserted without registration! Call RegistryBuilder::register::<{}>() or use serde_autoreg.",
|
||||||
core::any::type_name::<T>(),
|
core::any::type_name::<T>(),
|
||||||
core::any::type_name::<T>()
|
core::any::type_name::<T>()
|
||||||
);
|
);
|
||||||
self.map.entry(id)
|
self.map.raw_entry_mut().from_key(type_repr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a value by type, or inserts it using the given construction function `default`
|
/// Gets a value by type, or inserts it using the given construction function `default`
|
||||||
@ -309,8 +368,10 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
T: SerdeAny + 'static,
|
T: SerdeAny + 'static,
|
||||||
{
|
{
|
||||||
let ret = self.entry::<T>().or_insert_with(|| default());
|
let ret = self
|
||||||
ret.as_mut().as_any_mut().downcast_mut::<T>().unwrap()
|
.raw_entry_mut::<T>()
|
||||||
|
.or_insert_with(|| (type_repr_owned::<T>(), default()));
|
||||||
|
ret.1.as_any_mut().downcast_mut::<T>().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the count of elements in this map.
|
/// Returns the count of elements in this map.
|
||||||
@ -333,7 +394,11 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
self.map.contains_key(&unpack_type_id(TypeId::of::<T>()))
|
let type_repr = type_repr::<T>();
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
let type_repr = &type_repr;
|
||||||
|
|
||||||
|
self.map.contains_key(type_repr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new [`SerdeAnyMap`].
|
/// Create a new [`SerdeAnyMap`].
|
||||||
@ -356,7 +421,7 @@ pub mod serdeany_registry {
|
|||||||
#[allow(unused_qualifications)]
|
#[allow(unused_qualifications)]
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct NamedSerdeAnyMap {
|
pub struct NamedSerdeAnyMap {
|
||||||
map: HashMap<u128, HashMap<u64, Box<dyn crate::serdeany::SerdeAny>>>,
|
map: HashMap<TypeRepr, HashMap<u64, Box<dyn crate::serdeany::SerdeAny>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cloning by serializing and deserializing. It ain't fast, but it's honest work.
|
// Cloning by serializing and deserializing. It ain't fast, but it's honest work.
|
||||||
@ -377,7 +442,11 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
match self.map.get(&unpack_type_id(TypeId::of::<T>())) {
|
let type_repr = type_repr::<T>();
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
let type_repr = &type_repr;
|
||||||
|
|
||||||
|
match self.map.get(type_repr) {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => h
|
Some(h) => h
|
||||||
.get(&hash_std(name.as_bytes()))
|
.get(&hash_std(name.as_bytes()))
|
||||||
@ -392,7 +461,11 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
match self.map.get_mut(&unpack_type_id(TypeId::of::<T>())) {
|
let type_repr = type_repr::<T>();
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
let type_repr = &type_repr;
|
||||||
|
|
||||||
|
match self.map.get_mut(type_repr) {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => h
|
Some(h) => h
|
||||||
.remove(&hash_std(name.as_bytes()))
|
.remove(&hash_std(name.as_bytes()))
|
||||||
@ -400,29 +473,18 @@ pub mod serdeany_registry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an element of a given type contained in this map by [`TypeId`].
|
/// Get an element of a given type contained in this map by type `T`, as mut.
|
||||||
#[must_use]
|
|
||||||
#[allow(unused_qualifications)]
|
|
||||||
#[inline]
|
|
||||||
pub fn by_typeid(
|
|
||||||
&self,
|
|
||||||
name: &str,
|
|
||||||
typeid: &TypeId,
|
|
||||||
) -> Option<&dyn crate::serdeany::SerdeAny> {
|
|
||||||
match self.map.get(&unpack_type_id(*typeid)) {
|
|
||||||
None => None,
|
|
||||||
Some(h) => h.get(&hash_std(name.as_bytes())).map(AsRef::as_ref),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get an element of a given type contained in this map by [`TypeId`], as mut.
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_mut<T>(&mut self, name: &str) -> Option<&mut T>
|
pub fn get_mut<T>(&mut self, name: &str) -> Option<&mut T>
|
||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
match self.map.get_mut(&unpack_type_id(TypeId::of::<T>())) {
|
let type_repr = type_repr::<T>();
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
let type_repr = &type_repr;
|
||||||
|
|
||||||
|
match self.map.get_mut(type_repr) {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => h
|
Some(h) => h
|
||||||
.get_mut(&hash_std(name.as_bytes()))
|
.get_mut(&hash_std(name.as_bytes()))
|
||||||
@ -430,20 +492,6 @@ pub mod serdeany_registry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an element of a given type contained in this map by [`TypeId`], as mut.
|
|
||||||
#[must_use]
|
|
||||||
#[inline]
|
|
||||||
pub fn by_typeid_mut(
|
|
||||||
&mut self,
|
|
||||||
name: &str,
|
|
||||||
typeid: &TypeId,
|
|
||||||
) -> Option<&mut dyn crate::serdeany::SerdeAny> {
|
|
||||||
match self.map.get_mut(&unpack_type_id(*typeid)) {
|
|
||||||
None => None,
|
|
||||||
Some(h) => h.get_mut(&hash_std(name.as_bytes())).map(AsMut::as_mut),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get all elements of a type contained in this map.
|
/// Get all elements of a type contained in this map.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[allow(unused_qualifications)]
|
#[allow(unused_qualifications)]
|
||||||
@ -460,34 +508,17 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
|
let type_repr = type_repr::<T>();
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
let type_repr = &type_repr;
|
||||||
|
|
||||||
#[allow(clippy::manual_map)]
|
#[allow(clippy::manual_map)]
|
||||||
match self.map.get(&unpack_type_id(TypeId::of::<T>())) {
|
match self.map.get(type_repr) {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => Some(h.values().map(|x| x.as_any().downcast_ref::<T>().unwrap())),
|
Some(h) => Some(h.values().map(|x| x.as_any().downcast_ref::<T>().unwrap())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get all elements of a given type contained in this map by [`TypeId`].
|
|
||||||
#[must_use]
|
|
||||||
#[allow(unused_qualifications)]
|
|
||||||
#[inline]
|
|
||||||
#[allow(clippy::type_complexity)]
|
|
||||||
pub fn all_by_typeid(
|
|
||||||
&self,
|
|
||||||
typeid: &TypeId,
|
|
||||||
) -> Option<
|
|
||||||
core::iter::Map<
|
|
||||||
Values<'_, u64, Box<dyn crate::serdeany::SerdeAny>>,
|
|
||||||
fn(&Box<dyn crate::serdeany::SerdeAny>) -> &dyn crate::serdeany::SerdeAny,
|
|
||||||
>,
|
|
||||||
> {
|
|
||||||
#[allow(clippy::manual_map)]
|
|
||||||
match self.map.get(&unpack_type_id(*typeid)) {
|
|
||||||
None => None,
|
|
||||||
Some(h) => Some(h.values().map(|x| x.as_ref())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get all elements contained in this map, as mut.
|
/// Get all elements contained in this map, as mut.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_qualifications)]
|
#[allow(unused_qualifications)]
|
||||||
@ -503,8 +534,12 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
|
let type_repr = type_repr::<T>();
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
let type_repr = &type_repr;
|
||||||
|
|
||||||
#[allow(clippy::manual_map)]
|
#[allow(clippy::manual_map)]
|
||||||
match self.map.get_mut(&unpack_type_id(TypeId::of::<T>())) {
|
match self.map.get_mut(type_repr) {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => Some(
|
Some(h) => Some(
|
||||||
h.values_mut()
|
h.values_mut()
|
||||||
@ -513,51 +548,18 @@ pub mod serdeany_registry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get all [`TypeId`]`s` contained in this map, as mut.
|
|
||||||
#[inline]
|
|
||||||
#[allow(unused_qualifications)]
|
|
||||||
#[allow(clippy::type_complexity)]
|
|
||||||
pub fn all_by_typeid_mut(
|
|
||||||
&mut self,
|
|
||||||
typeid: &TypeId,
|
|
||||||
) -> Option<
|
|
||||||
core::iter::Map<
|
|
||||||
ValuesMut<'_, u64, Box<dyn crate::serdeany::SerdeAny>>,
|
|
||||||
fn(&mut Box<dyn crate::serdeany::SerdeAny>) -> &mut dyn crate::serdeany::SerdeAny,
|
|
||||||
>,
|
|
||||||
> {
|
|
||||||
#[allow(clippy::manual_map)]
|
|
||||||
match self.map.get_mut(&unpack_type_id(*typeid)) {
|
|
||||||
None => None,
|
|
||||||
Some(h) => Some(h.values_mut().map(|x| x.as_mut())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get all [`TypeId`]`s` contained in this map.
|
|
||||||
#[inline]
|
|
||||||
#[allow(unused_qualifications)]
|
|
||||||
#[allow(clippy::type_complexity)]
|
|
||||||
pub fn all_typeids(
|
|
||||||
&self,
|
|
||||||
) -> core::iter::Map<
|
|
||||||
Keys<'_, u128, HashMap<u64, Box<dyn crate::serdeany::SerdeAny>>>,
|
|
||||||
fn(&u128) -> TypeId,
|
|
||||||
> {
|
|
||||||
self.map.keys().map(|x| pack_type_id(*x))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run `func` for each element in this map.
|
/// Run `func` for each element in this map.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_qualifications)]
|
#[allow(unused_qualifications)]
|
||||||
pub fn for_each<
|
pub fn for_each<
|
||||||
F: FnMut(&TypeId, &Box<dyn crate::serdeany::SerdeAny>) -> Result<(), Error>,
|
F: FnMut(&TypeRepr, &Box<dyn crate::serdeany::SerdeAny>) -> Result<(), Error>,
|
||||||
>(
|
>(
|
||||||
&self,
|
&self,
|
||||||
func: &mut F,
|
func: &mut F,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
for (id, h) in &self.map {
|
for (id, h) in &self.map {
|
||||||
for x in h.values() {
|
for x in h.values() {
|
||||||
func(&pack_type_id(*id), x)?;
|
func(id, x)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -566,14 +568,14 @@ pub mod serdeany_registry {
|
|||||||
/// Run `func` for each element in this map, getting a mutable borrow.
|
/// Run `func` for each element in this map, getting a mutable borrow.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn for_each_mut<
|
pub fn for_each_mut<
|
||||||
F: FnMut(&TypeId, &mut Box<dyn crate::serdeany::SerdeAny>) -> Result<(), Error>,
|
F: FnMut(&TypeRepr, &mut Box<dyn crate::serdeany::SerdeAny>) -> Result<(), Error>,
|
||||||
>(
|
>(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: &mut F,
|
func: &mut F,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
for (id, h) in &mut self.map {
|
for (id, h) in &mut self.map {
|
||||||
for x in h.values_mut() {
|
for x in h.values_mut() {
|
||||||
func(&pack_type_id(*id), x)?;
|
func(id, x)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -604,14 +606,17 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
let id = unpack_type_id(TypeId::of::<T>());
|
let type_repr = type_repr::<T>();
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
let type_repr = &type_repr;
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
unsafe {
|
unsafe {
|
||||||
REGISTRY
|
REGISTRY
|
||||||
.deserializers
|
.deserializers
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("Empty types registry")
|
.expect("Empty types registry")
|
||||||
.get(&id)
|
.get(type_repr)
|
||||||
.is_some()
|
.is_some()
|
||||||
},
|
},
|
||||||
"Type {} was inserted without registration! Call RegistryBuilder::register::<{}>() or use serde_autoreg.",
|
"Type {} was inserted without registration! Call RegistryBuilder::register::<{}>() or use serde_autoreg.",
|
||||||
@ -619,8 +624,10 @@ pub mod serdeany_registry {
|
|||||||
core::any::type_name::<T>()
|
core::any::type_name::<T>()
|
||||||
);
|
);
|
||||||
self.map
|
self.map
|
||||||
.entry(id)
|
.raw_entry_mut()
|
||||||
.or_default()
|
.from_key(type_repr)
|
||||||
|
.or_insert_with(|| (type_repr_owned::<T>(), HashMap::default()))
|
||||||
|
.1
|
||||||
.entry(hash_std(name.as_bytes()))
|
.entry(hash_std(name.as_bytes()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,7 +673,11 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
self.map.contains_key(&unpack_type_id(TypeId::of::<T>()))
|
let type_repr = type_repr::<T>();
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
let type_repr = &type_repr;
|
||||||
|
|
||||||
|
self.map.contains_key(type_repr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns if the element by a given `name` is contained in this map.
|
/// Returns if the element by a given `name` is contained in this map.
|
||||||
@ -676,7 +687,11 @@ pub mod serdeany_registry {
|
|||||||
where
|
where
|
||||||
T: crate::serdeany::SerdeAny,
|
T: crate::serdeany::SerdeAny,
|
||||||
{
|
{
|
||||||
match self.map.get(&unpack_type_id(TypeId::of::<T>())) {
|
let type_repr = type_repr::<T>();
|
||||||
|
#[cfg(not(feature = "unsafe_stable_anymap"))]
|
||||||
|
let type_repr = &type_repr;
|
||||||
|
|
||||||
|
match self.map.get(type_repr) {
|
||||||
None => false,
|
None => false,
|
||||||
Some(h) => h.contains_key(&hash_std(name.as_bytes())),
|
Some(h) => h.contains_key(&hash_std(name.as_bytes())),
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user