From 86ca6ce3e18a28402f9a0b9f285db420c31bf922 Mon Sep 17 00:00:00 2001 From: trivernis Date: Tue, 15 Mar 2022 20:37:40 +0100 Subject: [PATCH] Add FromIterator and IntoIterator implementations Signed-off-by: trivernis --- Cargo.toml | 2 +- README.md | 10 +++++++++- src/entry.rs | 19 +++++++++++++++++++ src/lib.rs | 2 ++ src/macros.rs | 30 ++++++++++++++++++++++++++++++ src/tests.rs | 13 +++++++++++-- src/trait_maps/typemap.rs | 2 +- src/typemap_trait.rs | 10 ++++++++++ 8 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 src/entry.rs diff --git a/Cargo.toml b/Cargo.toml index de29c9e..0ce5c36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "trait-bound-typemap" -version = "0.1.0" +version = "0.2.0" edition = "2021" license = "Apache-2.0" readme = "README.md" diff --git a/README.md b/README.md index 001f9fb..3896abf 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ fat pointer used by trait objects changes which it hasn't in a long time so far. ## Usage ```rust -use trait_bound_typemap::{CloneTypeMap, TypeMapTrait, TypeMapKey}; +use trait_bound_typemap::{CloneTypeMap, AnyTypeMap, TypeMapTrait, TypeMapKey}; #[derive(Clone)] pub struct MyStruct { @@ -34,6 +34,14 @@ fn main() { let value = MyStruct {a: 5, b: String::from("Hello World")}; map.insert::(value); assert!(map.contains_key::()); + + // can be cloned + let map2 = map.clone(); + assert!(map.contains_key::()); + + // less restrictive is always allowed + let any_map = AnyTypeMap::from_iter(map2); + assert!(map.contains_key::()); } ``` diff --git a/src/entry.rs b/src/entry.rs new file mode 100644 index 0000000..7bc6af8 --- /dev/null +++ b/src/entry.rs @@ -0,0 +1,19 @@ +use multi_trait_object::MultitraitObject; +use std::any::TypeId; +use std::marker::PhantomData; + +pub struct TypeMapEntry { + pub type_id: TypeId, + pub mto: MultitraitObject, + _marker: PhantomData, +} + +impl TypeMapEntry { + pub fn new(type_id: TypeId, mto: MultitraitObject) -> Self { + Self { + type_id, + mto, + _marker: PhantomData, + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 362b030..cb77d7d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![doc=include_str!("../README.md")] +mod entry; mod macros; #[cfg(test)] mod tests; @@ -7,5 +8,6 @@ mod trait_maps; mod type_indexed; mod typemap_trait; +pub use entry::*; pub use trait_maps::*; pub use typemap_trait::*; diff --git a/src/macros.rs b/src/macros.rs index 6f30469..462ca06 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -7,8 +7,13 @@ macro_rules! impl_typemap { $( #[$outer] )* #[derive(Debug)] pub struct $map($crate::type_indexed::TypeIndexedMap); + $crate::impl_typekey!($key, $( $trt )+); + impl $crate::MapKey for $key { + type Map = $map; + } + impl $crate::TypeMapTrait for $map { type Key = $key; @@ -50,6 +55,31 @@ macro_rules! impl_typemap { self.0.contains_key::() } } + + impl IntoIterator for $map { + type Item = $crate::TypeMapEntry<$key>; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0 + .0 + .into_iter() + .map(|(k, v)| $crate::TypeMapEntry::new(k, v)) + .collect::>() + .into_iter() + } + } + + impl, M: 'static $(+ $trt )+> FromIterator<$crate::TypeMapEntry> for $map { + fn from_iter>>(iter: T2) -> Self { + let map = iter + .into_iter() + .map(|e: $crate::TypeMapEntry| (e.type_id, e.mto)) + .collect::>(); + + $map($crate::type_indexed::TypeIndexedMap(map)) + } + } }; } diff --git a/src/tests.rs b/src/tests.rs index 7e9bef1..35dc60a 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,4 +1,4 @@ -use crate::{CloneTypeMap, PartialEqTypeMap, TypeMap, TypeMapKey, TypeMapTrait}; +use crate::{AnyTypeMap, CloneTypeMap, PartialEqTypeMap, TypeMapKey, TypeMapTrait}; pub struct TestStructKey; #[derive(Clone, Debug, PartialEq)] @@ -51,7 +51,7 @@ impl TypeMapKey for NotInsertedKey { #[test] fn it_creates_any_maps() { - let mut map = TypeMap::new(); + let mut map = AnyTypeMap::new(); map.insert::(NoCloneStruct); map.insert::(TestStruct::default()); map.insert::(TestStruct2::default()); @@ -79,3 +79,12 @@ fn it_creates_partial_eq_maps() { map2.insert::(TestStruct::default()); assert_eq!(map, map2) } + +#[test] +fn it_converts() { + let mut clone_map = CloneTypeMap::new(); + clone_map.insert::(TestStruct::default()); + assert!(clone_map.contains_key::()); + let any_map = AnyTypeMap::from_iter(clone_map); + assert!(any_map.contains_key::()); +} diff --git a/src/trait_maps/typemap.rs b/src/trait_maps/typemap.rs index 0044b4e..b16a2d4 100644 --- a/src/trait_maps/typemap.rs +++ b/src/trait_maps/typemap.rs @@ -3,7 +3,7 @@ use std::any::Any; impl_typemap!( /// A typemap that can store any type (implementing [std::any::Any]). - TypeMap, + AnyTypeMap, AnyTypeMapKey, Any ); diff --git a/src/typemap_trait.rs b/src/typemap_trait.rs index 56ebef5..ff2635c 100644 --- a/src/typemap_trait.rs +++ b/src/typemap_trait.rs @@ -21,6 +21,16 @@ pub trait TypedKeyMto { fn into_mto(self) -> MultitraitObject; } +/// A trait to map the key to the map it describes +#[doc(hidden)] +pub trait MapKey { + type Map: TypeMapTrait; +} + +/// A marker trait to transfer trait information +#[doc(hidden)] +pub trait TraitCarrier {} + /// A trait implemented by all typemaps that provides /// all basic typemap functions pub trait TypeMapTrait {