1use std::any::Any;
3
4use dyn_clone::DynClone;
5
6use crate::bounds::{Bounds, ContainerWithHash};
7use crate::{impl_custom_bounds_with_key_container, TypedMap};
8
9pub trait CloneAny: DynClone + Any {
11 fn as_any(&self) -> &dyn Any;
12 fn as_mut_any(&mut self) -> &mut dyn Any;
13 fn as_any_box(self: Box<Self>) -> Box<dyn Any>;
14}
15
16dyn_clone::clone_trait_object!(CloneAny);
17
18impl<T: Clone + Any> CloneAny for T {
19 fn as_any(&self) -> &dyn Any {
20 self
21 }
22
23 fn as_mut_any(&mut self) -> &mut dyn Any {
24 self
25 }
26
27 fn as_any_box(self: Box<Self>) -> Box<dyn Any> {
28 self
29 }
30}
31
32pub fn clone_box<T: ?Sized + CloneAny>(t: &T) -> Box<T> {
34 dyn_clone::clone_box(t)
35}
36
37pub struct CloneBounds;
74
75pub trait ContainerWithHashAndClone<B: Bounds>: ContainerWithHash<B> + CloneAny {}
76
77impl<B: Bounds, K: ContainerWithHash<B> + CloneAny + 'static> ContainerWithHashAndClone<B> for K {}
78
79pub struct SyncCloneBounds;
81impl_custom_bounds_with_key_container!(
82 CloneBounds,
83 CloneAny,
84 dyn ContainerWithHashAndClone<CloneBounds>,
85 CloneAny
86);
87impl_custom_bounds_with_key_container!(
88 SyncCloneBounds,
89 CloneAny,
90 dyn ContainerWithHashAndClone<SyncCloneBounds> + Send + Sync,
91 CloneAny, + Send + Sync
92);
93
94impl<M, KB: 'static + Bounds, VB: 'static + Bounds> Clone for TypedMap<M, KB, VB>
95where
96 KB::KeyContainer: CloneAny,
97 VB::Container: CloneAny,
98{
99 fn clone(&self) -> Self {
100 self.iter().map(|pair| pair.to_owned()).collect()
101 }
102}
103
104#[cfg(feature = "dashmap")]
105impl<M, KB: 'static + Bounds, VB: 'static + Bounds> Clone for crate::TypedDashMap<M, KB, VB>
106where
107 KB::KeyContainer: CloneAny,
108 VB::Container: CloneAny,
109{
110 fn clone(&self) -> Self {
111 self.iter().map(|pair| pair.to_owned()).collect()
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use crate::clone::{CloneBounds, SyncCloneBounds};
118
119 use crate::TypedMap;
120 use crate::TypedMapKey;
121
122 struct Marker;
123
124 impl TypedMapKey<Marker> for String {
125 type Value = String;
126 }
127
128 #[test]
129 fn test_clone_typed_map() {
130 let mut map: TypedMap<Marker, CloneBounds, SyncCloneBounds> = TypedMap::new_with_bounds();
131 map.insert("String".to_owned(), "Value".to_owned());
132
133 let map2 = map.clone();
134 assert_eq!(map2.get(&"String".to_owned()), Some(&"Value".to_owned()))
135 }
136
137 #[cfg(feature = "dashmap")]
138 #[test]
139 fn test_clone() {
140 use crate::clone::SyncCloneBounds;
141 use crate::TypedDashMap;
142 let state: TypedDashMap<Marker, SyncCloneBounds, SyncCloneBounds> =
143 TypedDashMap::new_with_bounds();
144 state.insert("Key".to_owned(), "Value".to_owned());
145
146 let cloned = state.clone();
147 assert_eq!(
148 state.get(&"Key".to_owned()).unwrap().value(),
149 cloned.get(&"Key".to_owned()).unwrap().value()
150 );
151 }
152}