Add initial map implementations

Signed-off-by: trivernis <trivernis@protonmail.com>
main
trivernis 3 years ago
commit 14e369449e
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

3
.gitignore vendored

@ -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…
Cancel
Save