Skip to content

Commit

Permalink
Make more classes hashable and comparable (#3363)
Browse files Browse the repository at this point in the history
Signed-off-by: Julien Jerphanion <[email protected]>
Co-authored-by: Klaim <[email protected]>
  • Loading branch information
jjerphan and Klaim authored Jul 29, 2024
1 parent 154012f commit b09f1d1
Show file tree
Hide file tree
Showing 12 changed files with 327 additions and 0 deletions.
21 changes: 21 additions & 0 deletions libmamba/include/mamba/specs/build_number_spec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <fmt/format.h>

#include "mamba/specs/error.hpp"
#include "mamba/util/tuple_hash.hpp"

namespace mamba::specs
{
Expand Down Expand Up @@ -124,6 +125,17 @@ namespace mamba::specs
*/
[[nodiscard]] auto contains(BuildNumber point) const -> bool;

// TODO(C++20): replace by the `= default` implementation of `operator==`
[[nodiscard]] auto operator==(const BuildNumberSpec& other) const -> bool
{
return m_predicate == other.m_predicate;
}

[[nodiscard]] auto operator!=(const BuildNumberSpec& other) const -> bool
{
return !(*this == other);
}

private:

BuildNumberPredicate m_predicate;
Expand Down Expand Up @@ -155,4 +167,13 @@ struct fmt::formatter<mamba::specs::BuildNumberSpec>
format(const ::mamba::specs::BuildNumberSpec& spec, format_context& ctx) -> decltype(ctx.out());
};

template <>
struct std::hash<mamba::specs::BuildNumberSpec>
{
auto operator()(const mamba::specs::BuildNumberSpec& spec) const -> std::size_t
{
return mamba::util::hash_vals(spec.str());
}
};

#endif
21 changes: 21 additions & 0 deletions libmamba/include/mamba/specs/chimera_string_spec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "mamba/specs/error.hpp"
#include "mamba/specs/glob_spec.hpp"
#include "mamba/specs/regex_spec.hpp"
#include "mamba/util/tuple_hash.hpp"

namespace mamba::specs
{
Expand Down Expand Up @@ -51,6 +52,17 @@ namespace mamba::specs

[[nodiscard]] auto str() const -> const std::string&;

// TODO(C++20): replace by the `= default` implementation of `operator==`
[[nodiscard]] auto operator==(const ChimeraStringSpec& other) const -> bool
{
return m_spec == other.m_spec;
}

[[nodiscard]] auto operator!=(const ChimeraStringSpec& other) const -> bool
{
return !(*this == other);
}

private:

Chimera m_spec;
Expand All @@ -66,4 +78,13 @@ struct fmt::formatter<mamba::specs::ChimeraStringSpec>
format(const ::mamba::specs::ChimeraStringSpec& spec, format_context& ctx) -> decltype(ctx.out());
};

template <>
struct std::hash<mamba::specs::ChimeraStringSpec>
{
auto operator()(const mamba::specs::ChimeraStringSpec& spec) const -> std::size_t
{
return mamba::util::hash_vals(spec.str());
}
};

#endif
20 changes: 20 additions & 0 deletions libmamba/include/mamba/specs/glob_spec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ namespace mamba::specs

[[nodiscard]] auto str() const -> const std::string&;

// TODO(C++20): replace by the `= default` implementation of `operator==`
[[nodiscard]] auto operator==(const GlobSpec& other) const -> bool
{
return m_pattern == other.m_pattern;
}

[[nodiscard]] auto operator!=(const GlobSpec& other) const -> bool
{
return !(*this == other);
}

private:

std::string m_pattern = std::string(free_pattern);
Expand All @@ -57,4 +68,13 @@ struct fmt::formatter<mamba::specs::GlobSpec>
auto format(const ::mamba::specs::GlobSpec& spec, format_context& ctx) -> decltype(ctx.out());
};

template <>
struct std::hash<mamba::specs::GlobSpec>
{
auto operator()(const mamba::specs::GlobSpec& spec) const -> std::size_t
{
return std::hash<std::string>{}(spec.str());
}
};

