/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include namespace apache { namespace thrift { namespace frozen { namespace detail { template struct KeyExtractor { using KeyType = K; using rvalue_reference = std::add_rvalue_reference_t< std::remove_reference_t>; using const_reference = typename Table::const_reference; // deleted functions used to avoid returning references to temporary values static const K& getKey(const std::pair&& pair) = delete; static const K& getKey(const std::pair& pair) { return pair.first; } // To support VectorAsHashMap static const K& getKey(const std::pair&& pair) = delete; static const K& getKey(const std::pair& pair) { return pair.first; } // Some maps don't contain pairs; listen to whatever they say about their // const_reference type. template shenanigans used to avoid duplicating the // previous two overloads in the cases where they're redundant. template static std::enable_if_t< !std::is_same_v&&> && !std::is_same_v&&>, const K&> getKey(rvalue_reference) = delete; template static std::enable_if_t< !std::is_same_v&> && !std::is_same_v&>, const K&> getKey(const_reference pair) { return pair.first; } static const std::pair* getPointer(rvalue_reference) = delete; static const std::pair* getPointer(const_reference pair) { // Cast to support VectorAsHashMap. return reinterpret_cast*>(&pair); } static typename Layout::View getViewKey( const typename Layout>::View& pair) { return pair.first(); } }; template struct SelfKey { using KeyType = K; static const K& getKey(const K& item) { return item; } static const K* getPointer(const K& item) { return &item; } static typename Layout::View getViewKey( typename Layout::View itemView) { return itemView; } }; template < class T, class K, class V, template class Table> struct MapTableLayout : public Table, KeyExtractor, K> { typedef Table, KeyExtractor, K> Base; typedef MapTableLayout LayoutSelf; class View : public Base::View { public: typedef typename Layout::View key_type; typedef typename Layout::View mapped_type; View() {} View(const LayoutSelf* layout, ViewPosition position) : Base::View(layout, position) {} mapped_type getDefault( const key_type& key, mapped_type def = mapped_type()) const { auto found = this->find(key); if (found == this->end()) { return std::move(def); } return found->second(); } folly::Optional getOptional(const key_type& key) const { folly::Optional rv; auto found = this->find(key); if (found != this->end()) { rv.assign(found->second()); } return rv; } mapped_type at(const key_type& key) const { auto found = this->find(key); if (found == this->end()) { throw std::out_of_range("Key not found"); } return found->second(); } }; View view(ViewPosition self) const { return View(this, self); } void print(std::ostream& os, int level) const override { Base::print(os, level); os << DebugLine(level) << "...viewed as a map"; } }; template class Table> struct SetTableLayout : public Table, V> { typedef Table, V> Base; void print(std::ostream& os, int level) const override { Base::print(os, level); os << DebugLine(level) << "...viewed as a set"; } }; } // namespace detail template struct Layout::value>::type> : public apache::thrift::frozen::detail::MapTableLayout< T, typename T::key_type, typename T::mapped_type, apache::thrift::frozen::detail::SortedTableLayout> {}; template struct Layout::value>::type> : public apache::thrift::frozen::detail::SetTableLayout< T, typename T::value_type, apache::thrift::frozen::detail::SortedTableLayout> {}; template struct Layout::value>::type> : public apache::thrift::frozen::detail::MapTableLayout< T, typename T::key_type, typename T::mapped_type, apache::thrift::frozen::detail::HashTableLayout> {}; template struct Layout::value>::type> : public apache::thrift::frozen::detail::SetTableLayout< T, typename T::value_type, apache::thrift::frozen::detail::HashTableLayout> {}; } // namespace frozen } // namespace thrift } // namespace apache THRIFT_DECLARE_TRAIT_TEMPLATE(IsHashMap, std::unordered_map) THRIFT_DECLARE_TRAIT_TEMPLATE(IsHashSet, std::unordered_set) THRIFT_DECLARE_TRAIT_TEMPLATE(IsHashMap, folly::F14NodeMap) THRIFT_DECLARE_TRAIT_TEMPLATE(IsHashMap, folly::F14ValueMap) THRIFT_DECLARE_TRAIT_TEMPLATE(IsHashMap, folly::F14VectorMap) THRIFT_DECLARE_TRAIT_TEMPLATE(IsHashMap, folly::F14FastMap) THRIFT_DECLARE_TRAIT_TEMPLATE(IsHashSet, folly::F14NodeSet) THRIFT_DECLARE_TRAIT_TEMPLATE(IsHashSet, folly::F14ValueSet) THRIFT_DECLARE_TRAIT_TEMPLATE(IsHashSet, folly::F14VectorSet) THRIFT_DECLARE_TRAIT_TEMPLATE(IsHashSet, folly::F14FastSet) THRIFT_DECLARE_TRAIT_TEMPLATE(IsOrderedMap, std::map) THRIFT_DECLARE_TRAIT_TEMPLATE(IsOrderedMap, folly::sorted_vector_map) THRIFT_DECLARE_TRAIT_TEMPLATE(IsOrderedMap, folly::heap_vector_map) THRIFT_DECLARE_TRAIT_TEMPLATE(IsOrderedMap, folly::small_heap_vector_map) THRIFT_DECLARE_TRAIT_TEMPLATE(IsOrderedSet, std::set) THRIFT_DECLARE_TRAIT_TEMPLATE(IsOrderedSet, folly::sorted_vector_set) THRIFT_DECLARE_TRAIT_TEMPLATE(IsOrderedSet, folly::heap_vector_set) THRIFT_DECLARE_TRAIT_TEMPLATE(HasSortedUniqueCtor, folly::sorted_vector_map) THRIFT_DECLARE_TRAIT_TEMPLATE(HasSortedUniqueCtor, folly::heap_vector_map) THRIFT_DECLARE_TRAIT_TEMPLATE(HasSortedUniqueCtor, folly::small_heap_vector_map) THRIFT_DECLARE_TRAIT_TEMPLATE(HasSortedUniqueCtor, folly::sorted_vector_set) THRIFT_DECLARE_TRAIT_TEMPLATE(HasSortedUniqueCtor, folly::heap_vector_set)