1<%
2m_name = method.snake_case
3m_tag = method.snake_case + "_t"
4m_param = method.parameters_as_list()
5m_pmove = method.parameters_as_list(lambda p: f"std::move({p.camelCase})")
6m_pargs = method.parameters_as_list(lambda p: method.parameter(interface, p))
7m_ptypes = method.parameter_types_as_list(interface)
8m_return = method.cpp_return_type(interface)
9i_name = interface.classname
10m_param_count = len(method.parameters)
11m_return_count = len(method.returns)
12%>\
13    static int _callback_m_${m_name}(sd_bus_message* msg, void* context,
14                                     sd_bus_error* error [[maybe_unused]])
15        requires (server_details::has_method<
16                            ${m_tag}, Instance\
17% if m_param_count:
18, ${m_ptypes}\
19% endif
20>)
21    {
22        auto self = static_cast<${i_name}*>(context);
23        auto self_i = static_cast<Instance*>(self);
24
25        try
26        {
27            auto m = sdbusplus::message_t{msg};
28% if m_param_count == 1:
29            auto ${m_param} = m.unpack<${m_ptypes}>();
30% elif m_param_count:
31            auto [${m_param}] = m.unpack<${m_ptypes}>();
32% endif
33
34            constexpr auto has_method_msg =
35                server_details::has_method_msg<
36                    ${m_tag}, Instance\
37% if m_param_count:
38, ${m_ptypes}\
39% endif
40>;
41
42            if constexpr (has_method_msg)
43            {
44                constexpr auto is_async = std::is_same_v<
45                    sdbusplus::async::task<${m_return}>,
46                    decltype(self_i->method_call(${m_tag}{}, m\
47% if m_param_count:
48,
49                                ${m_pmove}\
50%endif
51))>;
52
53                if constexpr (!is_async)
54                {
55                    auto r = m.new_method_return();
56% if m_return_count == 0:
57                    \
58% elif m_return_count == 1:
59                    r.append(\
60% else:
61                    std::apply(
62                        [&](auto&&... v) { (r.append(std::move(v)), ...); },
63                        \
64% endif
65self_i->method_call(${m_tag}{}, m\
66% if m_param_count:
67,
68                            ${m_pmove}\
69%endif
70% if m_return_count != 0:
71)\
72% endif
73);
74                    r.method_return();
75                }
76                else
77                {
78                    auto fn = [](auto self, auto self_i,
79                                 sdbusplus::message_t m\
80% if m_param_count:
81,
82                                 ${m_pargs}\
83% endif
84)
85                            -> sdbusplus::async::task<>
86                    {
87                        try
88                        {
89
90                            auto r = m.new_method_return();
91% if m_return_count == 0:
92                            \
93% elif m_return_count == 1:
94                            r.append(\
95% else:
96                            std::apply(
97                                [&](auto&&... v) { (r.append(std::move(v)), ...); },
98                                \
99% endif
100co_await self_i->method_call(
101                                ${m_tag}{}, m\
102% if m_param_count:
103, ${m_pmove}\
104% endif
105% if m_return_count != 0:
106)\
107% endif
108);
109
110                            r.method_return();
111                            co_return;
112                        }
113% for e in method.errors:
114                        catch(const ${interface.errorNamespacedClass(e)}& e)
115                        {
116                            m.new_method_error(e).method_return();
117                            co_return;
118                        }
119                        % endfor
120                        catch(const std::exception&)
121                        {
122                            self->_context().get_bus().set_current_exception(
123                                std::current_exception());
124                            co_return;
125                        }
126                    };
127
128                    self->_context().spawn(
129                        std::move(fn(self, self_i, m\
130% if m_param_count:
131, ${m_pmove}\
132% endif
133)));
134                }
135            }
136            else
137            {
138                constexpr auto is_async [[maybe_unused]] = std::is_same_v<
139                    sdbusplus::async::task<${m_return}>,
140                    decltype(self_i->method_call(${m_tag}{}\
141% if m_param_count:
142,
143                                ${m_pmove}\
144% endif:
145))>;
146
147                if constexpr (!is_async)
148                {
149                    auto r = m.new_method_return();
150% if m_return_count == 0:
151                    \
152% elif m_return_count == 1:
153                    r.append(\
154% else:
155                    std::apply(
156                        [&](auto&&... v) { (r.append(std::move(v)), ...); },
157                        \
158% endif
159self_i->method_call(${m_tag}{}\
160% if m_param_count:
161,
162                            ${m_pmove}\
163%endif
164% if m_return_count != 0:
165)\
166% endif
167);
168                    r.method_return();
169                }
170                else
171                {
172                    auto fn = [](auto self, auto self_i,
173                                 sdbusplus::message_t m\
174% if m_param_count:
175,
176                                 ${m_pargs}\
177% endif
178)
179                            -> sdbusplus::async::task<>
180                    {
181                        try
182                        {
183
184                            auto r = m.new_method_return();
185% if m_return_count == 0:
186                            \
187% elif m_return_count == 1:
188                            r.append(\
189% else:
190                            std::apply(
191                                [&](auto&&... v) { (r.append(std::move(v)), ...); },
192                                \
193% endif
194co_await self_i->method_call(
195                                ${m_tag}{}\
196% if m_param_count:
197, ${m_pmove}\
198% endif
199% if m_return_count != 0:
200)\
201% endif
202);
203
204                            r.method_return();
205                            co_return;
206                        }
207% for e in method.errors:
208                        catch(const ${interface.errorNamespacedClass(e)}& e)
209                        {
210                            m.new_method_error(e).method_return();
211                            co_return;
212                        }
213                        % endfor
214                        catch(const std::exception&)
215                        {
216                            self->_context().get_bus().set_current_exception(
217                                std::current_exception());
218                            co_return;
219                        }
220                    };
221
222                    self->_context().spawn(
223                        std::move(fn(self, self_i, m\
224% if m_param_count:
225, ${m_pmove}\
226% endif
227)));
228                }
229            }
230        }
231% for e in method.errors:
232        catch(const ${interface.errorNamespacedClass(e)}& e)
233        {
234            return e.set_error(error);
235        }
236% endfor
237        catch(const std::exception&)
238        {
239            self->_context().get_bus().set_current_exception(
240                std::current_exception());
241            return -EINVAL;
242        }
243
244        return 1;
245    }
246