message: move enum-string conversion routines
Move enum conversion routines out of the 'details' namespace
so they are available for library users and consolidate them
in the 'native_types' header.
In order to support future work of template-specialization on
`variant` types, this also added a level of indirection in the
generated specializations for enums so that they are handled
through a struct-with-op pattern. (Functions cannot be partially
specialized and overloading the template with std::variant support
requires that).
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: I1db7cface90abe7296b9043ca9caa247368821de
diff --git a/include/sdbusplus/message/append.hpp b/include/sdbusplus/message/append.hpp
index 0fb1eb8..5dd8645 100644
--- a/include/sdbusplus/message/append.hpp
+++ b/include/sdbusplus/message/append.hpp
@@ -42,15 +42,6 @@
namespace details
{
-/** @brief Convert from a native type to a string.
- *
- * Some C++ types cannot be represented directly on dbus, so we encode
- * them as strings. Enums are the primary example of this. This is a
- * template function prototype for the conversion to string functions.
- */
-template <typename T>
-std::string convert_to_string(T) = delete;
-
/** @struct can_append_multiple
* @brief Utility to identify C++ types that may not be grouped into a
* single sd_bus_message_append call and instead need special
@@ -179,7 +170,7 @@
static std::enable_if_t<std::is_same_v<S, Td<T>> && std::is_enum_v<Td<T>>>
op(sdbusplus::SdBusInterface* intf, sd_bus_message* m, T&& t)
{
- auto value = convert_to_string<Td<T>>(t);
+ auto value = sdbusplus::message::convert_to_string<Td<T>>(t);
sdbusplus::message::append(intf, m, value);
}
};
diff --git a/include/sdbusplus/message/native_types.hpp b/include/sdbusplus/message/native_types.hpp
index d76604b..1f77914 100644
--- a/include/sdbusplus/message/native_types.hpp
+++ b/include/sdbusplus/message/native_types.hpp
@@ -175,6 +175,52 @@
using signature = details::string_wrapper;
using unix_fd = details::unix_fd_type;
+namespace details
+{
+
+template <typename T>
+struct convert_from_string
+{
+ static auto op(const std::string&) noexcept = delete;
+};
+
+template <typename T>
+struct convert_to_string
+{
+ static std::string op(T) = delete;
+};
+
+} // namespace details
+
+/** @brief Convert from a string to a native type.
+ *
+ * Some C++ types cannot be represented directly on dbus, so we encode
+ * them as strings. Enums are the primary example of this. This is a
+ * template function prototype for the conversion from string functions.
+ *
+ * @return A std::optional<T> containing the value if conversion is possible.
+ */
+template <typename T>
+auto convert_from_string(const std::string& str) noexcept
+{
+ return details::convert_from_string<T>::op(str);
+};
+
+/** @brief Convert from a native type to a string.
+ *
+ * Some C++ types cannot be represented directly on dbus, so we encode
+ * them as strings. Enums are the primary example of this. This is a
+ * template function prototype for the conversion to string functions.
+ *
+ * @return A std::string containing an encoding of the value, if conversion is
+ * possible.
+ */
+template <typename T>
+std::string convert_to_string(T t)
+{
+ return details::convert_to_string<T>::op(t);
+}
+
} // namespace message
} // namespace sdbusplus
diff --git a/include/sdbusplus/message/read.hpp b/include/sdbusplus/message/read.hpp
index 92a2839..e64066e 100644
--- a/include/sdbusplus/message/read.hpp
+++ b/include/sdbusplus/message/read.hpp
@@ -43,15 +43,6 @@
namespace details
{
-/** @brief Convert from a string to a native type.
- *
- * Some C++ types cannot be represented directly on dbus, so we encode
- * them as strings. Enums are the primary example of this. This is a
- * template function prototype for the conversion from string functions.
- */
-template <typename T>
-auto convert_from_string(const std::string&) noexcept = delete;
-
/** @struct can_read_multiple
* @brief Utility to identify C++ types that may not be grouped into a
* single sd_bus_message_read call and instead need special
@@ -167,7 +158,7 @@
std::string value{};
sdbusplus::message::read(intf, m, value);
- auto r = convert_from_string<Td<T>>(value);
+ auto r = sdbusplus::message::convert_from_string<Td<T>>(value);
if (!r)
{
throw sdbusplus::exception::InvalidEnumString();
diff --git a/tools/sdbusplus/templates/interface.server.hpp.mako b/tools/sdbusplus/templates/interface.server.hpp.mako
index 1a3d25e..92f29ee 100644
--- a/tools/sdbusplus/templates/interface.server.hpp.mako
+++ b/tools/sdbusplus/templates/interface.server.hpp.mako
@@ -216,25 +216,26 @@
} // namespace ${s}
% endfor
-namespace message
-{
-namespace details
+namespace message::details
{
% for e in interface.enums:
template <>
-inline auto convert_from_string<${interface.cppNamespace()}::${e.name}>(
- const std::string& value) noexcept
+struct convert_from_string<${interface.cppNamespace()}::${e.name}>
{
- return ${interface.cppNamespace()}::convertStringTo${e.name}(value);
-}
+ static auto op(const std::string& value) noexcept
+ {
+ return ${interface.cppNamespace()}::convertStringTo${e.name}(value);
+ }
+};
template <>
-inline std::string convert_to_string<${interface.cppNamespace()}::${e.name}>(
- ${interface.cppNamespace()}::${e.name} value)
+struct convert_to_string<${interface.cppNamespace()}::${e.name}>
{
- return ${interface.cppNamespace()}::convert${e.name}ToString(value);
-}
+ static std::string op(${interface.cppNamespace()}::${e.name} value)
+ {
+ return ${interface.cppNamespace()}::convert${e.name}ToString(value);
+ }
+};
% endfor
-} // namespace details
-} // namespace message
+} // namespace message::details
} // namespace sdbusplus