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