33 static constexpr std::uint64_t
width = N;
36 namespace registry_detail {
37 template <
class Values,
unsigned Shift>
struct value_bits;
39 static constexpr std::optional<std::uint64_t> value = std::nullopt;
42 static_assert(N <= (std::numeric_limits<std::uint64_t>::max() >> Shift),
43 "fixed value width exceeds a bit extent");
44 static constexpr std::optional<std::uint64_t> value = N << Shift;
81 namespace registry_detail {
82 template <
class T>
inline constexpr bool hole = std::is_same_v<T, sort_undefined>;
83 template <
class... S>
struct sorts {};
91 : std::bool_constant<(!std::is_same_v<A, B> && ...) && unique<sorts<B...>>::value> {};
95 static constexpr std::size_t
count = 0;
96 static constexpr std::optional<profile_unit>
mode = std::nullopt;
97 static constexpr std::optional<std::uint64_t>
width = std::nullopt;
99 template <
class S,
bool = hole<S>>
struct leaf :
empty {};
100 template <
class S>
struct leaf<S, false> {
103 static constexpr std::size_t
count = 1;
104 static constexpr std::optional<profile_unit>
mode = encoding::unit;
106 "sort encoding has an invalid storage unit");
107 static constexpr std::optional<std::uint64_t>
width = encoding::fixed_value_bits;
109 "byte sort values must occupy whole bytes");
112 template <
class A,
class B>
struct join {
114 static constexpr std::size_t
count = A::count + B::count;
115 static constexpr std::optional<std::uint64_t>
width = !A::count ? B::width :
116 !B::count ? A::width : A::width && B::width && A::width == B::width ? A::width : std::nullopt;
119 template <
class S,
class... Rest>
struct list_width<S, Rest...>
120 :
join<leaf<S>, list_width<Rest...>> {};
122 template <
class R>
struct info;
126 template <
class L,
class R>
struct info<
bin<L, R>> :
join<info<L>, info<R>> {
130 static_assert(
sizeof...(S) <= 256,
"a byte sort list has at most 256 codes");
132 "a byte sort list requires byte encodings");
136 template <
class Old,
class New>
struct extends;
137 template <
class Old,
class New>
struct extension : std::is_same<Old, New> {};
140 template <
class OL,
class OR,
class NL,
class NR>
142 : std::bool_constant<extends<OL, NL>::value && extends<OR, NR>::value> {};
143 template <
class Old,
class New, std::size_t... I>
145 if constexpr (std::tuple_size_v<Old> > std::tuple_size_v<New>)
return false;
146 else return ((
hole<std::tuple_element_t<I, Old>> ||
147 std::is_same_v<std::tuple_element_t<I, Old>, std::tuple_element_t<I, New>>) && ...);
150 : std::bool_constant<list_extends<std::tuple<O...>, std::tuple<N...>>(std::index_sequence_for<O...>{})> {};
151 template <
class Old,
class New>
struct extends
152 : std::bool_constant<info<Old>::count == 0 || extension<Old, New>::value> {};
154 template <
class Leaves,
class Reader,
class Visitor>
struct result;
155 template <
class Reader,
class Visitor>
struct result<
sorts<>, Reader, Visitor> {
using type = void; };
156 template <
class S,
class... Rest,
class Reader,
class Visitor>
158 using type = std::invoke_result_t<Visitor, std::type_identity<S>, Reader &>;
159 static_assert((std::is_same_v<
type,
160 std::invoke_result_t<Visitor, std::type_identity<Rest>, Reader &>> && ...),
161 "sort visitor branches must have the same return type");
164 auto code =
static_cast<std::uint64_t
>(reader.read_bits(width));
165 if (code >= (std::uint64_t{1} << width))
166 error_detail::raise<std::invalid_argument>(
"sort discriminator exceeds its width");
169 template <
class S,
class Result,
class Reader,
class Visitor>
170 Result
visit(Reader & reader, Visitor && visitor) {
171 if constexpr (hole<S>) error_detail::raise<std::invalid_argument>(
"undefined sort code");
172 else return std::invoke(std::forward<Visitor>(visitor), std::type_identity<S>{}, reader);
176 template <
class Result,
class Reader,
class Visitor>
177 static Result
run(Reader &, Visitor &&) {
178 error_detail::raise<std::invalid_argument>(
"empty sort registry");
182 template <
class Result,
class Reader,
class Visitor>
183 static Result
run(Reader & reader, Visitor && visitor) {
184 return visit<S, Result>(reader, std::forward<Visitor>(visitor));
189 template <
class Result,
class Reader,
class Visitor>
190 static Result
run(Reader & reader, Visitor && visitor) {
197 template <std::
size_t I,
class Result,
class Reader,
class Visitor>
198 static Result
at(std::uint64_t code, Reader & reader, Visitor && visitor) {
199 if constexpr (I ==
sizeof...(S))
200 error_detail::raise<std::invalid_argument>(
"undefined sort code");
202 if (code == I)
return visit<std::tuple_element_t<I, std::tuple<S...>>, Result>(reader,
203 std::forward<Visitor>(visitor));
204 return at<I + 1, Result>(code, reader, std::forward<Visitor>(visitor));
207 template <
class Result,
class Reader,
class Visitor>
208 static Result
run(Reader & reader, Visitor && visitor) {
209 return at<0, Result>(
discriminator(reader, 8), reader, std::forward<Visitor>(visitor));
220 "each sort type must have exactly one registry code");
233 : std::bool_constant<(sizeof(registry_traits<Old>) != 0) && (sizeof(registry_traits<New>) != 0) &&
234 registry_detail::extends<Old, New>::value> {};
235 template <
class Old,
class New>
243 template <
class R,
class Reader,
class Visitor>
247 Reader, Visitor &&>::type;
Outlines exceptional check failures while preserving their types and messages.
std::uint64_t discriminator(auto &reader, unsigned width)
Definition registry.h:163
Result visit(Reader &reader, Visitor &&visitor)
Definition registry.h:170
constexpr bool hole
Definition registry.h:82
consteval bool list_extends(std::index_sequence< I... >)
Definition registry.h:144
Definition active_engine.h:18
constexpr bool registry_extends_v
Definition registry.h:236
decltype(auto) dispatch_sort(Reader &reader, Visitor &&visitor)
Definition registry.h:244
profile_unit
Definition registry.h:29
R right_type
Definition registry.h:78
L left_type
Definition registry.h:78
static constexpr profile_unit unit
Definition registry.h:56
static constexpr auto fixed_value_bits
Definition registry.h:57
static constexpr auto fixed_value_bits
Definition registry.h:53
static constexpr profile_unit unit
Definition registry.h:52
Codec encoding
Definition registry.h:59
static constexpr std::uint64_t width
Definition registry.h:33
static Result run(Reader &reader, Visitor &&visitor)
Definition registry.h:190
static Result run(Reader &reader, Visitor &&visitor)
Definition registry.h:208
static Result at(std::uint64_t code, Reader &reader, Visitor &&visitor)
Definition registry.h:198
static Result run(Reader &, Visitor &&)
Definition registry.h:177
static Result run(Reader &reader, Visitor &&visitor)
Definition registry.h:183
Definition registry.h:174
static constexpr std::optional< std::uint64_t > width
Definition registry.h:97
static constexpr std::size_t count
Definition registry.h:95
static constexpr std::optional< profile_unit > mode
Definition registry.h:96
Definition registry.h:152
Definition registry.h:137
Definition registry.h:122
Definition registry.h:112
static constexpr std::size_t count
Definition registry.h:114
typename concatenate< typename A::leaves, typename B::leaves >::type leaves
Definition registry.h:113
static constexpr std::optional< std::uint64_t > width
Definition registry.h:115
typename S::encoding encoding
Definition registry.h:101
Definition registry.h:118
std::invoke_result_t< Visitor, std::type_identity< S >, Reader & > type
Definition registry.h:158
void type
Definition registry.h:155
Definition registry.h:154
Definition registry.h:234
Definition registry.h:217
static constexpr profile_unit unit
Definition registry.h:222
static constexpr std::size_t sort_count
Definition registry.h:221
static constexpr bool fixed_width
Definition registry.h:226
static constexpr auto value_width
Definition registry.h:224
static constexpr auto fixed_value_bits
Definition registry.h:223
R registry_type
Definition registry.h:218
S sort_type
Definition registry.h:77
T value_type
Definition registry.h:71
typename value_encoding< T >::type encoding
Definition registry.h:72
typename T::encoding type
Definition registry.h:63