diff options
| author | Martin Fischer <martin@push-f.com> | 2021-11-22 08:55:14 +0100 | 
|---|---|---|
| committer | Martin Fischer <martin@push-f.com> | 2021-11-22 09:21:02 +0100 | 
| commit | ef698909223b2f29f7a6cae17f0aba3461c8803d (patch) | |
| tree | 5f91a28cf98b6742c899bf515e99fcb8f89261ff | |
| parent | 19823e09b7fe5e6a5b3965c7096c9daba18ce028 (diff) | |
support HashMap and BTreeMap
| -rw-r--r-- | README.md | 6 | ||||
| -rw-r--r-- | src/lib.rs | 5 | ||||
| -rw-r--r-- | src/parse_trait_sig.rs | 1 | ||||
| -rw-r--r-- | src/transform.rs | 26 | ||||
| -rw-r--r-- | tests/tests.rs | 6 | 
5 files changed, 33 insertions, 11 deletions
| @@ -91,9 +91,9 @@ Dynamize also understands if you wrap associated types in the following types:  * `Result<_, _>`  * `some::module::Result<_>` (type alias with fixed error type)  * `&mut dyn Iterator<Item = _>` -* `Vec<_>`, `VecDeque<_>`,`LinkedList<_>` -* `HashSet<_>`, `BinaryHeap<_>`, `BTreeSet<_>`   -  (these only work with `Into`-bounded associated types because they require `Eq`) +* `Vec<_>`, `VecDeque<_>`, `LinkedList<_>`, `HashSet<K>`, `BinaryHeap<K>`, +  `BTreeSet<K>`, `HashMap<K, _>`, `BTreeMap<K, _>`   +  (for `K` only `Into`-bounded associated types work because they require `Eq`)  Note that since these are resolved recursively you can actually nest these  arbitrarily so e.g. the following also just works: @@ -413,6 +413,11 @@ impl TypeTransform {                  let inner = inner.convert(quote!(x));                  quote! {#arg.into_iter().map(|x| #inner).collect()}              } +            TypeTransform::CollectionMap(key, value) => { +                let key = key.convert(quote!(k)); +                let value = value.convert(quote!(v)); +                quote! {#arg.into_iter().map(|(k,v)| (#key, #value)).collect()} +            }              TypeTransform::NoOp => arg,          }      } diff --git a/src/parse_trait_sig.rs b/src/parse_trait_sig.rs index c924a71..4c0b4fd 100644 --- a/src/parse_trait_sig.rs +++ b/src/parse_trait_sig.rs @@ -18,6 +18,7 @@ pub enum TypeTransform {      Box(BoxType),      Map(Box<TypeTransform>),      Collection(Box<TypeTransform>), +    CollectionMap(Box<TypeTransform>, Box<TypeTransform>),      Iterator(BoxType, Box<TypeTransform>),      Result(Box<TypeTransform>, Box<TypeTransform>),  } diff --git a/src/transform.rs b/src/transform.rs index 4dc88f0..4625f4c 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -33,6 +33,12 @@ fn is_supported_collection(ident: &Ident) -> bool {          || ident == "BTreeSet"  } +fn is_supported_collection_map(ident: &Ident) -> bool { +    // collections added here must implement IntoIterator & FromIterator +    // when adding a type here don't forget to document it in the README +    ident == "HashMap" || ident == "BTreeMap" +} +  impl AssocTypeConversions<'_> {      pub fn parse_type_path(&self, type_: &mut Type) -> Result<TypeTransform, TransformError> {          if !iter_type(type_).any(match_assoc_type) { @@ -123,14 +129,20 @@ impl AssocTypeConversions<'_> {                          if let (GenericArgument::Type(arg1), GenericArgument::Type(arg2)) =                              (args_iter.next().unwrap(), args_iter.next().unwrap())                          { -                            if (iter_type(arg1).any(match_assoc_type) -                                || iter_type(arg2).any(match_assoc_type)) -                                && last_seg.ident == "Result" +                            if iter_type(arg1).any(match_assoc_type) +                                || iter_type(arg2).any(match_assoc_type)                              { -                                return Ok(TypeTransform::Result( -                                    self.parse_type_path(arg1)?.into(), -                                    self.parse_type_path(arg2)?.into(), -                                )); +                                if last_seg.ident == "Result" { +                                    return Ok(TypeTransform::Result( +                                        self.parse_type_path(arg1)?.into(), +                                        self.parse_type_path(arg2)?.into(), +                                    )); +                                } else if is_supported_collection_map(&last_seg.ident) { +                                    return Ok(TypeTransform::CollectionMap( +                                        self.parse_type_path(arg1)?.into(), +                                        self.parse_type_path(arg2)?.into(), +                                    )); +                                }                              }                          }                      } diff --git a/tests/tests.rs b/tests/tests.rs index e004d61..925fe72 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -204,7 +204,7 @@ fn test3<T: TypeWithSuper>(some: T) {      println!("{}", dyn_trait);  } -use std::collections::{BTreeSet, BinaryHeap, HashSet, LinkedList, VecDeque}; +use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};  #[dynamize::dynamize]  trait Collections { @@ -228,6 +228,10 @@ trait CollectionsRequiringEq {      fn binary_heap(&self) -> BinaryHeap<Self::A>;      fn btree_set(&self) -> BTreeSet<Self::A>; + +    fn hash_map(&self) -> HashMap<Self::A, Self::A>; + +    fn btree_map(&self) -> BTreeMap<Self::A, Self::A>;  }  #[dynamize::dynamize] | 
