Fix AnyMap for TypeIds with 128 bit (#1311)

* Fix AnyMap for TypeIds with 128 bit

* make const

* added test, removed static_assertions
This commit is contained in:
Dominik Maier 2023-06-09 14:06:42 +02:00 committed by GitHub
parent fa63493cee
commit 62b1bde7a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 15 deletions

View File

@ -67,7 +67,6 @@ serde = { version = "1.0", default-features = false, features = ["alloc", "deriv
erased-serde = { version = "0.3.21", default-features = false, features = ["alloc"] } # erased serde erased-serde = { version = "0.3.21", default-features = false, features = ["alloc"] } # erased serde
postcard = { version = "1.0", features = ["alloc"] } # no_std compatible serde serialization fromat postcard = { version = "1.0", features = ["alloc"] } # no_std compatible serde serialization fromat
bincode = {version = "1.3", optional = true } bincode = {version = "1.3", optional = true }
static_assertions = "1.1.0"
c2rust-bitfields = { version = "0.17", features = ["no_std"] } c2rust-bitfields = { version = "0.17", features = ["no_std"] }
num_enum = { version = "0.5.7", default-features = false } num_enum = { version = "0.5.7", default-features = false }
typed-builder = "0.14" # Implement the builder pattern at compiletime typed-builder = "0.14" # Implement the builder pattern at compiletime

View File

@ -3,6 +3,7 @@
use alloc::boxed::Box; use alloc::boxed::Box;
use core::{ use core::{
any::{Any, TypeId}, any::{Any, TypeId},
mem::size_of,
ptr::addr_of, ptr::addr_of,
}; };
@ -43,10 +44,21 @@ macro_rules! impl_asany {
/// ///
/// # Note /// # Note
/// Probably not safe for future compilers, fine for now. /// Probably not safe for future compilers, fine for now.
/// The size changed in later rust versions, see <https://github.com/rust-lang/compiler-team/issues/608>
#[inline]
#[must_use] #[must_use]
pub fn pack_type_id(id: u64) -> TypeId { pub const fn pack_type_id(id: u128) -> TypeId {
assert_eq_size!(TypeId, u64); match size_of::<TypeId>() {
unsafe { *(addr_of!(id) as *const TypeId) } 8 => {
let id_64 = id as u64;
unsafe { *(addr_of!(id_64) as *const TypeId) }
}
16 => unsafe { *(addr_of!(id) as *const TypeId) },
_ => {
// TypeId size of this size is not yet supported"
panic!("Unsupported size for TypeId");
}
}
} }
/// Unpack a `type_id` to an `u64` /// Unpack a `type_id` to an `u64`
@ -54,10 +66,19 @@ pub fn pack_type_id(id: u64) -> TypeId {
/// ///
/// # Note /// # Note
/// Probably not safe for future compilers, fine for now. /// Probably not safe for future compilers, fine for now.
/// The size changed in later rust versions, see <https://github.com/rust-lang/compiler-team/issues/608>
#[inline]
#[must_use] #[must_use]
pub fn unpack_type_id(id: TypeId) -> u64 { pub const fn unpack_type_id(id: TypeId) -> u128 {
assert_eq_size!(TypeId, u64); #[allow(clippy::cast_ptr_alignment)] // we never actually cast to u128 if the type is u64.
unsafe { *(addr_of!(id) as *const u64) } match size_of::<TypeId>() {
8 => unsafe { *(addr_of!(id) as *const u64) as u128 },
16 => unsafe { *(addr_of!(id) as *const u128) },
_ => {
// TypeId size of this size is not yet supported"
panic!("Unsupported size for TypeId");
}
}
} }
/// Create `AnyMap` and `NamedAnyMap` for a given trait /// Create `AnyMap` and `NamedAnyMap` for a given trait
@ -432,3 +453,22 @@ macro_rules! create_anymap_for_trait {
} }
} }
} }
#[cfg(test)]
mod test {
use core::any::TypeId;
use super::{pack_type_id, unpack_type_id};
#[test]
fn test_type_id() {
let type_id_u64 = unpack_type_id(TypeId::of::<u64>());
let type_id_u128 = unpack_type_id(TypeId::of::<u128>());
assert_eq!(pack_type_id(type_id_u64), TypeId::of::<u64>());
assert_eq!(pack_type_id(type_id_u128), TypeId::of::<u128>());
assert_ne!(pack_type_id(type_id_u64), TypeId::of::<u128>());
assert_ne!(pack_type_id(type_id_u128), TypeId::of::<u64>());
}
}

View File

@ -100,7 +100,7 @@ macro_rules! create_serde_registry_for_trait {
where where
V: serde::de::SeqAccess<'de>, V: serde::de::SeqAccess<'de>,
{ {
let id: u64 = visitor.next_element()?.unwrap(); let id: u128 = visitor.next_element()?.unwrap();
let cb = unsafe { let cb = unsafe {
*REGISTRY *REGISTRY
.deserializers .deserializers
@ -117,7 +117,7 @@ macro_rules! create_serde_registry_for_trait {
#[allow(unused_qualifications)] #[allow(unused_qualifications)]
struct Registry { struct Registry {
deserializers: Option<HashMap<u64, DeserializeCallback<dyn $trait_name>>>, deserializers: Option<HashMap<u128, DeserializeCallback<dyn $trait_name>>>,
finalized: bool, finalized: bool,
} }
@ -174,7 +174,7 @@ macro_rules! create_serde_registry_for_trait {
/// in the registry /// in the registry
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct SerdeAnyMap { pub struct SerdeAnyMap {
map: HashMap<u64, Box<dyn $trait_name>>, map: HashMap<u128, Box<dyn $trait_name>>,
} }
// 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.
@ -301,7 +301,7 @@ macro_rules! create_serde_registry_for_trait {
#[allow(unused_qualifications)] #[allow(unused_qualifications)]
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct NamedSerdeAnyMap { pub struct NamedSerdeAnyMap {
map: HashMap<u64, HashMap<u64, Box<dyn $trait_name>>>, map: HashMap<u128, HashMap<u64, Box<dyn $trait_name>>>,
} }
// 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.
@ -467,8 +467,8 @@ macro_rules! create_serde_registry_for_trait {
pub fn all_typeids( pub fn all_typeids(
&self, &self,
) -> core::iter::Map< ) -> core::iter::Map<
Keys<'_, u64, HashMap<u64, Box<dyn $trait_name>>>, Keys<'_, u128, HashMap<u64, Box<dyn $trait_name>>>,
fn(&u64) -> TypeId, fn(&u128) -> TypeId,
> { > {
self.map.keys().map(|x| pack_type_id(*x)) self.map.keys().map(|x| pack_type_id(*x))
} }

View File

@ -79,8 +79,6 @@ extern crate std;
#[macro_use] #[macro_use]
#[doc(hidden)] #[doc(hidden)]
pub extern crate alloc; pub extern crate alloc;
#[macro_use]
extern crate static_assertions;
#[cfg(feature = "ctor")] #[cfg(feature = "ctor")]
#[doc(hidden)] #[doc(hidden)]
pub use ctor::ctor; pub use ctor::ctor;