MySQL 9.6.0
Source Code Documentation
resolve_format.h
Go to the documentation of this file.
1// Copyright (c) 2025, Oracle and/or its affiliates.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is designed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of MySQL hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License, version 2.0, for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
24#ifndef MYSQL_STRCONV_FORMATS_RESOLVE_FORMAT_H
25#define MYSQL_STRCONV_FORMATS_RESOLVE_FORMAT_H
26
27/// @file
28/// Experimental API header
29///
30/// This defines the internal function detail::resolve_format, which is used
31/// to find the correct Format class to use for formatting or parsing.
32
33#include <cassert> // assert
34#include <concepts> // same_as
35#include <utility> // declval
36#include "mysql/strconv/formats/format.h" // Is_format
37
38/// @addtogroup GroupLibsMysqlStrconv
39/// @{
40
41namespace mysql::strconv::detail {
42
43/// True if there is a default format type defined for <Format_t, Object_t>.
44template <class Format_t, class Object_t>
45concept Has_default_format = // this comment helps clang-format
46 requires(Format_t format, Object_t object) {
47 { get_default_format(format, object) } -> Is_format;
48 };
49
50/// True if there is a parent format type defined for Format_t.
51template <class Format_t>
52concept Has_parent_format = requires(Format_t format) { format.parent(); };
53
54/// The type of the default format for <Format_t, Object_t>.
55template <class Format_t, class Object_t>
57 std::declval<Format_t>(), std::declval<Object_t>()));
58
59/// True if Func_t::call(Format_t, Object_t) is defined.
60template <template <class, class> class Can_invoke_t, class Format_t,
61 class Object_t>
63
64/// True if <Format_t, Object_t> has a default format and Func_t::call is
65/// defined for <Default_format_type<Format_t, Object_t>, Object_t>.
66template <template <class, class> class Can_invoke_t, class Format_t,
67 class Object_t>
71
72/// Return the format to pass to the implementation function, given the format
73/// and object type passed by the user to the API. The three overloads,
74/// together, have the effect of using the encode_impl with exactly the
75/// requested Format_t type if it exists; otherwise, use the encode_impl
76/// using exactly the default format if it exists; otherwise, recursively,
77/// perform the same checks for the parent format. Returns void if no
78/// implementation is found.
79///
80/// @tparam Can_invoke_t Two-argument type predicate. When instantiated with a
81/// format type and an object type, it should have the member `value` equal to
82/// true if there is an implementation of `encode_impl`/`decode_impl`for
83/// that combination of arguments.
84///
85/// @tparam Object_t Type of object to check.
86///
87/// @tparam Format_t Type of format to check.
88///
89/// @param format Format to check.
90///
91/// @param object Object to check.
92///
93/// return: If there is an implementation for `Format_t`, returns `format`.
94/// Otherwise, if there is an implementation for the default format, returns the
95/// default format. Otherwise, if there is a parent format, recursively checks
96/// that. If no format is found this way, the return type is void.
97template <template <class, class> class Can_invoke_t, class Object_t,
98 Is_format Format_t>
99constexpr void do_resolve_format(const Format_t &format [[maybe_unused]],
100 const Object_t &object [[maybe_unused]]) {
101 assert(false);
102}
103
104template <template <class, class> class Can_invoke_t, class Object_t,
105 Is_format Format_t>
106 requires Has_impl<Can_invoke_t, Format_t, Object_t>
107constexpr Format_t do_resolve_format(const Format_t &format,
108 const Object_t &object [[maybe_unused]]) {
109 return format;
110}
111
112template <template <class, class> class Can_invoke_t, class Object_t,
113 Is_format Format_t>
114 requires(!Has_impl<Can_invoke_t, Format_t, Object_t> &&
115 Has_default_impl<Can_invoke_t, Format_t, Object_t>)
116constexpr auto do_resolve_format(const Format_t &format,
117 const Object_t &object) {
118 return get_default_format(format, object);
119}
120
121template <template <class, class> class Can_invoke_t, class Object_t,
122 Is_format Format_t>
123 requires(!Has_impl<Can_invoke_t, Format_t, Object_t> &&
124 !Has_default_impl<Can_invoke_t, Format_t, Object_t> &&
125 Has_parent_format<Format_t>)
126constexpr auto do_resolve_format(const Format_t &format,
127 const Object_t &object) {
128 return do_resolve_format<Can_invoke_t>(format.parent(), object);
129}
130
131/// The return type of `do_resolve_format`.
132template <template <class, class> class Can_invoke_t, class Format_t,
133 class Object_t>
134using Resolved_format_type = decltype(do_resolve_format<Can_invoke_t>(
135 std::declval<Format_t>(), std::declval<Object_t>()));
136
137// NOLINTNEXTLINE(performance-enum-size): silence clang-tidy's pointless hint
139
140/// Return the format to pass to the implementation function, given the format
141/// and object type passed by the user to the API. This checks for
142/// implementations for the format itself, its default format, and the parent
143/// format(s). Fails to compile if no implementation is found.
144///
145/// @tparam Can_invoke_t Two-argument type predicate. When instantiated with a
146/// format type and an object type, it should have the member `value` equal to
147/// true if there is an implementation of `encode_impl`/`decode_impl`for
148/// that combination of format/object arguments.
149///
150/// @tparam Object_t Type of object to check.
151///
152/// @tparam Format_t Type of format to check.
153///
154/// @param format Format to check.
155///
156/// @param object Object to check.
157///
158/// @return If there is an implementation for `Format_t`, returns `format`.
159/// Otherwise, if there is an implementation for the default format, returns the
160/// default format. Otherwise, if there is a parent format, recursively checks
161/// that. If no format is found this way, generates a compilation error.
162template <Conversion_direction conversion_direction,
163 template <class, class> class Can_invoke_t, class Object_t,
164 Is_format Format_t>
165constexpr auto resolve_format(const Format_t &format, const Object_t &object) {
167 constexpr bool can_resolve = !std::same_as<Return_t, void>;
168 if constexpr (can_resolve) {
169 return do_resolve_format<Can_invoke_t>(format, object);
170 } else {
171// static_assert accepts only string literals for the message, so when we
172// need to compute a message it can only be implemented using a macro.
173// NOLINTBEGIN(cppcoreguidelines-macro-usage)
174#define RESOLVE_FORMAT_ERROR_MESSAGE(TOFROM, PROTOTYPE_ARGS) \
175 "No `mysql::strconv::" TOFROM \
176 "_string_impl` for `Format_t` and " \
177 "`Object_t`, because " \
178 "(1) There is no direct implementation defined with the prototype " \
179 "`mysql::strconv::" TOFROM "_string_impl(const Format_t &, " PROTOTYPE_ARGS \
180 ") (or there are more than one, ambiguously); and " \
181 "(2) there is no default format or no implementation for the " \
182 "default format, i.e., either " \
183 "`get_default_format(const Format_t &, const Object_t &)` " \
184 "is not defined or `mysql::strconv::" TOFROM \
185 "_string_impl(const /*default format*/ &, " PROTOTYPE_ARGS \
186 ")` is not defined (or is defined more than once, ambiguously); and " \
187 "(3) there is no parent format or no implementation for the parent " \
188 "format, i.e., either `Format_t::parent()` is not defined or " \
189 "(1), (2), (3) fail also when replacing `Format_t` by " \
190 "`decltype(Format_t::parent())`. " \
191 "If you believe you have implemented the necessary functions, maybe " \
192 "there are mistakes in their prototypes; to debug this, double-check " \
193 "the namespace, `const` and `&` qualifiers, and/or try to invoke `" TOFROM \
194 "_string_impl` directly and check the compilation error."
195 // NOLINTEND(cppcoreguidelines-macro-usage)
196
197 // clang-tidy evaluates this even if it shouldn't.
198 // NOLINTBEGIN
199 if constexpr (conversion_direction == Conversion_direction::encode) {
200 static_assert( // this comment helps clang-format
201 can_resolve, RESOLVE_FORMAT_ERROR_MESSAGE(
202 "to", "Is_string_target auto &, const Object_t &"));
203 } else {
204 static_assert( // this comment helps clang-format
205 can_resolve,
206 RESOLVE_FORMAT_ERROR_MESSAGE("from", "Parser &, Object_t &"));
207 }
210 static_assert(Has_parent_format<Format_t>);
211 // NOLINTEND
212#undef RESOLVE_FORMAT_ERROR_MESSAGE
213 }
214}
215
216} // namespace mysql::strconv::detail
217
218// addtogroup GroupLibsMysqlStrconv
219/// @}
220
221#endif // ifndef MYSQL_STRCONV_FORMATS_RESOLVE_FORMAT_H
True if Test is a format.
Definition: format.h:42
True if there is a default format type defined for <Format_t, Object_t>.
Definition: resolve_format.h:45
True if <Format_t, Object_t> has a default format and Func_t::call is defined for <Default_format_typ...
Definition: resolve_format.h:68
True if Func_t::call(Format_t, Object_t) is defined.
Definition: resolve_format.h:62
True if there is a parent format type defined for Format_t.
Definition: resolve_format.h:52
Experimental API header.
std::string format(const routing_guidelines::Session_info &session_info, bool extended_session_info)
Definition: dest_metadata_cache.cc:170
ValueType value(const std::optional< ValueType > &v)
Definition: gtid.h:83
Definition: gtid_binary_format_conv.h:252
decltype(get_default_format(std::declval< Format_t >(), std::declval< Object_t >())) Default_format_type
The type of the default format for <Format_t, Object_t>.
Definition: resolve_format.h:57
constexpr void do_resolve_format(const Format_t &format, const Object_t &object)
Return the format to pass to the implementation function, given the format and object type passed by ...
Definition: resolve_format.h:99
decltype(do_resolve_format< Can_invoke_t >(std::declval< Format_t >(), std::declval< Object_t >())) Resolved_format_type
The return type of do_resolve_format.
Definition: resolve_format.h:135
constexpr auto resolve_format(const Format_t &format, const Object_t &object)
Return the format to pass to the implementation function, given the format and object type passed by ...
Definition: resolve_format.h:165
Conversion_direction
Definition: resolve_format.h:138
auto get_default_format(const Binary_format &, const Object_t &)
Definition: gtid_binary_format.h:114
decltype(call_function()) Return_t
Definition: call_and_catch.h:80
#define RESOLVE_FORMAT_ERROR_MESSAGE(TOFROM, PROTOTYPE_ARGS)