libdpf/include/dpf/eval_target.hpp

201 lines
6.2 KiB
C++
Raw Permalink Normal View History

/// @file dpf/eval_target.hpp
/// @brief Eval channel tags for the unified DPF / iDPF / DCF surface.
/// @copyright Copyright (c) 2019-2026 Ryan Henry and [others](@ref authors)
/// @license Released under a GNU General Public v2.0 (GPLv2) license.
#ifndef LIBDPF_INCLUDE_DPF_EVAL_TARGET_HPP__
#define LIBDPF_INCLUDE_DPF_EVAL_TARGET_HPP__
#include <cstddef>
#include <limits>
#include <type_traits>
#include "hedley/hedley.h"
namespace dpf
{
/// @brief Sentinel: deduce point-slot prefix from the key (`meta[I].prefix`).
inline constexpr std::size_t prefix_deduce =
std::numeric_limits<std::size_t>::max();
/// @brief Point-output channel: slot `I`, optional prefix check `N`.
/// @tparam I output index
/// @tparam N prefix length, or `prefix_deduce`
template <std::size_t I = 0, std::size_t N = prefix_deduce>
struct out_t
{
static constexpr std::size_t index = I;
static constexpr std::size_t prefix = N;
static constexpr bool prefix_fixed = (N != prefix_deduce);
};
template <std::size_t I = 0, std::size_t N = prefix_deduce>
inline constexpr out_t<I, N> out{};
/// @brief Comparison (DCF) channel.
struct cmp_t
{
};
inline constexpr cmp_t cmp{};
/// @brief Prefix of an `idcf` comparison. `L` is the number of leading bits.
/// @tparam L number of leading bits
template <std::size_t L>
struct cmp_prefix_t
{
static constexpr std::size_t length = L;
};
template <std::size_t L>
inline constexpr cmp_prefix_t<L> cmp_prefix{};
template <typename T>
struct is_out : std::false_type
{
};
template <std::size_t I, std::size_t N>
struct is_out<out_t<I, N>> : std::true_type
{
};
template <typename T>
inline constexpr bool is_out_v = is_out<std::decay_t<T>>::value;
template <typename T>
struct is_cmp_target : std::bool_constant<std::is_same_v<std::decay_t<T>, cmp_t>>
{
};
template <typename T>
inline constexpr bool is_cmp_target_v = is_cmp_target<T>::value;
template <typename T>
struct is_cmp_prefix_target : std::false_type
{
};
template <std::size_t L>
struct is_cmp_prefix_target<cmp_prefix_t<L>> : std::true_type
{
};
template <typename T>
inline constexpr bool is_cmp_prefix_target_v =
is_cmp_prefix_target<std::decay_t<T>>::value;
/// @brief True for channel tags that must not bind as the key in classic eval_*.
template <typename T>
inline constexpr bool is_eval_channel_tag_v =
is_out_v<T> || is_cmp_target_v<T> || is_cmp_prefix_target_v<T>;
template <typename T, typename = void>
struct looks_like_dpf_key : std::false_type
{
};
HEDLEY_PRAGMA(GCC diagnostic push)
HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
template <typename T>
struct looks_like_dpf_key<T,
std::void_t<typename T::input_type, typename T::interior_node>>
: std::true_type
{
};
HEDLEY_PRAGMA(GCC diagnostic pop)
template <typename T>
inline constexpr bool looks_like_dpf_key_v =
looks_like_dpf_key<std::decay_t<T>>::value;
template <typename T, typename = void>
struct is_incremental_dpf_key : std::false_type
{
};
template <typename T>
struct is_incremental_dpf_key<T,
std::void_t<decltype(T::cmp_depth), decltype(T::meta),
decltype(T::deepest_output)>> : std::true_type
{
};
template <typename T>
inline constexpr bool is_incremental_dpf_key_v =
is_incremental_dpf_key<std::decay_t<T>>::value;
/// @brief True only for keys that must use the slot-aware (multi-level / comparison)
/// eval path. Every key now carries a `slot_meta` table (so
/// `is_incremental_dpf_key_v` is true for all keys), but classic single-level
/// equal-width keys keep using the classic `eval_*` fast paths; they set
/// `is_multilevel == false`. Multi-level (`at<N>`) and comparison keys set it
/// to true.
/// @tparam T value type
template <typename T, typename = void>
struct is_multilevel_key : std::false_type
{
};
template <typename T>
struct is_multilevel_key<T, std::void_t<decltype(T::is_multilevel)>>
: std::bool_constant<T::is_multilevel>
{
};
template <typename T>
inline constexpr bool is_multilevel_key_v =
is_multilevel_key<std::decay_t<T>>::value;
/// @brief True when `T` stores its DPF key in a public member named `dpf_key`
/// and is not itself a DPF key.
/// @details Wrappers (`ic_key`, `vdpf_plus_key`, `dpf3_cmp_key`, `dpf3_ic_key`,
/// and the distributed `opened_*` envelopes) use that member name.
/// `party_key` inherits the DPF key, so it is not a wrapper.
template <typename T, typename = void>
struct has_embedded_dpf_key : std::false_type
{
};
template <typename T>
struct has_embedded_dpf_key<T,
std::void_t<decltype(std::declval<T &>().dpf_key)>>
: std::bool_constant<!looks_like_dpf_key_v<T>>
{
};
template <typename T>
inline constexpr bool has_embedded_dpf_key_v =
has_embedded_dpf_key<std::decay_t<T>>::value;
/// @brief The DPF key `T` evaluates as: `T` itself, or `T::dpf_key` peeled
/// until the result looks like a DPF key.
template <typename T, typename = void>
struct bare_dpf_key
{
using type = std::decay_t<T>;
};
template <typename T>
struct bare_dpf_key<T, std::enable_if_t<has_embedded_dpf_key_v<std::decay_t<T>>>>
: bare_dpf_key<std::decay_t<decltype(std::declval<std::decay_t<T> &>().dpf_key)>>
{
};
template <typename T>
using bare_dpf_key_t = typename bare_dpf_key<std::decay_t<T>>::type;
/// @brief Key-first protocol evals (`dpf3`, `dpf3_cmp`, `dpf3_ic`) keep their
/// own overloads. Peel does not replace those.
template <typename T, typename = void>
struct flag_is_dpf3 : std::false_type {};
template <typename T>
struct flag_is_dpf3<T, std::void_t<decltype(T::is_dpf3)>>
: std::bool_constant<T::is_dpf3> {};
template <typename T, typename = void>
struct flag_is_dpf3_cmp : std::false_type {};
template <typename T>
struct flag_is_dpf3_cmp<T, std::void_t<decltype(T::is_dpf3_cmp)>>
: std::bool_constant<T::is_dpf3_cmp> {};
template <typename T, typename = void>
struct flag_is_dpf3_ic : std::false_type {};
template <typename T>
struct flag_is_dpf3_ic<T, std::void_t<decltype(T::is_dpf3_ic)>>
: std::bool_constant<T::is_dpf3_ic> {};
template <typename T>
inline constexpr bool owns_protocol_eval_v =
flag_is_dpf3<std::decay_t<T>>::value
|| flag_is_dpf3_cmp<std::decay_t<T>>::value
|| flag_is_dpf3_ic<std::decay_t<T>>::value;
} // namespace dpf
#endif // LIBDPF_INCLUDE_DPF_EVAL_TARGET_HPP__