#endif
82 changes: 82 additions & 0 deletions libmamba/include/mamba/specs/match_spec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "mamba/specs/version_spec.hpp"
#include "mamba/util/flat_set.hpp"
#include "mamba/util/heap_optional.hpp"
#include "mamba/util/tuple_hash.hpp"

namespace mamba::specs
{
Expand Down Expand Up @@ -135,6 +136,28 @@ namespace mamba::specs
*/
[[nodiscard]] auto contains_except_channel(const PackageInfo& pkg) const -> bool;

// TODO(C++20): replace by the `= default` implementation of `operator==`
[[nodiscard]] auto operator==(const MatchSpec& other) const -> bool
{
return m_channel == other.m_channel //
&& m_version == other.m_version //
&& m_name == other.m_name //
&& m_build_string == other.m_build_string //
&& m_name_space == other.m_name_space //
&& m_build_number == other.m_build_number //
&& m_extra == other.m_extra;
}

[[nodiscard]] auto operator!=(const MatchSpec& other) const -> bool
{
return !(*this == other);
}

auto extra_members_hash() const -> std::size_t
{
return mamba::util::hash_vals(m_extra);
}

private:

struct ExtraMembers
Expand All @@ -150,7 +173,29 @@ namespace mamba::specs
std::string features = {};
string_set track_features = {};
bool optional = false;

// TODO(C++20): replace by the `= default` implementation of `operator==`
[[nodiscard]] auto operator==(const ExtraMembers& other) const -> bool
{
return filename == other.filename //
&& subdirs == other.subdirs //
&& md5 == other.md5 //
&& sha256 == other.sha256 //
&& license == other.license //
&& license_family == other.license_family //
&& features == other.features //
&& track_features == other.track_features //
&& optional == other.optional;
}

[[nodiscard]] auto operator!=(const ExtraMembers& other) const -> bool
{
return !(*this == other);
}

friend struct std::hash<ExtraMembers>;
};
friend struct std::hash<MatchSpec::ExtraMembers>;

std::optional<UnresolvedChannel> m_channel;
VersionSpec m_version;
Expand Down Expand Up @@ -255,4 +300,41 @@ namespace mamba::specs
return true;
}
}

template <>
struct std::hash<mamba::specs::MatchSpec>
{
auto operator()(const mamba::specs::MatchSpec& spec) const -> std::size_t
{
return mamba::util::hash_vals(
spec.channel(),
spec.version(),
spec.name(),
spec.build_string(),
spec.name_space(),
spec.build_number(),
spec.extra_members_hash()
);
}
};

template <>
struct std::hash<mamba::specs::MatchSpec::ExtraMembers>
{
auto operator()(const mamba::specs::MatchSpec::ExtraMembers& extra) const -> std::size_t
{
return mamba::util::hash_vals(
extra.filename,
extra.subdirs,
extra.md5,
extra.sha256,
extra.license,
extra.license_family,
extra.features,
extra.track_features,
extra.optional
);
}
};

#endif
44 changes: 44 additions & 0 deletions libmamba/include/mamba/specs/package_info.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "mamba/specs/error.hpp"
#include "mamba/specs/platform.hpp"
#include "mamba/util/tuple_hash.hpp"

namespace mamba::specs
{
Expand Down Expand Up @@ -81,4 +82,47 @@ namespace mamba::specs

void from_json(const nlohmann::json& j, PackageInfo& pkg);
}

template <>
struct std::hash<mamba::specs::PackageInfo>
{
auto operator()(const mamba::specs::PackageInfo& pkg) const -> std::size_t
{
auto seed = std::size_t(0);
seed = mamba::util::hash_vals(
seed,
pkg.name,
pkg.version,
pkg.build_string,
pkg.build_number,
pkg.channel,
pkg.package_url,
pkg.platform,
pkg.filename,
pkg.license,
pkg.md5,
pkg.sha256,
pkg.signatures
);
seed = mamba::util::hash_combine_val_range(
seed,
pkg.track_features.begin(),
pkg.track_features.end()
);
seed = mamba::util::hash_combine_val_range(
seed,
pkg.dependencies.begin(),
pkg.dependencies.end()
);
seed = mamba::util::hash_combine_val_range(seed, pkg.constrains.begin(), pkg.constrains.end());
seed = mamba::util::hash_combine_val_range(
seed,
pkg.defaulted_keys.begin(),
pkg.defaulted_keys.end()
);
seed = mamba::util::hash_vals(seed, pkg.noarch, pkg.size, pkg.timestamp, pkg.package_type);
return seed;
}
};

