diff --git a/rust-runtime/aws-smithy-http/src/property_bag.rs b/rust-runtime/aws-smithy-http/src/property_bag.rs index 00d32961a46..50e2bb12490 100644 --- a/rust-runtime/aws-smithy-http/src/property_bag.rs +++ b/rust-runtime/aws-smithy-http/src/property_bag.rs @@ -18,8 +18,33 @@ use std::hash::{BuildHasherDefault, Hasher}; use std::ops::{Deref, DerefMut}; use std::sync::{Arc, Mutex}; -type AnyMap = - HashMap), BuildHasherDefault>; +type AnyMap = HashMap>; + +struct NamedType { + name: &'static str, + value: Box, +} + +impl NamedType { + fn as_mut(&mut self) -> Option<&mut T> { + self.value.downcast_mut() + } + + fn as_ref(&self) -> Option<&T> { + self.value.downcast_ref() + } + + fn assume(self) -> Option { + self.value.downcast().map(|t| *t).ok() + } + + fn new(value: T) -> Self { + Self { + name: std::any::type_name::(), + value: Box::new(value), + } + } +} // With TypeIds as keys, there's no need to hash them. They are already hashes // themselves, coming from the compiler. The IdHasher just holds the u64 of @@ -83,16 +108,8 @@ impl PropertyBag { /// ``` pub fn insert(&mut self, val: T) -> Option { self.map - .insert( - TypeId::of::(), - (std::any::type_name::(), Box::new(val)), - ) - .and_then(|(_, boxed)| { - (boxed as Box) - .downcast() - .ok() - .map(|boxed| *boxed) - }) + .insert(TypeId::of::(), NamedType::new(val)) + .and_then(|val| val.assume()) } /// Get a reference to a type previously inserted on this `PropertyBag`. @@ -110,12 +127,16 @@ impl PropertyBag { pub fn get(&self) -> Option<&T> { self.map .get(&TypeId::of::()) - .and_then(|(_, boxed)| (&**boxed as &(dyn Any + 'static)).downcast_ref()) + .and_then(|val| val.as_ref()) } /// Returns an iterator of the types contained in this PropertyBag + /// + /// # Stability + /// This method is unstable and may be removed or changed in a future release. The exact + /// format of the returned types may also change. pub fn contents(&self) -> impl Iterator + '_ { - self.map.values().map(|(name, _)| *name) + self.map.values().map(|tpe| tpe.name) } /// Get a mutable reference to a type previously inserted on this `PropertyBag`. @@ -133,7 +154,7 @@ impl PropertyBag { pub fn get_mut(&mut self) -> Option<&mut T> { self.map .get_mut(&TypeId::of::()) - .and_then(|(_, boxed)| (&mut **boxed as &mut (dyn Any + 'static)).downcast_mut()) + .map(|val| val.as_mut().expect("type mismatch!")) } /// Remove a type from this `PropertyBag`. @@ -150,8 +171,8 @@ impl PropertyBag { /// assert!(props.get::().is_none()); /// ``` pub fn remove(&mut self) -> Option { - self.map.remove(&TypeId::of::()).and_then(|(_, boxed)| { - (boxed as Box) + self.map.remove(&TypeId::of::()).and_then(|tpe| { + (tpe.value as Box) .downcast() .ok() .map(|boxed| *boxed)