Add std::hash implementation for oxenmq::address

So that you can store addresses in unordered_sets _maps.
This commit is contained in:
Jason Rhinelander 2021-11-28 10:26:35 -04:00
parent a53e1f1786
commit 31f64821f8
2 changed files with 41 additions and 1 deletions

View File

@ -31,6 +31,7 @@
#include <string_view>
#include <cstdint>
#include <iosfwd>
#include <functional>
namespace oxenmq {
@ -206,4 +207,12 @@ struct address {
// Outputs address.full_address() when sent to an ostream.
std::ostream& operator<<(std::ostream& o, const address& a);
}
} // namespace oxenmq
namespace std {
template<> struct hash<oxenmq::address> {
std::size_t operator()(const oxenmq::address& a) const noexcept {
return std::hash<std::string>{}(a.full_address(oxenmq::address::encoding::hex));
}
};
} // namespace std

View File

@ -129,3 +129,34 @@ TEST_CASE("tcp QR-code friendly addresses", "[address][tcp][qr]") {
REQUIRE_THROWS_AS(address{"CURVE://PUBLIC.LOKI.FOUNDATION:12345/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="}, std::invalid_argument);
}
TEST_CASE("address hashing", "[address][hash]") {
address a{"tcp://public.loki.foundation:12345"};
address b{"tcp+curve://public.loki.foundation:12345/" + pk_hex};
address c{"ipc:///tmp/some.sock"};
address d{"ipc:///tmp/some.other.sock"};
std::hash<oxenmq::address> hasher{};
REQUIRE( hasher(a) != hasher(b) );
REQUIRE( hasher(a) != hasher(c) );
REQUIRE( hasher(a) != hasher(d) );
REQUIRE( hasher(b) != hasher(c) );
REQUIRE( hasher(b) != hasher(d) );
REQUIRE( hasher(c) != hasher(d) );
std::unordered_set<oxenmq::address> set;
set.insert(a);
set.insert(b);
set.insert(c);
set.insert(d);
CHECK( set.size() == 4 );
std::unordered_map<oxenmq::address, int> count;
for (const auto& addr : set)
count[addr]++;
REQUIRE( count.size() == 4 );
CHECK( count[a] == 1 );
CHECK( count[b] == 1 );
CHECK( count[c] == 1 );
CHECK( count[d] == 1 );
}