Skip to content

Commit ab882b9

Browse files
mbasmanovafacebook-github-bot
authored andcommitted
feat: Introduce a pattern for handling mapping between enum values and names (facebookincubator#13988)
Summary: X-link: facebookincubator/axiom#24 Pull Request resolved: facebookincubator#13988 In the header file, declare the enum class and a XxxName struct: ``` enum class Foo {...}; struct FooName { static std::string_view toName(Foo foo); static Foo toFoo(std::string_view name); }; ``` In the .cpp file, implement XxxName's methods: ``` #include "velox/common/Enums.h" namespace { folly::F14FastMap<Foo, std::string> fooNames() { return { {Foo::kFirst, "FIRST"}, {Foo::kSecond, "SECOND"}, ... }; } } // namespace // static std::string_view FooName::toName(Foo foo) { static const auto kNames = fooNames(); auto it = kNames.find(foo); VELOX_CHECK( it != kNames.end(), "Invalid enum value: {}", static_cast<int>(foo)); return it->second.c_str(); } // static Foo FooName::toFoo(std::string_view name) { static const auto kEnums = Enums::invertMap(fooNames()); auto it = kEnums.find(name); VELOX_CHECK(it != kEnums.end(), "Invalid enum name: {}", name); return it->second; } ``` To reduce boiler plate code required to implement this pattern, introduce helper macros. .h ``` #include "velox/common/Enums.h" enum class Foo {...}; VELOX_DEFINE_ENUM_NAME(Foo); ``` .cpp ``` namespace { folly::F14FastMap<Foo, std::string> fooNames() { return { {Foo::kFirst, "FIRST"}, {Foo::kSecond, "SECOND"}, ... }; } } // namespace VELOX_DECLARE_ENUM_NAME(Foo, fooNames); ``` Migrate all enums in PlanNode.h to the new pattern. Reviewed By: oerling Differential Revision: D77654609 fbshipit-source-id: 6dbd779a17f5da788532734dd2fc6a9cc3e8883d
1 parent 8a18387 commit ab882b9

18 files changed

+244
-234
lines changed

velox/common/Enums.h

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#pragma once
17+
18+
#include "folly/container/F14Map.h"
19+
#include "velox/common/base/Exceptions.h"
20+
21+
namespace facebook::velox {
22+
23+
struct Enums {
24+
/// Helper function to invert a mapping from enum type to name.
25+
template <typename E>
26+
static folly::F14FastMap<std::string, E> invertMap(
27+
const folly::F14FastMap<E, std::string>& mapping) {
28+
folly::F14FastMap<std::string, E> inverted;
29+
for (const auto& [key, value] : mapping) {
30+
bool ok = inverted.emplace(value, key).second;
31+
VELOX_USER_CHECK(
32+
ok, "Cannot invert a map with duplicate values: {}", value);
33+
}
34+
return inverted;
35+
}
36+
};
37+
38+
} // namespace facebook::velox
39+
40+
/// Helper macros to implement bi-direction mappings between enum values and
41+
/// names.
42+
///
43+
/// Usage:
44+
///
45+
/// In the header file, define the enum:
46+
///
47+
/// #include "velox/common/Enums.h"
48+
///
49+
/// enum class Foo {...};
50+
///
51+
/// VELOX_DEFINE_ENUM_NAME(Foo);
52+
///
53+
/// In the cpp file, define the mapping:
54+
///
55+
/// namespace {
56+
/// folly::F14FastMap<Foo, std::string> fooNames() {
57+
/// return {
58+
/// {Foo::kFirst, "FIRST"},
59+
/// {Foo::kSecond, "SECOND"},
60+
/// ...
61+
/// };
62+
/// }
63+
/// } // namespace
64+
///
65+
/// VELOX_DECLARE_ENUM_NAME(Foo, fooNames);
66+
///
67+
/// In the client code, use FooName::toName(Foo::kFirst) to get the name of the
68+
/// enum and FooName::toFoo("FIRST") to get the enum value.
69+
///
70+
/// Use _EMBEDDED_ versions of the macros to define enums embedded in other
71+
/// classes.
72+
73+
#define VELOX_DECLARE_ENUM_NAME(EnumType) \
74+
struct EnumType##Name { \
75+
static std::string_view toName(EnumType value); \
76+
static EnumType to##EnumType(std::string_view name); \
77+
};
78+
79+
#define VELOX_DEFINE_ENUM_NAME(EnumType, Names) \
80+
std::string_view EnumType##Name::toName(EnumType value) { \
81+
static const auto kNames = Names(); \
82+
auto it = kNames.find(value); \
83+
VELOX_CHECK( \
84+
it != kNames.end(), \
85+
"Invalid enum value: {}", \
86+
static_cast<int>(value)); \
87+
return it->second.c_str(); \
88+
} \
89+
\
90+
EnumType EnumType##Name::to##EnumType(std::string_view name) { \
91+
static const auto kValues = facebook::velox::Enums::invertMap(Names()); \
92+
\
93+
auto it = kValues.find(name); \
94+
VELOX_CHECK(it != kValues.end(), "Invalid enum name: {}", name); \
95+
return it->second; \
96+
}
97+
98+
#define VELOX_DECLARE_EMBEDDED_ENUM_NAME(EnumType) \
99+
static std::string_view toName(EnumType value); \
100+
static EnumType to##EnumType(std::string_view name);
101+
102+
#define VELOX_DEFINE_EMBEDDED_ENUM_NAME(Class, EnumType, Names) \
103+
std::string_view Class::toName(Class::EnumType value) { \
104+
static const auto kNames = Names(); \
105+
auto it = kNames.find(value); \
106+
VELOX_CHECK( \
107+
it != kNames.end(), \
108+
"Invalid enum value: {}", \
109+
static_cast<int>(value)); \
110+
return it->second.c_str(); \
111+
} \
112+
\
113+
Class::EnumType Class::to##EnumType(std::string_view name) { \
114+
static const auto kValues = facebook::velox::Enums::invertMap(Names()); \
115+
\
116+
auto it = kValues.find(name); \
117+
VELOX_CHECK(it != kValues.end(), "Invalid enum name: {}", name); \
118+
return it->second; \
119+
}

0 commit comments

Comments
 (0)