1 /* Copyright 2017-2018 Fizyr B.V. - https://fizyr.com
2  *
3  * Redistribution and use in source and binary forms, with or without modification,
4  * are permitted provided that the following conditions are met:
5  *
6  * 1. Redistributions of source code must retain the above copyright notice,
7  *    this list of conditions and the following disclaimer.
8  *
9  * 2. Redistributions in binary form must reproduce the above copyright notice,
10  *    this list of conditions and the following disclaimer in the documentation
11  *    and/or other materials provided with the distribution.
12  *
13  * 3. Neither the name of the copyright holder nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software without
15  *    specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #pragma once
30 #include "../traits.hpp"
31 
32 #include <unordered_map>
33 #include <type_traits>
34 
35 namespace estd {
36 
37 /// Convert a unordered_map<K, F> to unordered_map<K, T>.
38 template<typename K, typename F, typename T, typename Tag>
39 struct conversion<std::unordered_map<K, F>, std::unordered_map<K, T>, Tag> {
40 	using From = std::unordered_map<K, F>;
41 	using To   = std::unordered_map<K, T>;
42 
43 	static constexpr bool possible = can_convert<F, T, Tag>;
44 
performestd::conversion45 	static To perform(From const & from) {
46 		static_assert(possible, "no conversion available for F and T");
47 		To result;
48 		for (std::pair<K, F> const & elem : from) result.insert(std::pair<K, T>{elem.first, convert<T, Tag>(elem.second)});
49 		return result;
50 	}
51 
performestd::conversion52 	static To perform(From && from) {
53 		static_assert(possible, "no conversion available for F and T");
54 		To result;
55 		for (std::pair<K, F> & elem : from) result.insert(std::pair<K, T>{std::move(elem.first), convert<T, Tag>(std::move(elem.second))});
56 		return result;
57 	}
58 };
59 
60 /// Convert a unordered_map<K, F> to result<unordered_map<K, T>, E>.
61 template<typename K, typename F, typename T, typename E, typename Tag>
62 struct conversion<std::unordered_map<K, F>, result<std::unordered_map<K, T>, E>, Tag> {
63 	using From = std::unordered_map<K, F>;
64 	using Raw  = std::unordered_map<K, T>;
65 	using To   = result<Raw, E>;
66 
67 	static constexpr bool possible = can_parse<F, T, Tag>;
68 
performestd::conversion69 	static To perform(From const & from) {
70 		static_assert(possible, "no conversion available for F and result<T, E>");
71 		To result;
72 		for (std::pair<K, F> const & elem : from) {
73 			estd::result<T, E> converted = parse<T, E, Tag>(elem.second);
74 			if (!converted) return converted.error_unchecked();
75 			result.insert(std::pair<K, T>{elem.first, std::move(*converted)});
76 		}
77 		return result;
78 	}
79 
performestd::conversion80 	static To perform(From && from) {
81 		static_assert(possible, "no conversion available for F and result<T, E>");
82 		To result;
83 		for (std::pair<K, F> & elem : from) {
84 			estd::result<T, E> converted = parse<T, E, Tag>(std::move(elem.second));
85 			if (!converted) return converted.error_unchecked();
86 			result.insert(std::pair<K, T>{elem.first, std::move(*converted)});
87 		}
88 		return result;
89 	}
90 };
91 
92 
93 /// Convert a unordered_multimap<K, F> to unordered_multimap<K, T>.
94 template<typename K, typename F, typename T, typename Tag>
95 struct conversion<std::unordered_multimap<K, F>, std::unordered_multimap<K, T>, Tag> {
96 	using From = std::unordered_multimap<K, F>;
97 	using To   = std::unordered_multimap<K, T>;
98 
99 	static constexpr bool possible = can_convert<F, T, Tag>;
100 
performestd::conversion101 	static To perform(From const & from) {
102 		static_assert(possible, "no conversion available for F and T");
103 		To result;
104 		for (std::pair<K, F> const & elem : from) result.insert(std::pair<K, T>{elem.first, convert<T, Tag>(elem.second)});
105 		return result;
106 	}
107 
performestd::conversion108 	static To perform(From && from) {
109 		static_assert(possible, "no conversion available for F and T");
110 		To result;
111 		for (std::pair<K, F> & elem : from) result.insert(std::pair<K, T>{std::move(elem.first), convert<T, Tag>(std::move(elem.second))});
112 		return result;
113 	}
114 };
115 
116 /// Convert a unordered_multimap<K, F> to result<unordered_multimap<K, T>, E>.
117 template<typename K, typename F, typename T, typename E, typename Tag>
118 struct conversion<std::unordered_multimap<K, F>, result<std::unordered_multimap<K, T>, E>, Tag> {
119 	using From = std::unordered_multimap<K, F>;
120 	using Raw  = std::unordered_multimap<K, T>;
121 	using To   = result<Raw, E>;
122 
123 	static constexpr bool possible = can_parse<F, T, Tag>;
124 
performestd::conversion125 	static To perform(From const & from) {
126 		static_assert(possible, "no conversion available for F and result<T, E>");
127 		To result;
128 		for (std::pair<K, F> const & elem : from) {
129 			estd::result<T, E> converted = parse<T, E, Tag>(elem.second);
130 			if (!converted) return converted.error_unchecked();
131 			result.insert(std::pair<K, T>{elem.first, std::move(*converted)});
132 		}
133 		return result;
134 	}
135 
performestd::conversion136 	static To perform(From && from) {
137 		static_assert(possible, "no conversion available for F and result<T, E>");
138 		To result;
139 		for (std::pair<K, F> & elem : from) {
140 			estd::result<T, E> converted = parse<T, E, Tag>(std::move(elem.second));
141 			if (!converted) return converted.error_unchecked();
142 			result.insert(std::pair<K, T>{elem.first, std::move(*converted)});
143 		}
144 		return result;
145 	}
146 };
147 
148 }
149