#endif
12 changes: 12 additions & 0 deletions libmamba/include/mamba/specs/regex_spec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ namespace mamba::specs

[[nodiscard]] auto str() const -> const std::string&;

// TODO(C++20): replace by the `= default` implementation of `operator==`
[[nodiscard]] auto operator==(const RegexSpec& other) const -> bool
{
return m_raw_pattern == other.m_raw_pattern
&& m_pattern.flags() == other.m_pattern.flags();
}

[[nodiscard]] auto operator!=(const RegexSpec& other) const -> bool
{
return !(*this == other);
}

private:

std::regex m_pattern;
Expand Down
22 changes: 22 additions & 0 deletions libmamba/include/mamba/specs/unresolved_channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "mamba/specs/error.hpp"
#include "mamba/specs/platform.hpp"
#include "mamba/util/flat_set.hpp"
#include "mamba/util/tuple_hash.hpp"

namespace mamba::specs
{
Expand Down Expand Up @@ -111,6 +112,18 @@ namespace mamba::specs

[[nodiscard]] auto str() const -> std::string;

[[nodiscard]] auto operator==(const UnresolvedChannel& other) const -> bool
{
return m_location == other.m_location //
&& m_platform_filters == other.m_platform_filters //
&& m_type == other.m_type;
}

[[nodiscard]] auto operator!=(const UnresolvedChannel& other) const -> bool
{
return !(*this == other);
}

private:

std::string m_location = std::string(unknown_channel);
Expand All @@ -137,4 +150,13 @@ struct fmt::formatter<mamba::specs::UnresolvedChannel>
auto format(const UnresolvedChannel& uc, format_context& ctx) const -> format_context::iterator;
};

template <>
struct std::hash<mamba::specs::UnresolvedChannel>
{
auto operator()(const mamba::specs::UnresolvedChannel& uc) const -> std::size_t
{
return mamba::util::hash_vals(uc.location(), uc.platform_filters(), static_cast<int>(uc.type()));
}
};

#endif
30 changes: 30 additions & 0 deletions libmamba/include/mamba/specs/version_spec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "mamba/specs/error.hpp"
#include "mamba/specs/version.hpp"
#include "mamba/util/flat_bool_expr_tree.hpp"
#include "mamba/util/tuple_hash.hpp"

namespace mamba::specs
{
Expand Down Expand Up @@ -195,6 +196,16 @@ namespace mamba::specs
*/
[[nodiscard]] auto expression_size() const -> std::size_t;

[[nodiscard]] auto operator==(const VersionSpec& other) const -> bool
{
return m_tree == other.m_tree;
}

[[nodiscard]] auto operator!=(const VersionSpec& other) const -> bool
{
return !(*this == other);
}

private:

tree_type m_tree;
Expand Down Expand Up @@ -234,4 +245,23 @@ struct fmt::formatter<mamba::specs::VersionSpec>

auto format(const ::mamba::specs::VersionSpec& spec, format_context& ctx) -> decltype(ctx.out());
};

template <>
struct std::hash<mamba::specs::VersionPredicate>
{
auto operator()(const mamba::specs::VersionPredicate& pred) const -> std::size_t
{
return mamba::util::hash_vals(pred.str());
}
};

template <>
struct std::hash<mamba::specs::VersionSpec>
{
auto operator()(const mamba::specs::VersionSpec& spec) const -> std::size_t
{
return mamba::util::hash_vals(spec.str());
}
};

#endif
Loading

0 comments on commit b09f1d1

Please sign in to comment.