config: allow unordered_set in config

Summary: A future diff will create a ConfigSetting<std::unordered_set<T>>.

Reviewed By: kmancini

Differential Revision: D45162159

fbshipit-source-id: a67b3b94d708ae694041753d7dffaa6f0ff974de
This commit is contained in:
Xavier Deguillard 2023-04-21 08:27:20 -07:00 committed by Facebook GitHub Bot
parent 2c8e74370b
commit f23137cda1
3 changed files with 86 additions and 3 deletions

View File

@ -32,11 +32,10 @@ bool isValidAbsolutePath(string_view path) {
// reject relative paths.
return path.starts_with(detail::kRootStr);
}
} // namespace
Expected<AbsolutePath, string> FieldConverter<AbsolutePath>::fromString(
std::string expandConvData(
std::string_view value,
const std::map<string, string>& convData) const {
const std::map<std::string, std::string>& convData) {
auto sString = std::string{value};
for (auto varName : kEnvVars) {
auto it = convData.find(std::string{varName});
@ -53,6 +52,14 @@ Expected<AbsolutePath, string> FieldConverter<AbsolutePath>::fromString(
}
}
}
return sString;
}
} // namespace
Expected<AbsolutePath, string> FieldConverter<AbsolutePath>::fromString(
std::string_view value,
const std::map<string, string>& convData) const {
auto sString = expandConvData(value, convData);
if (!isValidAbsolutePath(sString)) {
return folly::makeUnexpected<string>(
@ -70,6 +77,20 @@ Expected<AbsolutePath, string> FieldConverter<AbsolutePath>::fromString(
}
}
Expected<RelativePath, string> FieldConverter<RelativePath>::fromString(
std::string_view value,
const std::map<string, string>& convData) const {
auto sString = expandConvData(value, convData);
try {
return RelativePath{sString};
} catch (const std::exception& ex) {
return folly::makeUnexpected<string>(fmt::format(
"Failed to convert value '{}' to a relative path, error : {}",
value,
ex.what()));
}
}
Expected<string, string> FieldConverter<string>::fromString(
std::string_view value,
const std::map<string, string>& /* unused */) const {

View File

@ -51,6 +51,24 @@ class FieldConverter<AbsolutePath> {
}
};
template <>
class FieldConverter<RelativePath> {
public:
/**
* Convert the passed string piece to a repository RelativePath.
* @param convData is a map of conversion data that can be used by conversions
* method (for example $HOME value.)
* @return the converted RelativePath or an error message.
*/
folly::Expected<RelativePath, std::string> fromString(
std::string_view value,
const std::map<std::string, std::string>& convData) const;
std::string toDebugString(const RelativePath& path) const {
return path.value();
}
};
template <>
class FieldConverter<std::string> {
public:
@ -135,6 +153,36 @@ class FieldConverter<std::vector<T>> {
}
};
template <typename T>
class FieldConverter<std::unordered_set<T>> {
public:
folly::Expected<std::unordered_set<T>, std::string> fromString(
std::string_view value,
const std::map<std::string, std::string>& convData) const {
// TODO(xavierd): directly construct the set without the vector middle-step
return FieldConverter<std::vector<T>>{}
.fromString(value, convData)
.then([](std::vector<T> vec) {
return std::unordered_set<T>{
std::make_move_iterator(vec.begin()),
std::make_move_iterator(vec.end())};
});
}
std::string toDebugString(const std::unordered_set<T>& value) const {
std::vector<std::string> serializedElements;
serializedElements.resize(value.size());
std::transform(
value.begin(),
value.end(),
serializedElements.begin(),
[](auto& element) {
return FieldConverter<T>{}.toDebugString(element);
});
return fmt::to_string(fmt::join(serializedElements, ", "));
}
};
/*
* FieldConverter implementation for integers, floating point, and bool types
*/

View File

@ -432,3 +432,17 @@ TEST_F(ConfigSettingTest, setArrayOptional) {
checkSet(
setting, std::vector<std::optional<std::string>>{"foo"}, "[\"foo\"]");
}
TEST_F(ConfigSettingTest, setRelativePath) {
ConfigSetting<RelativePath> setting{"test:value", RelativePath{}, nullptr};
checkSet(setting, RelativePath{"foo/bar"}, "foo/bar");
}
TEST_F(ConfigSettingTest, setUnorderedSet) {
ConfigSetting<std::unordered_set<std::string>> setting{
"test:value", std::unordered_set<std::string>{}, nullptr};
checkSet(
setting,
std::unordered_set<std::string>{"1", "2", "3", "4"},
"[\"1\", \"2\", \"3\", \"4\"]");
}