11#pragma once
22
3+ #include < log/catalog/arguments.hpp>
34#include < log/catalog/catalog.hpp>
45#include < log/catalog/mipi_messages.hpp>
56
7+ #include < stdx/bit.hpp>
68#include < stdx/compiler.hpp>
79#include < stdx/type_traits.hpp>
810#include < stdx/utility.hpp>
1618
1719namespace logging ::mipi {
1820template <typename T>
19- concept signed_packable = std::signed_integral<stdx:: underlying_type_t <T >> and
20- sizeof (T) <= sizeof (std:: int64_t ) ;
21+ concept packer = std::integral< typename T:: template pack_as_t < int >> and
22+ requires { typename T:: template encode_as_t < int >; } ;
2123
22- template <typename T>
23- concept unsigned_packable =
24- std::unsigned_integral<stdx::underlying_type_t <T>> and
25- sizeof (T) <= sizeof (std::int64_t );
26-
27- template <typename T>
28- concept packable = signed_packable<T> or unsigned_packable<T>;
29-
30- template <typename T> struct encoding ;
31-
32- template <signed_packable T> struct encoding <T> {
33- using encode_t = stdx::conditional_t <sizeof (T) <= sizeof (std::int32_t ),
34- encode_32<T>, encode_64<T>>;
35- using pack_t = stdx::conditional_t <sizeof (T) <= sizeof (std::int32_t ),
36- std::int32_t , std::int64_t >;
37- };
24+ template <typename , packer> struct builder ;
3825
39- template <unsigned_packable T> struct encoding <T> {
40- using encode_t = stdx::conditional_t <sizeof (T) <= sizeof (std::int32_t ),
41- encode_u32<T>, encode_u64<T>>;
42- using pack_t = stdx::conditional_t <sizeof (T) <= sizeof (std::uint32_t ),
43- std::uint32_t , std::uint64_t >;
44- };
45-
46- template <packable T> using pack_as_t = typename encoding<T>::pack_t ;
47- template <packable T> using encode_as_t = typename encoding<T>::encode_t ;
48-
49- template <typename > struct builder ;
50-
51- template <> struct builder <defn::short32_msg_t > {
26+ template <packer P> struct builder <defn::short32_msg_t , P> {
5227 template <auto Level> static auto build (string_id id, module_id) {
5328 using namespace msg ;
5429 return owning<defn::short32_msg_t >{" payload" _field = id};
5530 }
5631};
5732
58- template <typename Storage> struct catalog_builder {
33+ template <typename Storage, packer P > struct catalog_builder {
5934 template <auto Level, packable... Ts>
6035 static auto build (string_id id, module_id m, Ts... args) {
6136 using namespace msg ;
@@ -66,8 +41,16 @@ template <typename Storage> struct catalog_builder {
6641 constexpr auto header_size = defn::catalog_msg_t ::size<V>::value;
6742
6843 auto const pack_arg = []<typename T>(V *p, T arg) -> V * {
69- auto const packed = stdx::to_le (stdx::as_unsigned (
70- static_cast <pack_as_t <T>>(stdx::to_underlying (arg))));
44+ typename P::template pack_as_t <T> converted{};
45+ if constexpr (sizeof (stdx::to_underlying (arg)) ==
46+ sizeof (converted)) {
47+ converted = stdx::bit_cast<decltype (converted)>(
48+ stdx::to_underlying (arg));
49+ } else {
50+ converted =
51+ static_cast <decltype (converted)>(stdx::to_underlying (arg));
52+ }
53+ auto const packed = stdx::to_le (stdx::as_unsigned (converted));
7154 std::memcpy (p, &packed, sizeof (packed));
7255 return p + stdx::sized8{sizeof (packed)}.in <V>();
7356 };
@@ -80,48 +63,49 @@ template <typename Storage> struct catalog_builder {
8063 }
8164};
8265
83- template <> struct builder <defn::catalog_msg_t > {
66+ template <packer P > struct builder <defn::catalog_msg_t , P > {
8467 template <auto Level, typename ... Ts>
8568 static auto build (string_id id, module_id m, Ts... args) {
8669 using namespace msg ;
8770 if constexpr ((0 + ... + sizeof (Ts)) <= sizeof (std::uint32_t ) * 2 ) {
8871 constexpr auto header_size =
8972 defn::catalog_msg_t ::size<std::uint32_t >::value;
9073 constexpr auto payload_size =
91- stdx::sized8{(sizeof (id) + ... + sizeof (pack_as_t <Ts>))}
74+ stdx::sized8{(sizeof (id) + ... +
75+ sizeof (typename P::template pack_as_t <Ts>))}
9276 .in <std::uint32_t >();
9377 using storage_t =
9478 std::array<std::uint32_t , header_size + payload_size>;
95- return catalog_builder<storage_t >{}.template build <Level>(id, m,
96- args...);
79+ return catalog_builder<storage_t , P >{}.template build <Level>(
80+ id, m, args...);
9781 } else {
9882 constexpr auto header_size =
9983 defn::catalog_msg_t ::size<std::uint8_t >::value;
10084 constexpr auto payload_size =
101- (sizeof (id) + ... + sizeof (pack_as_t <Ts>));
85+ (sizeof (id) + ... + sizeof (typename P:: template pack_as_t <Ts>));
10286 using storage_t =
10387 std::array<std::uint8_t , header_size + payload_size>;
104- return catalog_builder<storage_t >{}.template build <Level>(id, m,
105- args...);
88+ return catalog_builder<storage_t , P >{}.template build <Level>(
89+ id, m, args...);
10690 }
10791 }
10892};
10993
110- template <> struct builder <defn::compact32_build_msg_t > {
94+ template <packer P > struct builder <defn::compact32_build_msg_t , P > {
11195 template <auto Version> static auto build () {
11296 using namespace msg ;
11397 return owning<defn::compact32_build_msg_t >{" build_id" _field = Version};
11498 }
11599};
116100
117- template <> struct builder <defn::compact64_build_msg_t > {
101+ template <packer P > struct builder <defn::compact64_build_msg_t , P > {
118102 template <auto Version> static auto build () {
119103 using namespace msg ;
120104 return owning<defn::compact64_build_msg_t >{" build_id" _field = Version};
121105 }
122106};
123107
124- template <> struct builder <defn::normal_build_msg_t > {
108+ template <packer P > struct builder <defn::normal_build_msg_t , P > {
125109 template <auto Version, stdx::ct_string S> static auto build () {
126110 using namespace msg ;
127111 constexpr auto header_size =
@@ -141,32 +125,33 @@ template <> struct builder<defn::normal_build_msg_t> {
141125 }
142126};
143127
144- struct default_builder {
128+ template <packer P = logging::default_arg_packer> struct default_builder {
145129 template <auto Level, packable... Ts>
146130 static auto build (string_id id, module_id m, Ts... args) {
147131 if constexpr (sizeof ...(Ts) == 0u ) {
148- return builder<defn::short32_msg_t >{}.template build <Level>(id, m);
132+ return builder<defn::short32_msg_t , P>{}.template build <Level>(id,
133+ m);
149134 } else {
150- return builder<defn::catalog_msg_t >{}.template build <Level>(
135+ return builder<defn::catalog_msg_t , P >{}.template build <Level>(
151136 id, m, args...);
152137 }
153138 }
154139
155140 template <auto Version, stdx::ct_string S = " " > auto build_version () {
156141 using namespace msg ;
157142 if constexpr (S.empty () and stdx::bit_width (Version) <= 22 ) {
158- return builder<defn::compact32_build_msg_t >{}
143+ return builder<defn::compact32_build_msg_t , P >{}
159144 .template build <Version>();
160145 } else if constexpr (S.empty () and stdx::bit_width (Version) <= 54 ) {
161- return builder<defn::compact64_build_msg_t >{}
146+ return builder<defn::compact64_build_msg_t , P >{}
162147 .template build <Version>();
163148 } else {
164- return builder<defn::normal_build_msg_t >{}
149+ return builder<defn::normal_build_msg_t , P >{}
165150 .template build <Version, S>();
166151 }
167152 }
168153
169154 template <template <typename ...> typename F, typename ... Args>
170- using convert_args = F<encode_as_t <Args>...>;
155+ using convert_args = F<typename P:: template encode_as_t <Args>...>;
171156};
172157} // namespace logging::mipi
0 commit comments