Expand description
Restricting types that may be stored in the hashmap.
Struct that implement Bounds
trait may be used as a restriction on types for keys or values
stored in the hashmap. Imagine that you’d like to store only values that implement some trait, e.g.
service. One can implement new bounds using convenience macros impl_custom_bounds and impl_dyn_trait_wrapper:
use std::any::Any;
use std::hash::Hash;
use typedmap::bounds::{Bounds, ContainerWithHash, HasBounds};
use typedmap::{AnyBounds, impl_custom_bounds, impl_dyn_trait_wrapper, TypedMap, TypedMapKey};
// Your trait that map values must implement
trait Service {
fn is_ready(&self) -> bool;
}
// You need a struct to represent bounds requirement
struct ServiceBounds;
// Implement a trait object type DynService to be stored in map and represent Service trait
impl_dyn_trait_wrapper!(DynService, Service);
// Implement Bounds trait & HasBounds<T> for ServiceBounds
impl_custom_bounds!(ServiceBounds, DynService, Service);
#[derive(Eq, PartialEq, Hash)]
struct Key;
impl TypedMapKey for Key {
type Value = ServiceA;
}
struct ServiceA;
impl Service for ServiceA {
fn is_ready(&self) -> bool {
true
}
}
// Use it
let mut map: TypedMap<(), AnyBounds, ServiceBounds, _> = TypedMap::new_with_bounds();
map.insert(Key, ServiceA);
for kv in map.iter() {
// use function from Service trait;
let _ = kv.value_container_ref().as_object().is_ready();
}
Manually one can do it in the following way:
use std::any::Any;
use std::hash::Hash;
use typedmap::bounds::{Bounds, ContainerWithHash, HasBounds};
use typedmap::{AnyBounds, impl_custom_bounds, impl_dyn_trait_wrapper, TypedMap, TypedMapKey};
// Your trait that map values must implement
trait Service {
fn is_ready(&self) -> bool;
}
// You need a struct to represent bounds requirement
struct ServiceBounds;
impl Bounds for ServiceBounds {
// Specify trait object type for keys (use dyn ContainerWithHash<Self> + Marker traits
type KeyContainer = dyn ContainerWithHash<ServiceBounds>;
// Specify trait object type for values (must be castable to Any and to Service trait)
type Container = dyn DynService;
// Implement basic conversion functions
fn as_any(this: &Self::Container) -> &dyn Any {
this.as_any()
}
fn as_any_mut(this: &mut Self::Container) -> &mut dyn Any {
this.as_mut_any()
}
fn as_any_box(this: Box<Self::Container>) -> Box<dyn Any> {
this.as_box_any()
}
}
// Implement HasBounds trait with simple conversion functions
impl<T: DynService> HasBounds<T> for ServiceBounds {
fn cast_box(this: Box<T>) -> Box<Self::Container> {
this
}
fn as_ref(this: &T) -> &Self::Container {
this
}
fn as_mut(this: &mut T) -> &mut Self::Container {
this
}
fn cast_key_box(this: Box<T>) -> Box<Self::KeyContainer> where T: 'static + Sized + Hash + Eq {
this
}
}
trait DynService: Any + Service {
fn as_object(&self) -> &dyn Service;
fn as_any(&self) -> &dyn Any;
fn as_mut_any(&mut self) -> &mut dyn Any;
fn as_box_any(self: Box<Self>) -> Box<dyn Any>;
}
impl<T: Service + Any> DynService for T {
fn as_object(&self) -> &dyn Service {
self
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_mut_any(&mut self) -> &mut dyn Any {
self
}
fn as_box_any(self: Box<Self>) -> Box<dyn Any> {
self
}
}
#[derive(Eq, PartialEq, Hash)]
struct Key;
impl TypedMapKey for Key {
type Value = ServiceA;
}
struct ServiceA;
impl Service for ServiceA {
fn is_ready(&self) -> bool {
true
}
}
// Use it
let mut map: TypedMap<(), AnyBounds, ServiceBounds, _> = TypedMap::new_with_bounds();
map.insert(Key, ServiceA);
for kv in map.iter() {
// use function from Service trait;
let _ = kv.value_container_ref().as_object().is_ready();
}
Structs§
- Default bounds for TypedMap that require keys/values just to implement
Any
. - Default bounds for TypedDashMap that require keys/values just to implement
Any + Send + Sync
.
Traits§
- Represents bounds for key or values. This allows to enforce TypedMap to store for example only cloneable values or ones that are Send+Sync.
- Trait used as container for keys, i.e. instances of types that meet bounds
B
and implement Hash & Eq Usedyn ContainerWithHash<Self> + Marker traits
as KeyContainer inBounds
trait. - Trait that marks that specific type fulfill specified bounds. For example
HasBounds<CloneBounds>
is implemented for all types that are implement Clone & Any.