From 037960d8b337725e9af605ef6ba3d411bcec971b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= Date: Tue, 13 May 2025 11:10:16 +0200 Subject: [PATCH] libcamera: ipa_data_serializer: Add specialization for enums MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of handling enums specially in the code generation templates, create a specialization of `IPADataSerializer` that handles enums. Every enum is serialized as a `uint32_t`, with `static_assert` to ensure that every possible value fits. Previously, enums were (de)serialized in `(de)serializer_field()` based on the size of their underlying types. Afer this change, every enum is uniformly handled as a `uint32_t`. Signed-off-by: Barnabás Pőcze Reviewed-by: Paul Elder Reviewed-by: Jacopo Mondi --- .../libcamera/internal/ipa_data_serializer.h | 48 ++++++++++++++++++- .../libcamera_templates/proxy_functions.tmpl | 17 +------ .../libcamera_templates/serializer.tmpl | 14 ------ 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/include/libcamera/internal/ipa_data_serializer.h b/include/libcamera/internal/ipa_data_serializer.h index b1fefba5..927f5c4c 100644 --- a/include/libcamera/internal/ipa_data_serializer.h +++ b/include/libcamera/internal/ipa_data_serializer.h @@ -61,7 +61,7 @@ T readPOD(std::vector &vec, size_t pos) } /* namespace */ -template +template class IPADataSerializer { public: @@ -344,6 +344,52 @@ public: } }; +template +class IPADataSerializer>> +{ + using U = uint32_t; + static_assert(sizeof(E) <= sizeof(U)); + +public: + static std::tuple, std::vector> + serialize(const E &data, [[maybe_unused]] ControlSerializer *cs = nullptr) + { + std::vector dataVec; + appendPOD(dataVec, static_cast(data)); + + return { dataVec, {} }; + } + + static E deserialize(std::vector &data, + [[maybe_unused]] ControlSerializer *cs = nullptr) + { + return deserialize(data.cbegin(), data.cend()); + } + + static E deserialize(std::vector::const_iterator dataBegin, + std::vector::const_iterator dataEnd, + [[maybe_unused]] ControlSerializer *cs = nullptr) + { + return static_cast(readPOD(dataBegin, 0, dataEnd)); + } + + static E deserialize(std::vector &data, + [[maybe_unused]] std::vector &fds, + [[maybe_unused]] ControlSerializer *cs = nullptr) + { + return deserialize(data.cbegin(), data.cend()); + } + + static E deserialize(std::vector::const_iterator dataBegin, + std::vector::const_iterator dataEnd, + [[maybe_unused]] std::vector::const_iterator fdsBegin, + [[maybe_unused]] std::vector::const_iterator fdsEnd, + [[maybe_unused]] ControlSerializer *cs = nullptr) + { + return deserialize(dataBegin, dataEnd); + } +}; + #endif /* __DOXYGEN__ */ } /* namespace libcamera */ diff --git a/utils/codegen/ipc/generators/libcamera_templates/proxy_functions.tmpl b/utils/codegen/ipc/generators/libcamera_templates/proxy_functions.tmpl index 25476990..01e2567c 100644 --- a/utils/codegen/ipc/generators/libcamera_templates/proxy_functions.tmpl +++ b/utils/codegen/ipc/generators/libcamera_templates/proxy_functions.tmpl @@ -52,9 +52,6 @@ #} {%- macro serialize_call(params, buf, fds) %} {%- for param in params %} -{%- if param|is_enum %} - static_assert(sizeof({{param|name_full}}) <= 4); -{%- endif %} std::vector {{param.mojom_name}}Buf; {%- if param|has_fd %} std::vector {{param.mojom_name}}Fds; @@ -62,13 +59,7 @@ {%- else %} std::tie({{param.mojom_name}}Buf, std::ignore) = {%- endif %} -{%- if param|is_flags %} IPADataSerializer<{{param|name_full}}>::serialize({{param.mojom_name}} -{%- elif param|is_enum %} - IPADataSerializer::serialize(static_cast({{param.mojom_name}}) -{%- else %} - IPADataSerializer<{{param|name}}>::serialize({{param.mojom_name}} -{% endif -%} {{- ", &controlSerializer_" if param|needs_control_serializer -}} ); {%- endfor %} @@ -107,13 +98,7 @@ #} {%- macro deserialize_param(param, pointer, loop, buf, fds, iter, data_size) -%} {{"*" if pointer}}{{param.mojom_name}} = -{%- if param|is_flags %} IPADataSerializer<{{param|name_full}}>::deserialize( -{%- elif param|is_enum %} -static_cast<{{param|name_full}}>(IPADataSerializer::deserialize( -{%- else %} -IPADataSerializer<{{param|name}}>::deserialize( -{%- endif %} {{buf}}{{- ".cbegin()" if not iter}} + {{param.mojom_name}}Start, {%- if loop.last and not iter %} {{buf}}.cend() @@ -137,7 +122,7 @@ IPADataSerializer<{{param|name}}>::deserialize( {%- if param|needs_control_serializer %} &controlSerializer_ {%- endif -%} -){{")" if param|is_enum and not param|is_flags}}; +); {%- endmacro -%} diff --git a/utils/codegen/ipc/generators/libcamera_templates/serializer.tmpl b/utils/codegen/ipc/generators/libcamera_templates/serializer.tmpl index d07836cc..e316dd88 100644 --- a/utils/codegen/ipc/generators/libcamera_templates/serializer.tmpl +++ b/utils/codegen/ipc/generators/libcamera_templates/serializer.tmpl @@ -32,15 +32,7 @@ {%- if field|is_pod or field|is_enum %} std::vector {{field.mojom_name}}; std::tie({{field.mojom_name}}, std::ignore) = - {%- if field|is_pod %} - IPADataSerializer<{{field|name}}>::serialize(data.{{field.mojom_name}}); - {%- elif field|is_flags %} IPADataSerializer<{{field|name_full}}>::serialize(data.{{field.mojom_name}}); - {%- elif field|is_enum_scoped %} - IPADataSerializer::serialize(static_cast(data.{{field.mojom_name}})); - {%- elif field|is_enum %} - IPADataSerializer::serialize(data.{{field.mojom_name}}); - {%- endif %} retData.insert(retData.end(), {{field.mojom_name}}.begin(), {{field.mojom_name}}.end()); {%- elif field|is_fd %} std::vector {{field.mojom_name}}; @@ -98,13 +90,7 @@ {% if field|is_pod or field|is_enum %} {%- set field_size = (field|bit_width|int / 8)|int %} {{- check_data_size(field_size, 'dataSize', field.mojom_name, 'data')}} - {%- if field|is_pod %} - ret.{{field.mojom_name}} = IPADataSerializer<{{field|name}}>::deserialize(m, m + {{field_size}}); - {%- elif field|is_flags %} ret.{{field.mojom_name}} = IPADataSerializer<{{field|name_full}}>::deserialize(m, m + {{field_size}}); - {%- else %} - ret.{{field.mojom_name}} = static_cast<{{field|name_full}}>(IPADataSerializer::deserialize(m, m + {{field_size}})); - {%- endif %} {%- if not loop.last %} m += {{field_size}}; dataSize -= {{field_size}};