Skip to content

Commit 61c8810

Browse files
committed
Serde WIP
Signed-off-by: Alexis Jeandet <[email protected]>
1 parent 4c08d35 commit 61c8810

File tree

10 files changed

+381
-141
lines changed

10 files changed

+381
-141
lines changed

include/cpp_utils/endianness/endianness.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ enum class Endianness
117117
struct big_endian_t
118118
{
119119
};
120+
120121
struct little_endian_t
121122
{
122123
};

include/cpp_utils/reflexion/reflection.hpp

Lines changed: 14 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -40,54 +40,20 @@ struct anything
4040
operator T() const;
4141
};
4242

43-
44-
template <class T, class Is, class = void>
45-
struct _can_construct_with_N : std::false_type
46-
{
47-
};
48-
49-
template <class T, std::size_t... Is>
50-
struct _can_construct_with_N<T, std::index_sequence<Is...>,
51-
std::void_t<decltype(T { (void(Is), anything {})... })>> : std::true_type
52-
{
53-
};
54-
55-
template <class T, std::size_t N>
56-
using can_construct_with_N = _can_construct_with_N<T, std::make_index_sequence<N>>;
57-
58-
59-
template <std::size_t Min, std::size_t Range, template <std::size_t N> class target>
60-
struct maximize
61-
: std::conditional_t<maximize<Min, Range / 2, target> {} == (Min + Range / 2) - 1,
62-
maximize<Min + Range / 2, (Range + 1) / 2, target>, maximize<Min, Range / 2, target>>
63-
{
64-
};
65-
template <std::size_t Min, template <std::size_t N> class target>
66-
struct maximize<Min, 1, target>
67-
: std::conditional_t<target<Min> {}, std::integral_constant<std::size_t, Min>,
68-
std::integral_constant<std::size_t, Min - 1>>
69-
{
70-
};
71-
template <std::size_t Min, template <std::size_t N> class target>
72-
struct maximize<Min, 0, target> : std::integral_constant<std::size_t, Min - 1>
73-
{
74-
};
75-
76-
template <class T>
77-
struct construct_searcher
78-
{
79-
template <std::size_t N>
80-
using result = can_construct_with_N<T, N>;
81-
};
82-
83-
template <class T, std::size_t Cap = 32>
84-
using construct_airity = details::maximize<0, Cap, details::construct_searcher<T>::template result>;
43+
template<typename T, typename... A0>
44+
consteval auto MemberCounter(auto ...c0) {
45+
if constexpr (requires { T{ {A0{}}..., {anything{}}, c0... }; } == false
46+
&& requires { T{ {A0{}}..., c0..., anything{}}; } == false )
47+
return sizeof...(A0) + sizeof...(c0);
48+
else
49+
if constexpr (requires { T{ {A0{}}..., {anything{}}, c0... }; })
50+
return MemberCounter<T,A0...,anything>(c0...);
51+
else
52+
return MemberCounter<T,A0...>(c0...,anything{});
53+
}
8554

8655
}
8756

88-
template <typename T>
89-
inline constexpr std::size_t count_members
90-
= details::construct_airity<std::remove_cv_t<std::remove_reference_t<T>>>::value;
9157

