Add initial map implementations
Signed-off-by: trivernis <trivernis@protonmail.com>main
commit
14e369449e
@ -0,0 +1,3 @@
|
|||||||
|
/target
|
||||||
|
Cargo.lock
|
||||||
|
.idea
|
@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "trait-bound-typemap"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
readme = "README.md"
|
||||||
|
description = "A crate to create typemaps with additional trait restrictions and implementations"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
multi-trait-object = "0.2.0"
|
@ -0,0 +1,33 @@
|
|||||||
|
# Trait bound Typemap
|
||||||
|
|
||||||
|
This crate offers typemaps that restrict a given type in their
|
||||||
|
trait and therefore offer additional trait implementations such as `Clone`.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use trait_bound_typemap::{CloneTypeMap, TypeMapTrait, TypeMapKey};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct MyStruct {
|
||||||
|
a: u8,
|
||||||
|
b: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MyStructKey;
|
||||||
|
|
||||||
|
impl TypeMapKey for MyStructKey {
|
||||||
|
type Value = MyStruct;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut map = CloneTypeMap::new();
|
||||||
|
let value = MyStruct {a: 5, b: String::from("Hello World")};
|
||||||
|
map.insert::<MyStructKey>(value);
|
||||||
|
assert!(map.contains_key::<MyStructKey>());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Apache-2.0
|
@ -0,0 +1,38 @@
|
|||||||
|
use multi_trait_object::MultitraitObject;
|
||||||
|
use std::any::TypeId;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub(crate) struct TypeMapBase(pub(crate) HashMap<TypeId, MultitraitObject>);
|
||||||
|
|
||||||
|
impl TypeMapBase {
|
||||||
|
#[inline]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn insert<K: 'static>(&mut self, value: MultitraitObject) {
|
||||||
|
self.0.insert(TypeId::of::<K>(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get<K: 'static>(&self) -> Option<&MultitraitObject> {
|
||||||
|
self.0.get(&TypeId::of::<K>())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_mut<K: 'static>(&mut self) -> Option<&mut MultitraitObject> {
|
||||||
|
self.0.get_mut(&TypeId::of::<K>())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn remove<K: 'static>(&mut self) -> Option<MultitraitObject> {
|
||||||
|
self.0.remove(&TypeId::of::<K>())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn contains_key<K: 'static>(&self) -> bool {
|
||||||
|
self.0.contains_key(&TypeId::of::<K>())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
#![doc=include_str!("../README.md")]
|
||||||
|
|
||||||
|
mod base;
|
||||||
|
pub(crate) mod macros;
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
mod trait_maps;
|
||||||
|
mod typemap_trait;
|
||||||
|
|
||||||
|
pub use trait_maps::*;
|
||||||
|
pub use typemap_trait::*;
|
@ -0,0 +1,49 @@
|
|||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! impl_typemap {
|
||||||
|
($map:ident, $key:ty) => {
|
||||||
|
pub struct $map($crate::base::TypeMapBase);
|
||||||
|
|
||||||
|
impl $crate::typemap_trait::TypeMapTrait for $map {
|
||||||
|
type Key = $key;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn new() -> Self {
|
||||||
|
Self($crate::base::TypeMapBase::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn insert<T: $crate::typemap_trait::TypedKeyTrait<Self::Key>>(
|
||||||
|
&mut self,
|
||||||
|
value: T::Value,
|
||||||
|
) {
|
||||||
|
let mto = value.into_mto();
|
||||||
|
self.0.insert::<T>(mto);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get<T: $crate::typemap_trait::TypedKeyTrait<Self::Key>>(&self) -> Option<&T::Value> {
|
||||||
|
self.0.get::<T>().and_then(|v| v.downcast_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_mut<T: $crate::typemap_trait::TypedKeyTrait<Self::Key>>(
|
||||||
|
&mut self,
|
||||||
|
) -> Option<&mut T::Value> {
|
||||||
|
self.0.get_mut::<T>().and_then(|v| v.downcast_mut())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn remove<T: $crate::typemap_trait::TypedKeyTrait<Self::Key>>(
|
||||||
|
&mut self,
|
||||||
|
) -> Option<T::Value> {
|
||||||
|
self.0.remove::<T>().and_then(|v| v.downcast())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn contains_key<T: $crate::typemap_trait::TypedKeyTrait<Self::Key>>(&self) -> bool {
|
||||||
|
self.0.contains_key::<T>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
use crate::{CloneTypeMap, TypeMap, TypeMapKey, TypeMapTrait};
|
||||||
|
|
||||||
|
pub struct TestStructKey;
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct TestStruct {
|
||||||
|
a: u64,
|
||||||
|
b: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TestStruct {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
a: 46,
|
||||||
|
b: String::from("Hello World"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeMapKey for TestStructKey {
|
||||||
|
type Value = TestStruct;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TestStruct2Key;
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct TestStruct2 {
|
||||||
|
c: i64,
|
||||||
|
d: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TestStruct2 {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { c: 12, d: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeMapKey for TestStruct2Key {
|
||||||
|
type Value = TestStruct2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NoCloneStruct;
|
||||||
|
|
||||||
|
impl TypeMapKey for NoCloneStruct {
|
||||||
|
type Value = NoCloneStruct;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NotInsertedKey;
|
||||||
|
|
||||||
|
impl TypeMapKey for NotInsertedKey {
|
||||||
|
type Value = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_creates_any_maps() {
|
||||||
|
let mut map = TypeMap::new();
|
||||||
|
map.insert::<NoCloneStruct>(NoCloneStruct);
|
||||||
|
map.insert::<TestStructKey>(TestStruct::default());
|
||||||
|
map.insert::<TestStruct2Key>(TestStruct2::default());
|
||||||
|
assert!(map.contains_key::<NoCloneStruct>());
|
||||||
|
assert!(map.contains_key::<TestStructKey>());
|
||||||
|
assert!(map.contains_key::<TestStruct2Key>());
|
||||||
|
assert_eq!(map.contains_key::<NotInsertedKey>(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_creates_clonable_maps() {
|
||||||
|
let mut map = CloneTypeMap::new();
|
||||||
|
map.insert::<TestStructKey>(TestStruct::default());
|
||||||
|
map.insert::<TestStruct2Key>(TestStruct2::default());
|
||||||
|
assert!(map.contains_key::<TestStructKey>());
|
||||||
|
assert!(map.contains_key::<TestStruct2Key>());
|
||||||
|
assert_eq!(map.contains_key::<NotInsertedKey>(), false);
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
use crate::base::TypeMapBase;
|
||||||
|
use crate::{impl_typemap, TypeMapKey, TypedKeyMto, TypedKeyTrait};
|
||||||
|
use multi_trait_object::{create_object, MultitraitObject, RawClone, TryClone};
|
||||||
|
|
||||||
|
pub struct CloneTypeMapKey;
|
||||||
|
|
||||||
|
impl<T> TypedKeyTrait<CloneTypeMapKey> for T
|
||||||
|
where
|
||||||
|
T: TypeMapKey,
|
||||||
|
<T as TypeMapKey>::Value: TypedKeyMto<CloneTypeMapKey> + Clone,
|
||||||
|
{
|
||||||
|
type Value = T::Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: 'static + Clone> TypedKeyMto<CloneTypeMapKey> for T {
|
||||||
|
fn into_mto(self) -> MultitraitObject {
|
||||||
|
create_object!(self, dyn RawClone)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_typemap!(CloneTypeMap, CloneTypeMapKey);
|
||||||
|
|
||||||
|
impl Clone for CloneTypeMap {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
let map = self
|
||||||
|
.0
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.map(|(t, o)| (t.clone(), o.try_clone().unwrap()))
|
||||||
|
.collect();
|
||||||
|
CloneTypeMap(TypeMapBase(map))
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
mod clone_typemap;
|
||||||
|
mod typemap;
|
||||||
|
|
||||||
|
pub use clone_typemap::*;
|
||||||
|
pub use typemap::*;
|
@ -0,0 +1,22 @@
|
|||||||
|
use crate::{impl_typemap, TypeMapKey, TypedKeyMto, TypedKeyTrait};
|
||||||
|
use multi_trait_object::{create_object, MultitraitObject};
|
||||||
|
use std::any::Any;
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Hash)]
|
||||||
|
pub struct AnyTypeMapKey;
|
||||||
|
|
||||||
|
impl<T> TypedKeyTrait<AnyTypeMapKey> for T
|
||||||
|
where
|
||||||
|
T: TypeMapKey,
|
||||||
|
<T as TypeMapKey>::Value: Any,
|
||||||
|
{
|
||||||
|
type Value = T::Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: 'static> TypedKeyMto<AnyTypeMapKey> for T {
|
||||||
|
fn into_mto(self) -> MultitraitObject {
|
||||||
|
create_object!(self, dyn Any)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_typemap!(TypeMap, AnyTypeMapKey);
|
@ -0,0 +1,44 @@
|
|||||||
|
use multi_trait_object::MultitraitObject;
|
||||||
|
use std::any::Any;
|
||||||
|
|
||||||
|
/// A trait that allows using the object implementing it
|
||||||
|
/// to be used as a type key.
|
||||||
|
pub trait TypeMapKey: 'static {
|
||||||
|
type Value: Any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A trait used for restricting values inserted in a type map
|
||||||
|
/// using type checking
|
||||||
|
pub trait TypedKeyTrait<T>: 'static {
|
||||||
|
type Value: TypedKeyMto<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A trait used to create a multitrait-object from a given
|
||||||
|
/// value with the given guaranteed trait implementations
|
||||||
|
pub trait TypedKeyMto<T> {
|
||||||
|
fn into_mto(self) -> MultitraitObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A trait implemented by all typemaps that provides
|
||||||
|
/// all basic typemap functions
|
||||||
|
pub trait TypeMapTrait {
|
||||||
|
type Key;
|
||||||
|
|
||||||
|
/// Creates a new typemap
|
||||||
|
fn new() -> Self;
|
||||||
|
|
||||||
|
/// Inserts a value into the typemap with the given key
|
||||||
|
fn insert<T: TypedKeyTrait<Self::Key>>(&mut self, value: T::Value);
|
||||||
|
|
||||||
|
/// Returns a reference to a value from the type map with the given provided key
|
||||||
|
fn get<T: TypedKeyTrait<Self::Key>>(&self) -> Option<&T::Value>;
|
||||||
|
|
||||||
|
/// Returns a mutable reference to a value from the type map with the given provided key
|
||||||
|
fn get_mut<T: TypedKeyTrait<Self::Key>>(&mut self) -> Option<&mut T::Value>;
|
||||||
|
|
||||||
|
/// Removes a value from the map for the given key
|
||||||
|
fn remove<T: TypedKeyTrait<Self::Key>>(&mut self) -> Option<T::Value>;
|
||||||
|
|
||||||
|
/// Returns if the map contains a given key
|
||||||
|
fn contains_key<T: TypedKeyTrait<Self::Key>>(&self) -> bool;
|
||||||
|
}
|
Loading…
Reference in New Issue