xref: /openbmc/sdbusplus/tools/sdbusplus/templates/interface.common.hpp.mako (revision 6bb7a8c9a34d805a624b9679b171e11a6d106f09)
1#pragma once
2#include <algorithm>
3#include <array>
4#include <optional>
5#include <string>
6#include <string_view>
7#include <tuple>
8
9#include <sdbusplus/exception.hpp>
10#include <sdbusplus/message.hpp>
11#include <sdbusplus/utility/dedup_variant.hpp>
12<%
13    def setOfPropertyTypes():
14        return set(p.cppTypeParam(interface.name) for p in
15                   interface.properties);
16%>\
17
18namespace sdbusplus::common::${interface.cppNamespace()}
19{
20
21struct ${interface.classname}
22{
23    static constexpr auto interface = "${interface.name}";
24
25    % for e in interface.enums:
26    enum class ${e.name}
27    {
28        % for v in e.values:
29        ${v.name},
30        % endfor
31    };
32    % endfor
33
34    % if interface.properties:
35    struct properties_t
36    {
37        % for p in interface.properties:
38        ${p.cppTypeParam(interface.name)} ${p.snake_case}${p.default_value(interface.name)};
39        % endfor
40    };
41
42    using PropertiesVariant = sdbusplus::utility::dedup_variant_t<
43        ${",\n        ".join(sorted(setOfPropertyTypes()))}>;
44    % endif \
45
46    % for p in interface.paths:
47        % if p.description:
48    /** ${p.description.strip()} */
49        % endif
50        % if len(p.segments) == 0:
51    static constexpr auto ${p.snake_case} = "${p.value}";
52        % else:
53    struct ${p.snake_case}
54    {
55        static constexpr auto value = "${p.value}";
56            % for s in p.segments:
57                % if s.description:
58        /** ${s.description.strip()} */
59                % endif
60        static constexpr auto ${s.snake_case} = "${s.value}";
61            % endfor
62    };
63        % endif
64    % endfor
65    % for s in interface.service_names:
66        % if s.description:
67    /** ${s.description.strip()} */
68        % endif
69    static constexpr auto ${s.snake_case} = "${s.value}";
70    % endfor
71
72    % for e in interface.enums:
73    /** @brief Convert a string to an appropriate enum value.
74     *  @param[in] s - The string to convert in the form of
75     *                 "${interface.name}.<value name>"
76     *  @return - The enum value.
77     *
78     *  @note Throws if string is not a valid mapping.
79     */
80    static ${e.name} convert${e.name}FromString(const std::string& s);
81
82    /** @brief Convert a string to an appropriate enum value.
83     *  @param[in] s - The string to convert in the form of
84     *                 "${interface.name}.<value name>"
85     *  @return - The enum value or std::nullopt
86     */
87    static std::optional<${e.name}>
88        convertStringTo${e.name}(const std::string& s) noexcept;
89
90    /** @brief Convert an enum value to a string.
91     *  @param[in] e - The enum to convert to a string.
92     *  @return - The string conversion in the form of
93     *            "${interface.name}.<value name>"
94     */
95    static std::string convert${e.name}ToString(${e.name} e);
96    % endfor
97};
98
99% for e in interface.enums:
100/* Specialization of sdbusplus::common::convertForMessage
101 * for enum-type ${interface.classname}::${e.name}.
102 *
103 * This converts from the enum to a constant string representing the enum.
104 *
105 * @param[in] e - Enum value to convert.
106 * @return string representing the name for the enum value.
107 */
108inline std::string convertForMessage(${interface.classname}::${e.name} e)
109{
110    return ${interface.classname}::convert${e.name}ToString(e);
111}
112% endfor
113
114    % for e in interface.enums:
115
116namespace details
117{
118using namespace std::literals::string_view_literals;
119
120/** String to enum mapping for ${interface.classname}::${e.name} */
121inline constexpr std::array mapping${interface.classname}${e.name} = {
122    % for v in e.values:
123    std::make_tuple("${interface.name}.${e.name}.${v.name}"sv,
124                    ${interface.classname}::${e.name}::${v.name} ),
125    % endfor
126};
127} //  namespace details
128
129inline auto ${interface.classname}::convertStringTo${e.name}(const std::string& s) noexcept
130    -> std::optional<${e.name}>
131{
132    auto i = std::find_if(std::begin(details::mapping${interface.classname}${e.name}),
133                          std::end(details::mapping${interface.classname}${e.name}),
134                          [&s](auto& e){ return s == std::get<0>(e); } );
135
136    if (std::end(details::mapping${interface.classname}${e.name}) == i)
137    {
138        return std::nullopt;
139    }
140    else
141    {
142        return std::get<1>(*i);
143    }
144}
145
146inline auto ${interface.classname}::convert${e.name}FromString(const std::string& s) -> ${e.name}
147{
148    auto r = convertStringTo${e.name}(s);
149
150    if (!r)
151    {
152        throw sdbusplus::exception::InvalidEnumString();
153    }
154    else
155    {
156        return *r;
157    }
158}
159
160inline std::string ${interface.classname}::convert${e.name}ToString(
161    ${interface.classname}::${e.name} v)
162{
163    auto i = std::find_if(std::begin(details::mapping${interface.classname}${e.name}),
164                          std::end(details::mapping${interface.classname}${e.name}),
165                          [v](auto& e){ return v == std::get<1>(e); });
166
167    if (i == std::end(details::mapping${interface.classname}${e.name}))
168    {
169        throw std::invalid_argument(std::to_string(static_cast<int>(v)));
170    }
171    return std::string(std::get<0>(*i));
172}
173    % endfor
174
175} // sdbusplus::common::${interface.cppNamespace()}
176
177namespace sdbusplus::message::details
178{
179    % for e in interface.enums:
180template <>
181struct convert_from_string<common::${interface.cppNamespacedClass()}::${e.name}>
182{
183    static auto op(const std::string& value) noexcept
184    {
185        return common::${interface.cppNamespacedClass()}::
186            convertStringTo${e.name}(value);
187    }
188};
189
190template <>
191struct convert_to_string<common::${interface.cppNamespacedClass()}::${e.name}>
192{
193    static std::string
194        op(common::${interface.cppNamespacedClass()}::${e.name} value)
195    {
196        return common::${interface.cppNamespacedClass()}::
197            convert${e.name}ToString(value);
198    }
199};
200    % endfor
201} // namespace sdbusplus::message::details
202