9258
#define SPLIT_FIELDS_FW_DECL(return_type, name, const_struct) \
9359
template <typename T, typename... Args> \
@@ -99,7 +65,7 @@ inline constexpr std::size_t count_members
9965
template <typename T, typename... Args> \
10066
constexpr return_type name(const_struct T& structure, Args&&... args) \
10167
{ \
102-
constexpr std::size_t count = count_members<T>; \
68+
constexpr std::size_t count = cpp_utils::reflexion::count_members<T>; \
10369
static_assert(count <= 31); \
10470
\
10571
if constexpr (count == 1) \
@@ -343,61 +309,7 @@ inline constexpr std::size_t count_members
343309

344310
namespace cpp_utils::reflexion
345311
{
346-
347-
SPLIT_FIELDS_FW_DECL(std::size_t, load_record, );
348-
349-
350-
template <typename field_t>
351-
struct is_field : std::false_type
352-
{
353-
};
354-
355-
template <typename field_t>
356-
inline constexpr bool is_field_v = is_field<field_t>::value;
357-
358-
359-
constexpr inline std::size_t _load_field(const auto& , auto& parsing_context, std::size_t offset, types::concepts::fundamental_type auto&& field)
360-
{
361-
using value_t = std::decay_t<decltype(field)>;
362-
load_value(parsing_context, offset, std::addressof(field), sizeof(value_t));
363-
return offset + sizeof(value_t);
364-
}
365-
366-
367-
template <typename record_t, typename parsing_context_t, typename T>
368-
constexpr inline std::size_t _load_field(const record_t& r, parsing_context_t& parsing_context, std::size_t offset, T&& field)
369-
{
370-
return load_field(r, parsing_context, offset, field);
371-
}
372-
373-
template <typename record_t, typename parsing_context_t, typename T>
374-
constexpr inline std::size_t load_fields(const record_t& r, parsing_context_t& parsing_context,
375-
[[maybe_unused]] std::size_t offset, T&& field)
376-
{
377-
using Field_t = std::remove_cv_t<std::remove_reference_t<T>>;
378-
constexpr std::size_t count = count_members<Field_t>;
379-
if constexpr (std::is_compound_v<Field_t> && (count > 1) && (not is_field_v<Field_t>))
380-
return load_record(field, parsing_context, offset);
381-
else
382-
return _load_field(r, parsing_context, offset, std::forward<T>(field));
383-
}
384-
385-
template <typename record_t, typename parsing_context_t, typename T, typename... Ts>
386-
constexpr inline std::size_t load_fields(const record_t& r, parsing_context_t& parsing_context,
387-
[[maybe_unused]] std::size_t offset, T&& field, Ts&&... fields)
388-
{
389-
offset = load_fields(r, parsing_context, offset, std::forward<T>(field));
390-
return load_fields(r, parsing_context, offset, std::forward<Ts>(fields)...);
391-
}
392-
393-
SPLIT_FIELDS(std::size_t, load_record, load_fields, );
394-
395-
template <typename record_t>
396-
constexpr record_t load_record(auto&& parsing_context, [[maybe_unused]] std::size_t offset)
397-
{
398-
record_t r;
399-
load_record(r, std::forward<decltype(parsing_context)>(parsing_context), offset);
400-
return r;
401-
}
312+
template <typename T>
313+
inline constexpr std::size_t count_members = details::MemberCounter<T>();
402314

403315
} // namespace cpp_utils::reflexion
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*------------------------------------------------------------------------------
2+
-- The MIT License (MIT)
3+
--
4+
-- Copyright © 2024, Laboratory of Plasma Physics- CNRS
5+
--
6+
-- Permission is hereby granted, free of charge, to any person obtaining a copy
7+
-- of this software and associated documentation files (the “Software”), to deal
8+
-- in the Software without restriction, including without limitation the rights
9+
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10+
-- of the Software, and to permit persons to whom the Software is furnished to do
11+
-- so, subject to the following conditions:
12+
--
13+
-- The above copyright notice and this permission notice shall be included in all
14+
-- copies or substantial portions of the Software.
15+
--
16+
-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
17+
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
18+
-- PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19+
-- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20+
-- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21+
-- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
-------------------------------------------------------------------------------*/
23+
/*-- Author : Alexis Jeandet
24+
25+
----------------------------------------------------------------------------*/
26+
#pragma once
27+
#include "../endianness/endianness.hpp"
28+
#include "../reflexion/reflection.hpp"
29+
#include "special_fields.hpp"
30+
31+
namespace cpp_utils::serde
32+
{
33+
34+
SPLIT_FIELDS_FW_DECL(std::size_t, deserialize, );
35+
36+
template <typename input_t, typename field_t, typename parent_composite_t>
37+
std::size_t load_field(const input_t& input, std::size_t offset, field_t& field,
38+
const parent_composite_t& parent_composite);
39+
40+
41+
namespace details
42+
{
43+
44+
std::size_t _load_value_from_memory(const char* const input_address, std::size_t offset,
45+
types::concepts::fundamental_type auto& dest, const auto& parent_composite)
46+
{
47+
using T = std::decay_t<decltype(dest)>;
48+
using parent_composite_t = std::decay_t<decltype(parent_composite)>;
49+
dest = endianness::decode<endianness_t<parent_composite_t>,T>(input_address + offset);
50+
return offset + sizeof(T);
51+
}
52+
}
53+
54+
std::size_t load_value(const char* input, std::size_t offset,
55+
types::concepts::fundamental_type auto& dest, const auto& parent_composite)
56+
{
57+
return details::_load_value_from_memory(input, offset, dest, parent_composite);
58+
}
59+
60+
std::size_t load_value(const types::concepts::contiguous_sequence_container auto& input,
61+
std::size_t offset, types::concepts::fundamental_type auto& dest, const auto& parent_composite)
62+
{
63+
return details::_load_value_from_memory(reinterpret_cast<const char*>(std::data(input)), offset, dest, parent_composite);
64+
}
65+
66+
constexpr inline std::size_t load_field(const auto& parent_composite, auto& parsing_context,
67+
std::size_t offset, types::concepts::fundamental_type auto&& field)
68+
{
69+
return load_value(
70+
parsing_context, offset, std::forward<decltype(field)>(field), parent_composite);
71+
}
72+
73+
constexpr inline std::size_t load_field(const auto&, auto& parsing_context, std::size_t offset,
74+
types::concepts::contiguous_sequence_container auto&& container_field)
75+
{
76+
// return load_value(parsing_context, offset, std::forward<decltype(field)>(field));
77+
return offset;
78+
}
79+
80+
template <typename composite_t, typename parsing_context_t, typename T>
81+
constexpr inline std::size_t load_fields(const composite_t& r, parsing_context_t& parsing_context,
82+
[[maybe_unused]] std::size_t offset, T&& field)
83+
{
84+
using Field_t = std::remove_cv_t<std::remove_reference_t<T>>;
85+
constexpr std::size_t count = reflexion::count_members<Field_t>;
86+
if constexpr (std::is_compound_v<Field_t> && (count > 1) && (not is_field_v<Field_t>))
87+
return deserialize(field, parsing_context, offset);
88+
else
89+
return load_field(r, parsing_context, offset, std::forward<T>(field));
90+
}
91+
92+
template <typename composite_t, typename parsing_context_t, typename T, typename... Ts>
93+
constexpr inline std::size_t load_fields(const composite_t& r, parsing_context_t& parsing_context,
94+
[[maybe_unused]] std::size_t offset, T&& field, Ts&&... fields)
95+
{
96+
offset = load_fields(r, parsing_context, offset, std::forward<T>(field));
97+
return load_fields(r, parsing_context, offset, std::forward<Ts>(fields)...);
98+
}
99+
100+
SPLIT_FIELDS(std::size_t, deserialize, load_fields, );
101+
102+
template <typename composite_t>
103+
constexpr composite_t deserialize(auto&& parsing_context, [[maybe_unused]] std::size_t offset = 0)
104+
{
105+
composite_t r;
106+
deserialize(r, std::forward<decltype(parsing_context)>(parsing_context), offset);
107+
return r;
108+
}
109+
110+
}

include/cpp_utils/serde/serde.hpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*------------------------------------------------------------------------------
2+
-- The MIT License (MIT)
3+
--
4+
-- Copyright © 2024, Laboratory of Plasma Physics- CNRS
5+
--
6+
-- Permission is hereby granted, free of charge, to any person obtaining a copy
7+
-- of this software and associated documentation files (the “Software”), to deal
8+
-- in the Software without restriction, including without limitation the rights
9+
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10+
-- of the Software, and to permit persons to whom the Software is furnished to do
11+
-- so, subject to the following conditions:
12+
--
13+
-- The above copyright notice and this permission notice shall be included in all
14+
-- copies or substantial portions of the Software.
15+
--
16+
-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
17+
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
18+
-- PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19+
-- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20+
-- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21+
-- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
-------------------------------------------------------------------------------*/
23+
/*-- Author : Alexis Jeandet
24+
25+
----------------------------------------------------------------------------*/
26+
#pragma once
27+
#include "special_fields.hpp"
28+
#include "deserialization.hpp"
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*------------------------------------------------------------------------------
2+
-- The MIT License (MIT)
3+
--
4+
-- Copyright © 2024, Laboratory of Plasma Physics- CNRS
5+
--
6+
-- Permission is hereby granted, free of charge, to any person obtaining a copy
7+
-- of this software and associated documentation files (the “Software”), to deal
8+
-- in the Software without restriction, including without limitation the rights
9+
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10+
-- of the Software, and to permit persons to whom the Software is furnished to do
11+
-- so, subject to the following conditions:
12+
--
13+
-- The above copyright notice and this permission notice shall be included in all
14+
-- copies or substantial portions of the Software.
15+
--
16+
-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
17+
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
18+
-- PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19+
-- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20+
-- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21+
-- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
-------------------------------------------------------------------------------*/
23+
/*-- Author : Alexis Jeandet
24+
25+
----------------------------------------------------------------------------*/
26+
#pragma once
27+
#include "../endianness/endianness.hpp"
28+
#include "../reflexion/reflection.hpp"
29+
30+
namespace cpp_utils::serde
31+
{
32+
template <typename field_t>
33+
struct is_field : std::false_type
34+
{
35+
};
36+
37+
template <typename field_t>
38+
inline constexpr bool is_field_v = is_field<field_t>::value;
39+
40+
41+
template <std::size_t size, uint8_t value>
42+
struct padding_bytes_t
43+
{
44+
static constexpr std::size_t padding_size = size;
45+
static constexpr uint8_t padding_value = value;
46+
};
47+
48+
49+
template <typename composite_t>
50+
consteval auto _endianness()
51+
{
52+
if constexpr (requires { typename composite_t::endianness; })
53+
{
54+
return typename composite_t::endianness{};
55+
}
56+
else
57+
{
58+
return endianness::little_endian_t{};
59+
}
60+
}
61+
62+
template <typename composite_t>
63+
using endianness_t = decltype(_endianness<composite_t>());
64+
65+
template <typename composite_t>
66+
inline constexpr bool is_big_endian_v = std::is_same_v<endianness_t<composite_t>,endianness::big_endian_t>;
67+
68+
69+
}

0 commit comments

Comments
 (0)