refactor: slightly sleeker variant matching

This commit is contained in:
Marcus Holland-Moritz 2024-01-24 12:34:58 +01:00
parent 905ac667e6
commit 22c079a4ca
6 changed files with 124 additions and 111 deletions

View File

@ -33,7 +33,7 @@
#include <folly/Conv.h> #include <folly/Conv.h>
#include <folly/String.h> #include <folly/String.h>
#include "dwarfs/overloaded.h" #include "dwarfs/match.h"
namespace dwarfs { namespace dwarfs {
@ -51,7 +51,7 @@ class integral_value_parser {
T parse(std::string_view arg) const { T parse(std::string_view arg) const {
auto val = folly::to<T>(arg); auto val = folly::to<T>(arg);
std::visit(overloaded{ valid_ | match{
[](std::monostate const&) {}, [](std::monostate const&) {},
[val](std::pair<T, T> const& minmax) { [val](std::pair<T, T> const& minmax) {
if (val < minmax.first || val > minmax.second) { if (val < minmax.first || val > minmax.second) {
@ -73,8 +73,7 @@ class integral_value_parser {
fmt::format("value {} out of range", val)); fmt::format("value {} out of range", val));
} }
}, },
}, };
valid_);
return val; return val;
} }

View File

@ -21,14 +21,41 @@
#pragma once #pragma once
#include <type_traits>
#include <variant>
namespace dwarfs { namespace dwarfs {
template <typename... Ts> template <typename... Ts>
struct overloaded : Ts... { struct match : Ts... {
using Ts::operator()...; using Ts::operator()...;
}; };
template <typename... Ts> template <typename... Ts>
overloaded(Ts...) -> overloaded<Ts...>; match(Ts...) -> match<Ts...>;
namespace detail {
template <typename T>
struct is_a_variant : std::false_type {};
template <typename... Ts>
struct is_a_variant<std::variant<Ts...>> : std::true_type {};
template <typename T>
struct is_a_match : std::false_type {};
template <typename... Ts>
struct is_a_match<match<Ts...>> : std::true_type {};
} // namespace detail
template <typename T, typename U>
[[nodiscard]] constexpr decltype(auto) operator|(T&& v, U&& m)
requires(detail::is_a_variant<std::decay_t<T>>::value &&
detail::is_a_match<std::decay_t<U>>::value)
{
return std::visit(std::forward<U>(m), std::forward<T>(v));
}
} // namespace dwarfs } // namespace dwarfs

View File

@ -49,11 +49,11 @@
#include "dwarfs/inode_manager.h" #include "dwarfs/inode_manager.h"
#include "dwarfs/inode_ordering.h" #include "dwarfs/inode_ordering.h"
#include "dwarfs/logger.h" #include "dwarfs/logger.h"
#include "dwarfs/match.h"
#include "dwarfs/mmif.h" #include "dwarfs/mmif.h"
#include "dwarfs/nilsimsa.h" #include "dwarfs/nilsimsa.h"
#include "dwarfs/options.h" #include "dwarfs/options.h"
#include "dwarfs/os_access.h" #include "dwarfs/os_access.h"
#include "dwarfs/overloaded.h"
#include "dwarfs/progress.h" #include "dwarfs/progress.h"
#include "dwarfs/promise_receiver.h" #include "dwarfs/promise_receiver.h"
#include "dwarfs/scanner_progress.h" #include "dwarfs/scanner_progress.h"
@ -273,37 +273,33 @@ class inode_ : public inode {
os << " similarity: "; os << " similarity: ";
auto basic_hash_visitor = [&os](uint32_t sh) { auto basic_hash_matcher = [&os](uint32_t sh) {
os << fmt::format("basic ({0:08x})\n", sh); os << fmt::format("basic ({0:08x})\n", sh);
}; };
auto nilsimsa_hash_visitor = [&os](nilsimsa::hash_type const& nh) { auto nilsimsa_hash_matcher = [&os](nilsimsa::hash_type const& nh) {
os << fmt::format("nilsimsa ({0:016x}{1:016x}{2:016x}{3:016x})\n", nh[0], os << fmt::format("nilsimsa ({0:016x}{1:016x}{2:016x}{3:016x})\n", nh[0],
nh[1], nh[2], nh[3]); nh[1], nh[2], nh[3]);
}; };
auto similarity_map_visitor = [&](similarity_map_type const& map) { auto similarity_map_matcher = [&](similarity_map_type const& map) {
os << "map\n"; os << "map\n";
for (auto const& [cat, val] : map) { for (auto const& [cat, val] : map) {
os << " "; os << " ";
dump_category(cat); dump_category(cat);
std::visit( val | match{
overloaded{ basic_hash_matcher,
basic_hash_visitor, nilsimsa_hash_matcher,
nilsimsa_hash_visitor, };
},
val);
} }
}; };
std::visit( similarity_ | match{
overloaded{
[&os](std::monostate const&) { os << "none\n"; }, [&os](std::monostate const&) { os << "none\n"; },
basic_hash_visitor, basic_hash_matcher,
nilsimsa_hash_visitor, nilsimsa_hash_matcher,
similarity_map_visitor, similarity_map_matcher,
}, };
similarity_);
} }
void set_scan_error(file const* fp, std::exception_ptr ep) override { void set_scan_error(file const* fp, std::exception_ptr ep) override {

View File

@ -28,8 +28,8 @@
#include "dwarfs/error.h" #include "dwarfs/error.h"
#include "dwarfs/logger.h" #include "dwarfs/logger.h"
#include "dwarfs/match.h"
#include "dwarfs/metadata_types.h" #include "dwarfs/metadata_types.h"
#include "dwarfs/overloaded.h"
#include "dwarfs/util.h" #include "dwarfs/util.h"
#include "dwarfs/gen-cpp2/metadata_types_custom_protocol.h" #include "dwarfs/gen-cpp2/metadata_types_custom_protocol.h"
@ -590,39 +590,34 @@ auto inode_view::getgid() const -> gid_type {
// TODO: pretty certain some of this stuff can be simplified // TODO: pretty certain some of this stuff can be simplified
std::string dir_entry_view::name() const { std::string dir_entry_view::name() const {
return std::visit(overloaded{ return v_ |
match{
[this](DirEntryView const& dev) { [this](DirEntryView const& dev) {
return g_->names()[dev.name_index()]; return g_->names()[dev.name_index()];
}, },
[this](InodeView const& iv) { [this](InodeView const& iv) {
return std::string( return std::string(g_->meta().names()[iv.name_index_v2_2()]);
g_->meta().names()[iv.name_index_v2_2()]);
}, },
}, };
v_);
} }
inode_view dir_entry_view::inode() const { inode_view dir_entry_view::inode() const {
return std::visit(overloaded{ return v_ | match{
[this](DirEntryView const& dev) { [this](DirEntryView const& dev) {
return inode_view( return inode_view(g_->meta().inodes()[dev.inode_num()],
g_->meta().inodes()[dev.inode_num()],
dev.inode_num(), g_->meta()); dev.inode_num(), g_->meta());
}, },
[this](InodeView const& iv) { [this](InodeView const& iv) {
return inode_view(iv, iv.inode_v2_2(), g_->meta()); return inode_view(iv, iv.inode_v2_2(), g_->meta());
}, },
}, };
v_);
} }
bool dir_entry_view::is_root() const { bool dir_entry_view::is_root() const {
return std::visit( return v_ | match{
overloaded{
[](DirEntryView const& dev) { return dev.inode_num() == 0; }, [](DirEntryView const& dev) { return dev.inode_num() == 0; },
[](InodeView const& iv) { return iv.inode_v2_2() == 0; }, [](InodeView const& iv) { return iv.inode_v2_2() == 0; },
}, };
v_);
} }
/** /**

View File

@ -73,11 +73,11 @@
#include "dwarfs/integral_value_parser.h" #include "dwarfs/integral_value_parser.h"
#include "dwarfs/iolayer.h" #include "dwarfs/iolayer.h"
#include "dwarfs/logger.h" #include "dwarfs/logger.h"
#include "dwarfs/match.h"
#include "dwarfs/mmap.h" #include "dwarfs/mmap.h"
#include "dwarfs/options.h" #include "dwarfs/options.h"
#include "dwarfs/options_interface.h" #include "dwarfs/options_interface.h"
#include "dwarfs/os_access.h" #include "dwarfs/os_access.h"
#include "dwarfs/overloaded.h"
#include "dwarfs/program_options_helpers.h" #include "dwarfs/program_options_helpers.h"
#include "dwarfs/progress.h" #include "dwarfs/progress.h"
#include "dwarfs/scanner.h" #include "dwarfs/scanner.h"
@ -1248,14 +1248,13 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
std::unique_ptr<filesystem_writer> fsw; std::unique_ptr<filesystem_writer> fsw;
try { try {
std::ostream& fsw_os = std::visit( std::ostream& fsw_os =
overloaded{ os |
[&](std::monostate) -> std::ostream& { return iol.out; }, match{[&](std::monostate) -> std::ostream& { return iol.out; },
[&](std::unique_ptr<output_stream>& os) -> std::ostream& { [&](std::unique_ptr<output_stream>& os) -> std::ostream& {
return os->os(); return os->os();
}, },
[&](std::ostringstream& oss) -> std::ostream& { return oss; }}, [&](std::ostringstream& oss) -> std::ostream& { return oss; }};
os);
fsw = std::make_unique<filesystem_writer>( fsw = std::make_unique<filesystem_writer>(
fsw_os, lgr, wg_compress, prog, schema_bc, metadata_bc, history_bc, fsw_os, lgr, wg_compress, prog, schema_bc, metadata_bc, history_bc,
@ -1339,14 +1338,13 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
} }
{ {
auto ec = std::visit( auto ec = os | match{[](std::monostate) -> int { return 0; },
overloaded{[](std::monostate) -> int { return 0; },
[&](std::unique_ptr<output_stream>& os) -> int { [&](std::unique_ptr<output_stream>& os) -> int {
std::error_code ec; std::error_code ec;
os->close(ec); os->close(ec);
if (ec) { if (ec) {
LOG_ERROR << "failed to close output file '" << output LOG_ERROR << "failed to close output file '"
<< "': " << ec.message(); << output << "': " << ec.message();
return 1; return 1;
} }
os.reset(); os.reset();
@ -1355,8 +1353,7 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
[](std::ostringstream& oss [[maybe_unused]]) -> int { [](std::ostringstream& oss [[maybe_unused]]) -> int {
assert(oss.str().empty()); assert(oss.str().empty());
return 0; return 0;
}}, }};
os);
if (ec != 0) { if (ec != 0) {
return ec; return ec;

View File

@ -33,8 +33,8 @@
#include <folly/String.h> #include <folly/String.h>
#include <folly/portability/Unistd.h> #include <folly/portability/Unistd.h>
#include "dwarfs/match.h"
#include "dwarfs/os_access_generic.h" #include "dwarfs/os_access_generic.h"
#include "dwarfs/overloaded.h"
#include "dwarfs/util.h" #include "dwarfs/util.h"
#include "loremipsum.h" #include "loremipsum.h"
#include "mmap_mock.h" #include "mmap_mock.h"
@ -448,16 +448,15 @@ os_access_mock::map_file(fs::path const& path, size_t size) const {
} }
return std::make_unique<mmap_mock>( return std::make_unique<mmap_mock>(
std::visit(overloaded{ de->v | match{
[this](std::string const& str) { return str; }, [this](std::string const& str) { return str; },
[this](std::function<std::string()> const& fun) { [this](std::function<std::string()> const& fun) {
return fun(); return fun();
}, },
[this](auto const&) -> std::string { [this](auto const&) -> std::string {
throw std::runtime_error("oops in overloaded"); throw std::runtime_error("oops in match");
}, },
}, },
de->v),
size); size);
} }